@spfn/core 0.1.0-alpha.81 → 0.1.0-alpha.82
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/dist/cache/index.js +26 -5
- package/dist/cache/index.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/codegen/generators/index.js +26 -5
- package/dist/codegen/generators/index.js.map +1 -1
- package/dist/codegen/index.d.ts +2 -2
- package/dist/codegen/index.js +26 -5
- package/dist/codegen/index.js.map +1 -1
- package/dist/db/index.js +26 -5
- package/dist/db/index.js.map +1 -1
- package/dist/env/index.js +26 -5
- package/dist/env/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +26 -5
- package/dist/index.js.map +1 -1
- package/dist/logger/index.js +26 -5
- package/dist/logger/index.js.map +1 -1
- package/dist/middleware/index.d.ts +29 -2
- package/dist/middleware/index.js +26 -5
- package/dist/middleware/index.js.map +1 -1
- package/dist/route/index.d.ts +3 -3
- package/dist/route/index.js +26 -5
- package/dist/route/index.js.map +1 -1
- package/dist/server/index.js +26 -5
- package/dist/server/index.js.map +1 -1
- package/dist/{types-DYueuoD6.d.ts → types/index.d.ts} +19 -60
- package/dist/types/index.js +38 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types-BXibIEyj.d.ts +60 -0
- package/package.json +9 -3
- package/dist/error-handler-wjLL3v-a.d.ts +0 -44
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/logger/adapters/pino.ts","../../src/logger/types.ts","../../src/logger/formatters.ts","../../src/logger/logger.ts","../../src/logger/transports/console.ts","../../src/logger/transports/file.ts","../../src/logger/config.ts","../../src/logger/adapters/custom.ts","../../src/logger/adapter-factory.ts","../../src/codegen/core/orchestrator.ts","../../src/codegen/built-in/contract/scanner.ts","../../src/codegen/built-in/contract/helpers.ts","../../src/codegen/built-in/contract/emitter.ts","../../src/codegen/built-in/contract/index.ts","../../src/codegen/core/config-loader.ts"],"names":["newPath","existsSync","mkdirSync","join","unlinkSync","chokidarWatch","capitalize","readFileSync"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Pino Logger Adapter\n *\n * High-performance logger adapter using Pino with pretty-print for development and JSON for production.\n */\n\nimport pino from 'pino';\nimport type { LoggerAdapter, AdapterConfig, LogLevel } from './types';\n\n/**\n * Pino Logger Adapter\n */\nexport class PinoAdapter implements LoggerAdapter\n{\n private logger: pino.Logger;\n\n constructor(config: AdapterConfig)\n {\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n // Development: use simple console output without transport\n // Production: use JSON output\n this.logger = pino({\n level: config.level,\n\n // 기본 필드\n base: config.module ? { module: config.module } : undefined,\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const childLogger = new PinoAdapter({ level: this.logger.level as LogLevel, module });\n childLogger.logger = this.logger.child({ module });\n return childLogger;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(context || {}, message);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(context || {}, message);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.warn(errorOrContext || {}, message);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.error(errorOrContext || {}, message);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.fatal(errorOrContext || {}, message);\n }\n }\n\n async close(): Promise<void>\n {\n // Pino는 자동으로 flush됨\n // 필요시 pino.final() 사용 가능\n }\n}","/**\n * Logger Type Definitions\n *\n * 로깅 시스템 타입 정의\n *\n * ✅ 구현 완료:\n * - LogLevel 타입 정의\n * - LogMetadata 인터페이스\n * - Transport 인터페이스\n * - 환경별 설정 타입\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현체)\n * - src/logger/config.ts (설정)\n */\n\n/**\n * 로그 레벨\n * debug < info < warn < error < fatal\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * 로그 레벨 우선순위\n */\nexport const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n fatal: 4,\n};\n\n/**\n * 로그 메타데이터\n */\nexport interface LogMetadata\n{\n timestamp: Date;\n level: LogLevel;\n message: string;\n module?: string;\n error?: Error;\n context?: Record<string, unknown>;\n}\n\n/**\n * Transport 인터페이스\n * 모든 Transport는 이 인터페이스를 구현해야 함\n */\nexport interface Transport\n{\n /**\n * Transport 이름\n */\n name: string;\n\n /**\n * 최소 로그 레벨 (이 레벨 이상만 처리)\n */\n level: LogLevel;\n\n /**\n * 활성화 여부\n */\n enabled: boolean;\n\n /**\n * 로그 처리 함수\n */\n log(metadata: LogMetadata): Promise<void>;\n\n /**\n * Transport 종료 (리소스 정리)\n */\n close?(): Promise<void>;\n}\n\n/**\n * Logger 설정\n */\nexport interface LoggerConfig\n{\n /**\n * 기본 로그 레벨\n */\n level: LogLevel;\n\n /**\n * 모듈명 (context)\n */\n module?: string;\n\n /**\n * Transport 리스트\n */\n transports: Transport[];\n}\n\n/**\n * Transport 설정 (공통)\n */\nexport interface TransportConfig\n{\n level: LogLevel;\n enabled: boolean;\n}\n\n/**\n * Console Transport 설정\n */\nexport interface ConsoleTransportConfig extends TransportConfig\n{\n colorize?: boolean;\n}\n\n/**\n * File Transport 설정\n */\nexport interface FileTransportConfig extends TransportConfig\n{\n logDir: string;\n maxFileSize?: number; // bytes\n maxFiles?: number; // 최대 로그 파일 개수\n}\n\n/**\n * Slack Transport 설정\n */\nexport interface SlackTransportConfig extends TransportConfig\n{\n webhookUrl: string;\n channel?: string;\n username?: string;\n}\n\n/**\n * Email Transport 설정\n */\nexport interface EmailTransportConfig extends TransportConfig\n{\n from: string;\n to: string[];\n smtpHost: string;\n smtpPort: number;\n smtpUser?: string;\n smtpPassword?: string;\n}","/**\n * Logger Formatters\n *\n * Log formatting utilities for console, JSON, Slack, and Email outputs with sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata } from './types';\n\n/**\n * 민감 정보로 간주되는 키 목록\n * 이 키들을 포함하는 필드는 자동으로 마스킹됨\n */\nconst SENSITIVE_KEYS = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'accesstoken',\n 'access_token',\n 'refreshtoken',\n 'refresh_token',\n 'authorization',\n 'auth',\n 'cookie',\n 'session',\n 'sessionid',\n 'session_id',\n 'privatekey',\n 'private_key',\n 'creditcard',\n 'credit_card',\n 'cardnumber',\n 'card_number',\n 'cvv',\n 'ssn',\n 'pin',\n];\n\n/**\n * 마스킹된 값\n */\nconst MASKED_VALUE = '***MASKED***';\n\n/**\n * 키가 민감 정보를 포함하는지 확인\n */\nfunction isSensitiveKey(key: string): boolean\n{\n const lowerKey = key.toLowerCase();\n return SENSITIVE_KEYS.some(sensitive => lowerKey.includes(sensitive));\n}\n\n/**\n * 민감 정보 마스킹\n * Context 객체에서 민감한 정보(비밀번호, 토큰 등)를 마스킹\n *\n * @param data - 원본 데이터\n * @returns 마스킹된 데이터\n */\nexport function maskSensitiveData(data: unknown): unknown\n{\n // null, undefined 처리\n if (data === null || data === undefined)\n {\n return data;\n }\n\n // 배열 처리\n if (Array.isArray(data))\n {\n return data.map(item => maskSensitiveData(item));\n }\n\n // 객체 처리\n if (typeof data === 'object')\n {\n const masked: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data))\n {\n if (isSensitiveKey(key))\n {\n // 민감 정보 키는 마스킹\n masked[key] = MASKED_VALUE;\n }\n else if (typeof value === 'object' && value !== null)\n {\n // 중첩된 객체는 재귀 처리\n masked[key] = maskSensitiveData(value);\n }\n else\n {\n // 일반 값은 그대로 유지\n masked[key] = value;\n }\n }\n\n return masked;\n }\n\n // 기본 타입은 그대로 반환\n return data;\n}\n\n/**\n * ANSI 컬러 코드\n */\nconst COLORS = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n\n // 로그 레벨 컬러\n debug: '\\x1b[36m', // cyan\n info: '\\x1b[32m', // green\n warn: '\\x1b[33m', // yellow\n error: '\\x1b[31m', // red\n fatal: '\\x1b[35m', // magenta\n\n // 추가 컬러\n gray: '\\x1b[90m',\n};\n\n/**\n * 로그 레벨을 컬러 문자열로 변환\n */\nexport function colorizeLevel(level: LogLevel): string\n{\n const color = COLORS[level];\n const levelStr = level.toUpperCase().padEnd(5);\n return `${color}${levelStr}${COLORS.reset}`;\n}\n\n/**\n * 타임스탬프 포맷 (ISO 8601)\n */\nexport function formatTimestamp(date: Date): string\n{\n return date.toISOString();\n}\n\n/**\n * 타임스탬프 포맷 (사람이 읽기 쉬운 형식)\n */\nexport function formatTimestampHuman(date: Date): string\n{\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n const seconds = String(date.getSeconds()).padStart(2, '0');\n const ms = String(date.getMilliseconds()).padStart(3, '0');\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`;\n}\n\n/**\n * 에러 객체를 문자열로 변환 (스택 트레이스 포함)\n */\nexport function formatError(error: Error): string\n{\n const lines: string[] = [];\n\n lines.push(`${error.name}: ${error.message}`);\n\n if (error.stack)\n {\n const stackLines = error.stack.split('\\n').slice(1);\n lines.push(...stackLines);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Context 객체를 문자열로 변환\n */\nexport function formatContext(context: Record<string, unknown>): string\n{\n try\n {\n return JSON.stringify(context, null, 2);\n }\n catch (error)\n {\n return '[Context serialization failed]';\n }\n}\n\n/**\n * 콘솔용 컬러 포맷\n */\nexport function formatConsole(metadata: LogMetadata, colorize = true): string\n{\n const parts: string[] = [];\n\n // [타임스탬프]\n const timestamp = formatTimestampHuman(metadata.timestamp);\n if (colorize)\n {\n parts.push(`${COLORS.gray}[${timestamp}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${timestamp}]`);\n }\n\n // [module=value]\n if (metadata.module)\n {\n if (colorize)\n {\n parts.push(`${COLORS.dim}[module=${metadata.module}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[module=${metadata.module}]`);\n }\n }\n\n // Context를 각각 [key=value] 형태로 추가\n if (metadata.context && Object.keys(metadata.context).length > 0)\n {\n Object.entries(metadata.context).forEach(([key, value]) =>\n {\n const valueStr = typeof value === 'string' ? value : String(value);\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Slack 메시지 포맷\n */\nexport function formatSlack(metadata: LogMetadata): string\n{\n const emoji = {\n debug: ':bug:',\n info: ':information_source:',\n warn: ':warning:',\n error: ':x:',\n fatal: ':fire:',\n };\n\n const parts: string[] = [];\n\n parts.push(`${emoji[metadata.level]} *${metadata.level.toUpperCase()}*`);\n\n if (metadata.module)\n {\n parts.push(`\\`[${metadata.module}]\\``);\n }\n\n parts.push(metadata.message);\n\n let message = parts.join(' ');\n\n if (metadata.context)\n {\n message += '\\n```\\n' + JSON.stringify(metadata.context, null, 2) + '\\n```';\n }\n\n if (metadata.error)\n {\n message += '\\n```\\n' + formatError(metadata.error) + '\\n```';\n }\n\n return message;\n}\n\n/**\n * Email 제목 생성\n */\nexport function formatEmailSubject(metadata: LogMetadata): string\n{\n const prefix = `[${metadata.level.toUpperCase()}]`;\n const module = metadata.module ? `[${metadata.module}]` : '';\n\n return `${prefix}${module} ${metadata.message}`;\n}\n\n/**\n * Email 본문 생성 (HTML)\n */\nexport function formatEmailBody(metadata: LogMetadata): string\n{\n const parts: string[] = [];\n\n parts.push('<html>');\n parts.push('<body style=\"font-family: monospace; padding: 20px;\">');\n\n // 헤더\n parts.push(`<h2 style=\"color: ${getEmailColor(metadata.level)};\">`);\n parts.push(`${metadata.level.toUpperCase()}`);\n parts.push('</h2>');\n\n // 시간\n parts.push('<p>');\n parts.push(`<strong>Timestamp:</strong> ${formatTimestamp(metadata.timestamp)}`);\n parts.push('</p>');\n\n // 모듈\n if (metadata.module)\n {\n parts.push('<p>');\n parts.push(`<strong>Module:</strong> ${metadata.module}`);\n parts.push('</p>');\n }\n\n // 메시지\n parts.push('<p>');\n parts.push(`<strong>Message:</strong> ${metadata.message}`);\n parts.push('</p>');\n\n // Context\n if (metadata.context)\n {\n parts.push('<h3>Context</h3>');\n parts.push('<pre style=\"background: #f4f4f4; padding: 10px; border-radius: 4px;\">');\n parts.push(JSON.stringify(metadata.context, null, 2));\n parts.push('</pre>');\n }\n\n // 에러\n if (metadata.error)\n {\n parts.push('<h3>Error Stack Trace</h3>');\n parts.push('<pre style=\"background: #fff0f0; padding: 10px; border-radius: 4px;\">');\n parts.push(formatError(metadata.error));\n parts.push('</pre>');\n }\n\n parts.push('</body>');\n parts.push('</html>');\n\n return parts.join('\\n');\n}\n\n/**\n * Email 레벨별 컬러\n */\nfunction getEmailColor(level: LogLevel): string\n{\n const colors: Record<LogLevel, string> = {\n debug: '#00BCD4',\n info: '#4CAF50',\n warn: '#FF9800',\n error: '#F44336',\n fatal: '#9C27B0',\n };\n\n return colors[level];\n}","/**\n * Logger Class\n *\n * Central logging class with multiple transports, child loggers, and sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata, LoggerConfig, Transport } from './types';\nimport { LOG_LEVEL_PRIORITY } from './types';\nimport { maskSensitiveData } from './formatters';\n\n/**\n * Logger class\n */\nexport class Logger\n{\n private readonly config: LoggerConfig;\n private readonly module?: string;\n\n constructor(config: LoggerConfig)\n {\n this.config = config;\n this.module = config.module;\n }\n\n /**\n * Get current log level\n */\n get level(): LogLevel\n {\n return this.config.level;\n }\n\n /**\n * Create child logger (per module)\n */\n child(module: string): Logger\n {\n return new Logger({\n ...this.config,\n module,\n });\n }\n\n /**\n * Debug log\n */\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.log('debug', message, undefined, context);\n }\n\n /**\n * Info log\n */\n info(message: string, context?: Record<string, unknown>): void\n {\n this.log('info', message, undefined, context);\n }\n\n /**\n * Warn log\n */\n warn(message: string, context?: Record<string, unknown>): void;\n warn(message: string, error: Error, context?: Record<string, unknown>): void;\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('warn', message, errorOrContext, context);\n }\n else\n {\n this.log('warn', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Error log\n */\n error(message: string, context?: Record<string, unknown>): void;\n error(message: string, error: Error, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('error', message, errorOrContext, context);\n }\n else\n {\n this.log('error', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Fatal log\n */\n fatal(message: string, context?: Record<string, unknown>): void;\n fatal(message: string, error: Error, context?: Record<string, unknown>): void;\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('fatal', message, errorOrContext, context);\n }\n else\n {\n this.log('fatal', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Log processing (internal)\n */\n private log(level: LogLevel, message: string, error?: Error, context?: Record<string, unknown>): void\n {\n // Early return if log level is below configured level\n // This prevents unnecessary metadata creation and processing\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level])\n {\n return;\n }\n\n const metadata: LogMetadata = {\n timestamp: new Date(),\n level,\n message,\n module: this.module,\n error,\n // Mask sensitive information in context to prevent credential leaks\n context: context ? maskSensitiveData(context) as Record<string, unknown> : undefined,\n };\n\n // Pass to all enabled Transports\n this.processTransports(metadata);\n }\n\n /**\n * Process Transports\n */\n private processTransports(metadata: LogMetadata): void\n {\n const promises = this.config.transports\n .filter(transport => transport.enabled)\n .map(transport => this.safeTransportLog(transport, metadata));\n\n // Async processing to prevent Transport errors from blocking logs\n Promise.all(promises).catch(error =>\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport error: ${errorMessage}\\n`);\n });\n }\n\n /**\n * Transport log (error-safe)\n */\n private async safeTransportLog(transport: Transport, metadata: LogMetadata): Promise<void>\n {\n try\n {\n await transport.log(metadata);\n }\n catch (error)\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport \"${transport.name}\" failed: ${errorMessage}\\n`);\n }\n }\n\n /**\n * Close all Transports\n */\n async close(): Promise<void>\n {\n const closePromises = this.config.transports\n .filter(transport => transport.close)\n .map(transport => transport.close!());\n\n await Promise.all(closePromises);\n }\n}","/**\n * Console Transport\n *\n * 콘솔 출력 Transport\n *\n * ✅ 구현 완료:\n * - 콘솔 출력 (stdout/stderr)\n * - 컬러 출력 지원\n * - 로그 레벨별 스트림 분리 (warn/error/fatal → stderr)\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (Transport 인터페이스)\n * - src/logger/formatters.ts (포맷터)\n * - src/logger/config.ts (설정)\n */\n\nimport type { Transport, LogMetadata, LogLevel, ConsoleTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatConsole } from '../formatters';\n\n/**\n * Console Transport\n */\nexport class ConsoleTransport implements Transport\n{\n public readonly name = 'console';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private colorize: boolean;\n\n constructor(config: ConsoleTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.colorize = config.colorize ?? true;\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // 포맷팅\n const message = formatConsole(metadata, this.colorize);\n\n // warn/error/fatal은 stderr로, 나머지는 stdout으로\n if (metadata.level === 'warn' || metadata.level === 'error' || metadata.level === 'fatal')\n {\n console.error(message);\n }\n else\n {\n console.log(message);\n }\n }\n}","/**\n * File Transport\n *\n * File output transport with date and size-based rotation, automatic cleanup.\n */\n\nimport { createWriteStream, existsSync, mkdirSync, statSync, readdirSync, unlinkSync, renameSync } from 'fs';\nimport type { WriteStream } from 'fs';\nimport { join } from 'path';\nimport type { Transport, LogMetadata, LogLevel, FileTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatJSON } from '../formatters';\n\n/**\n * File Transport\n */\nexport class FileTransport implements Transport\n{\n public readonly name = 'file';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private readonly logDir: string;\n private readonly maxFileSize: number;\n private readonly maxFiles: number;\n private currentStream: WriteStream | null = null;\n private currentFilename: string | null = null;\n\n constructor(config: FileTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.logDir = config.logDir;\n this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024; // 10MB\n this.maxFiles = config.maxFiles ?? 10;\n\n // 로그 디렉토리가 없으면 생성\n if (!existsSync(this.logDir))\n {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // JSON 포맷으로 변환\n const message = formatJSON(metadata);\n\n // 파일명: YYYY-MM-DD.log\n const filename = this.getLogFilename(metadata.timestamp);\n\n // 날짜가 변경되면 스트림 교체\n if (this.currentFilename !== filename)\n {\n await this.rotateStream(filename);\n await this.cleanOldFiles(); // 오래된 파일 정리\n }\n // 파일 크기 체크 및 로테이션\n else if (this.currentFilename)\n {\n await this.checkAndRotateBySize();\n }\n\n // 스트림에 쓰기\n if (this.currentStream)\n {\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.write(message + '\\n', 'utf-8', (error: Error | null | undefined) =>\n {\n if (error)\n {\n // 파일 쓰기 실패 시 stderr로 출력 (fallback)\n process.stderr.write(`[FileTransport] Failed to write log: ${error.message}\\n`);\n reject(error);\n }\n else\n {\n resolve();\n }\n });\n });\n }\n }\n\n /**\n * 스트림 교체 (날짜 변경 시)\n */\n private async rotateStream(filename: string): Promise<void>\n {\n // 기존 스트림 닫기\n if (this.currentStream)\n {\n await this.closeStream();\n }\n\n // 새 스트림 생성\n const filepath = join(this.logDir, filename);\n\n this.currentStream = createWriteStream(filepath, {\n flags: 'a', // append mode\n encoding: 'utf-8',\n });\n\n this.currentFilename = filename;\n\n // 스트림 에러 핸들링\n this.currentStream.on('error', (error) =>\n {\n process.stderr.write(`[FileTransport] Stream error: ${error.message}\\n`);\n // 에러 발생 시 스트림 초기화\n this.currentStream = null;\n this.currentFilename = null;\n });\n }\n\n /**\n * 현재 스트림 닫기\n */\n private async closeStream(): Promise<void>\n {\n if (!this.currentStream)\n {\n return;\n }\n\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.end((error: Error | null | undefined) =>\n {\n if (error)\n {\n reject(error);\n }\n else\n {\n this.currentStream = null;\n this.currentFilename = null;\n resolve();\n }\n });\n });\n }\n\n /**\n * 파일 크기 체크 및 크기 기반 로테이션\n */\n private async checkAndRotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n const filepath = join(this.logDir, this.currentFilename);\n\n // 파일이 존재하지 않으면 스킵\n if (!existsSync(filepath))\n {\n return;\n }\n\n try\n {\n const stats = statSync(filepath);\n\n // 파일 크기가 maxFileSize를 초과하면 로테이션\n if (stats.size >= this.maxFileSize)\n {\n await this.rotateBySize();\n }\n }\n catch (error)\n {\n // 파일 stat 실패 시 무시\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 크기 기반 로테이션 수행\n * 예: 2025-01-01.log -> 2025-01-01.1.log, 2025-01-01.1.log -> 2025-01-01.2.log\n */\n private async rotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n // 기존 스트림 닫기\n await this.closeStream();\n\n const baseName = this.currentFilename.replace(/\\.log$/, '');\n const files = readdirSync(this.logDir);\n\n // 현재 날짜의 로그 파일들 찾기 (예: 2025-01-01.log, 2025-01-01.1.log, ...)\n const relatedFiles = files\n .filter(file => file.startsWith(baseName) && file.endsWith('.log'))\n .sort()\n .reverse(); // 역순 정렬로 높은 번호부터 처리\n\n // 기존 파일들을 번호 증가시켜 이동 (예: .1.log -> .2.log)\n for (const file of relatedFiles)\n {\n const match = file.match(/\\.(\\d+)\\.log$/);\n if (match)\n {\n const oldNum = parseInt(match[1], 10);\n const newNum = oldNum + 1;\n const oldPath = join(this.logDir, file);\n const newPath = join(this.logDir, `${baseName}.${newNum}.log`);\n\n try\n {\n renameSync(oldPath, newPath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}\\n`);\n }\n }\n }\n\n // 현재 파일을 .1.log로 이동\n const currentPath = join(this.logDir, this.currentFilename);\n const newPath = join(this.logDir, `${baseName}.1.log`);\n\n try\n {\n if (existsSync(currentPath))\n {\n renameSync(currentPath, newPath);\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}\\n`);\n }\n\n // 새 스트림 생성 (동일한 파일명으로)\n await this.rotateStream(this.currentFilename);\n }\n\n /**\n * 오래된 로그 파일 정리\n * maxFiles 개수를 초과하는 로그 파일 삭제\n */\n private async cleanOldFiles(): Promise<void>\n {\n try\n {\n // 디렉토리가 존재하지 않으면 스킵\n if (!existsSync(this.logDir))\n {\n return;\n }\n\n const files = readdirSync(this.logDir);\n\n // .log로 끝나는 파일만 필터링 후 수정 시간 기준 정렬\n const logFiles = files\n .filter(file => file.endsWith('.log'))\n .map(file =>\n {\n const filepath = join(this.logDir, file);\n const stats = statSync(filepath);\n return { file, mtime: stats.mtime };\n })\n .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); // 최신 파일이 앞으로\n\n // maxFiles를 초과하는 오래된 파일들 삭제\n if (logFiles.length > this.maxFiles)\n {\n const filesToDelete = logFiles.slice(this.maxFiles);\n\n for (const { file } of filesToDelete)\n {\n const filepath = join(this.logDir, file);\n try\n {\n unlinkSync(filepath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to delete old file \"${file}\": ${errorMessage}\\n`);\n }\n }\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 날짜별 로그 파일명 생성\n */\n private getLogFilename(date: Date): string\n {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}.log`;\n }\n\n async close(): Promise<void>\n {\n // 스트림 정리\n await this.closeStream();\n }\n}","/**\n * Logger Configuration\n *\n * Environment-based logger configuration with validation for console, file, Slack, and Email transports.\n */\n\nimport { existsSync, accessSync, constants, mkdirSync, writeFileSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type {\n LogLevel,\n ConsoleTransportConfig,\n FileTransportConfig,\n SlackTransportConfig,\n EmailTransportConfig,\n} from './types';\n\n/**\n * Check if file logging is enabled (for self-hosted)\n */\nexport function isFileLoggingEnabled(): boolean\n{\n return process.env.LOGGER_FILE_ENABLED === 'true';\n}\n\n/**\n * Get default log level by environment\n */\nexport function getDefaultLogLevel(): LogLevel\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment)\n {\n return 'debug';\n }\n\n if (isProduction)\n {\n return 'info';\n }\n\n // Test environment\n return 'warn';\n}\n\n/**\n * Console Transport configuration\n */\nexport function getConsoleConfig(): ConsoleTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'debug',\n enabled: true,\n colorize: !isProduction, // Dev: colored output, Production: plain text\n };\n}\n\n/**\n * File Transport configuration\n */\nexport function getFileConfig(): FileTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'info',\n enabled: isProduction, // File logging in production only\n logDir: process.env.LOG_DIR || './logs',\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n };\n}\n\n/**\n * Slack Transport configuration\n */\nexport function getSlackConfig(): SlackTransportConfig | null\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return null; // Disabled if not configured\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'error', // Send error and above to Slack\n enabled: isProduction, // Enabled in production only\n webhookUrl,\n channel: process.env.SLACK_CHANNEL,\n username: process.env.SLACK_USERNAME || 'Logger Bot',\n };\n}\n\n/**\n * Email Transport configuration\n */\nexport function getEmailConfig(): EmailTransportConfig | null\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // Disabled if required settings are missing\n if (!smtpHost || !smtpPort || !emailFrom || !emailTo)\n {\n return null;\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'fatal', // Send fatal level only via email\n enabled: isProduction, // Enabled in production only\n from: emailFrom,\n to: emailTo.split(',').map(email => email.trim()),\n smtpHost,\n smtpPort: parseInt(smtpPort, 10),\n smtpUser: process.env.SMTP_USER,\n smtpPassword: process.env.SMTP_PASSWORD,\n };\n}\n\n/**\n * Validate directory path and write permissions\n */\nfunction validateDirectoryWritable(dirPath: string): void\n{\n // Check if directory exists\n if (!existsSync(dirPath))\n {\n // Try to create directory\n try\n {\n mkdirSync(dirPath, { recursive: true });\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to create log directory \"${dirPath}\": ${errorMessage}`);\n }\n }\n\n // Check write permission\n try\n {\n accessSync(dirPath, constants.W_OK);\n }\n catch\n {\n throw new Error(`Log directory \"${dirPath}\" is not writable. Please check permissions.`);\n }\n\n // Try to write a test file\n const testFile = join(dirPath, '.logger-write-test');\n try\n {\n writeFileSync(testFile, 'test', 'utf-8');\n unlinkSync(testFile);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Cannot write to log directory \"${dirPath}\": ${errorMessage}`);\n }\n}\n\n/**\n * Validate file transport configuration\n */\nfunction validateFileConfig(): void\n{\n if (!isFileLoggingEnabled())\n {\n return; // File logging disabled, skip validation\n }\n\n const logDir = process.env.LOG_DIR;\n\n // Check if LOG_DIR is set\n if (!logDir)\n {\n throw new Error(\n 'LOG_DIR environment variable is required when LOGGER_FILE_ENABLED=true. ' +\n 'Example: LOG_DIR=/var/log/myapp'\n );\n }\n\n // Validate directory\n validateDirectoryWritable(logDir);\n}\n\n/**\n * Validate Slack transport configuration\n */\nfunction validateSlackConfig(): void\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return; // Slack disabled, skip validation\n }\n\n // Validate webhook URL format\n if (!webhookUrl.startsWith('https://hooks.slack.com/'))\n {\n throw new Error(\n `Invalid SLACK_WEBHOOK_URL: \"${webhookUrl}\". ` +\n 'Slack webhook URLs must start with \"https://hooks.slack.com/\"'\n );\n }\n}\n\n/**\n * Validate Email transport configuration\n */\nfunction validateEmailConfig(): void\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // If any email config is set, all required fields must be present\n const hasAnyEmailConfig = smtpHost || smtpPort || emailFrom || emailTo;\n if (!hasAnyEmailConfig)\n {\n return; // Email disabled, skip validation\n }\n\n // Validate all required fields\n const missingFields: string[] = [];\n if (!smtpHost) missingFields.push('SMTP_HOST');\n if (!smtpPort) missingFields.push('SMTP_PORT');\n if (!emailFrom) missingFields.push('EMAIL_FROM');\n if (!emailTo) missingFields.push('EMAIL_TO');\n\n if (missingFields.length > 0)\n {\n throw new Error(\n `Email transport configuration incomplete. Missing: ${missingFields.join(', ')}. ` +\n 'Either set all required fields or remove all email configuration.'\n );\n }\n\n // Validate SMTP port is a number\n const port = parseInt(smtpPort!, 10);\n if (isNaN(port) || port < 1 || port > 65535)\n {\n throw new Error(\n `Invalid SMTP_PORT: \"${smtpPort}\". Must be a number between 1 and 65535.`\n );\n }\n\n // Validate email format (basic check)\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(emailFrom!))\n {\n throw new Error(`Invalid EMAIL_FROM format: \"${emailFrom}\"`);\n }\n\n // Validate email recipients\n const recipients = emailTo!.split(',').map(e => e.trim());\n for (const email of recipients)\n {\n if (!emailRegex.test(email))\n {\n throw new Error(`Invalid email address in EMAIL_TO: \"${email}\"`);\n }\n }\n}\n\n/**\n * Validate environment variables\n */\nfunction validateEnvironment(): void\n{\n const nodeEnv = process.env.NODE_ENV;\n\n if (!nodeEnv)\n {\n process.stderr.write(\n '[Logger] Warning: NODE_ENV is not set. Defaulting to test environment.\\n'\n );\n }\n // Allow any NODE_ENV value (development, production, test, staging, local, etc.)\n // No validation needed - users can use custom environments\n}\n\n/**\n * Validate all logger configuration\n * Throws an error if configuration is invalid\n */\nexport function validateConfig(): void\n{\n try\n {\n validateEnvironment();\n validateFileConfig();\n validateSlackConfig();\n validateEmailConfig();\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n throw new Error(`[Logger] Configuration validation failed: ${error.message}`);\n }\n throw error;\n }\n}","/**\n * Custom Logger Adapter\n *\n * 자체 구현한 Logger를 사용하는 Adapter\n *\n * ✅ 구현 완료:\n * - 기존 Logger 클래스 래핑\n * - Transport 시스템 (Console, File)\n * - Child logger 지원\n *\n * 💡 용도:\n * - Pino 의존성 제거 필요시\n * - 커스텀 Transport 필요시\n * - 완전한 제어가 필요한 경우\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현)\n * - src/logger/adapters/types.ts (인터페이스)\n */\n\nimport { Logger } from '../logger';\nimport { ConsoleTransport } from '../transports/console';\nimport { FileTransport } from '../transports/file';\nimport { getConsoleConfig, getFileConfig } from '../config';\nimport type { LoggerAdapter, AdapterConfig } from './types';\nimport type { Transport } from '../types';\n\n/**\n * Transport 초기화\n */\nfunction initializeTransports(): Transport[]\n{\n const transports: Transport[] = [];\n\n // Console Transport (항상 활성화)\n const consoleConfig = getConsoleConfig();\n transports.push(new ConsoleTransport(consoleConfig));\n\n // File Transport (프로덕션에서만 활성화)\n const fileConfig = getFileConfig();\n if (fileConfig.enabled)\n {\n transports.push(new FileTransport(fileConfig));\n }\n\n return transports;\n}\n\n/**\n * Custom Logger Adapter\n */\nexport class CustomAdapter implements LoggerAdapter\n{\n private logger: Logger;\n\n constructor(config: AdapterConfig)\n {\n this.logger = new Logger({\n level: config.level,\n module: config.module,\n transports: initializeTransports(),\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const adapter = new CustomAdapter({ level: this.logger.level, module });\n adapter.logger = this.logger.child(module);\n return adapter;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(message, context);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn(message, errorOrContext, context);\n }\n else\n {\n this.logger.warn(message, errorOrContext);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error(message, errorOrContext, context);\n }\n else\n {\n this.logger.error(message, errorOrContext);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal(message, errorOrContext, context);\n }\n else\n {\n this.logger.fatal(message, errorOrContext);\n }\n }\n\n async close(): Promise<void>\n {\n await this.logger.close();\n }\n}","/**\n * Logger Adapter Factory\n *\n * Adapter creation and initialization logic\n */\n\nimport { PinoAdapter } from './adapters/pino.js';\nimport { CustomAdapter } from './adapters/custom.js';\nimport { getDefaultLogLevel, validateConfig } from './config.js';\nimport type { LoggerAdapter } from './adapters/types.js';\n\n/**\n * Adapter type\n */\ntype AdapterType = 'pino' | 'custom';\n\n/**\n * Create adapter instance\n */\nfunction createAdapter(type: AdapterType): LoggerAdapter\n{\n const level = getDefaultLogLevel();\n\n switch (type)\n {\n case 'pino':\n return new PinoAdapter({ level });\n\n case 'custom':\n return new CustomAdapter({ level });\n\n default:\n return new PinoAdapter({ level });\n }\n}\n\n/**\n * Read adapter type from environment variable\n */\nfunction getAdapterType(): AdapterType\n{\n const adapterEnv = process.env.LOGGER_ADAPTER as AdapterType;\n\n if (adapterEnv === 'custom' || adapterEnv === 'pino')\n {\n return adapterEnv;\n }\n\n // Default: pino\n return 'pino';\n}\n\n/**\n * Initialize logger with configuration validation\n */\nfunction initializeLogger(): LoggerAdapter\n{\n // Validate configuration before creating logger\n validateConfig();\n\n // Create and return logger instance\n return createAdapter(getAdapterType());\n}\n\n/**\n * Singleton Logger instance\n */\nexport const logger: LoggerAdapter = initializeLogger();","/**\n * Codegen Orchestrator\n *\n * Manages multiple code generators and coordinates their execution\n */\n\nimport { watch as chokidarWatch } from 'chokidar';\nimport { join, relative } from 'path';\nimport mm from 'micromatch';\nimport type { Generator, GeneratorOptions, GeneratorTrigger } from './generator.js';\nimport { logger } from '../../logger';\n\nconst orchestratorLogger = logger.child('orchestrator');\n\nexport interface OrchestratorOptions\n{\n /** List of generators to orchestrate */\n generators: Generator[];\n\n /** Project root directory */\n cwd?: string;\n\n /** Enable debug logging */\n debug?: boolean;\n}\n\nexport class CodegenOrchestrator\n{\n private readonly generators: Generator[];\n private readonly cwd: string;\n private readonly debug: boolean;\n private isGenerating = false;\n private pendingRegenerations = new Set<string>();\n\n constructor(options: OrchestratorOptions)\n {\n this.generators = options.generators;\n this.cwd = options.cwd ?? process.cwd();\n this.debug = options.debug ?? false;\n }\n\n /**\n * Check if generator should run for given trigger\n */\n private shouldRun(generator: Generator, trigger: GeneratorTrigger): boolean\n {\n const runOn = generator.runOn ?? ['watch', 'manual', 'build'];\n return runOn.includes(trigger);\n }\n\n /**\n * Run all generators once\n *\n * @param trigger - How the generators are being triggered\n */\n async generateAll(trigger: GeneratorTrigger = 'manual'): Promise<void>\n {\n if (this.debug)\n {\n orchestratorLogger.info('Running all generators', {\n count: this.generators.length,\n names: this.generators.map(g => g.name),\n trigger\n });\n }\n\n for (const generator of this.generators)\n {\n // Check if generator should run for this trigger\n if (!this.shouldRun(generator, trigger))\n {\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Skipped (runOn: ${generator.runOn?.join(', ') ?? 'default'})`);\n }\n continue;\n }\n\n try\n {\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug,\n trigger: {\n type: trigger\n }\n };\n\n await generator.generate(genOptions);\n\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Generated successfully`);\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] Generation failed`, err);\n }\n }\n }\n\n /**\n * Start watch mode\n */\n async watch(): Promise<void>\n {\n // Initial generation with 'watch' trigger\n await this.generateAll('watch');\n\n // Collect all watch patterns from generators\n const allPatterns = this.generators.flatMap(g => g.watchPatterns);\n\n if (allPatterns.length === 0)\n {\n orchestratorLogger.warn('No watch patterns defined, exiting watch mode');\n return;\n }\n\n // Extract directories to watch from patterns\n // For pattern like \"watched/**/*.ts\", watch \"watched\" directory\n const dirsToWatch = new Set<string>();\n for (const pattern of allPatterns)\n {\n // Extract base directory from glob pattern (e.g., \"src/**/*.ts\" -> \"src\")\n const baseDir = pattern.split('**')[0].replace(/\\/$/, '') || '.';\n dirsToWatch.add(join(this.cwd, baseDir));\n }\n\n const watchDirs = Array.from(dirsToWatch);\n\n if (this.debug)\n {\n orchestratorLogger.info('Starting watch mode', {\n patterns: allPatterns,\n watchDirs,\n cwd: this.cwd\n });\n }\n\n const watcher = chokidarWatch(watchDirs, {\n ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50\n }\n });\n\n const handleChange = async (absolutePath: string, event: 'add' | 'change' | 'unlink') =>\n {\n // Convert absolute path to relative path for pattern matching\n const filePath = relative(this.cwd, absolutePath);\n\n if (this.isGenerating)\n {\n this.pendingRegenerations.add(absolutePath);\n return;\n }\n\n this.isGenerating = true;\n this.pendingRegenerations.clear();\n\n if (this.debug)\n {\n orchestratorLogger.info(`File ${event}`, { file: filePath });\n }\n\n // Find matching generators\n for (const generator of this.generators)\n {\n // Check if generator should run for 'watch' trigger\n if (!this.shouldRun(generator, 'watch'))\n {\n continue;\n }\n\n const matches = generator.watchPatterns.some(pattern =>\n mm.isMatch(filePath, pattern)\n );\n\n if (matches)\n {\n try\n {\n // Call generate() with trigger information\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug,\n trigger: {\n type: 'watch',\n changedFile: {\n path: filePath,\n event\n }\n }\n };\n\n await generator.generate(genOptions);\n\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Regenerated`);\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] Regeneration failed`, err);\n }\n }\n }\n\n this.isGenerating = false;\n\n // Process pending regenerations\n if (this.pendingRegenerations.size > 0)\n {\n const next = Array.from(this.pendingRegenerations)[0];\n await handleChange(next, 'change');\n }\n };\n\n watcher\n .on('add', (path) => handleChange(path, 'add'))\n .on('change', (path) => handleChange(path, 'change'))\n .on('unlink', (path) => handleChange(path, 'unlink'));\n\n // Cleanup on exit\n process.on('SIGINT', () =>\n {\n if (this.debug)\n {\n orchestratorLogger.info('Shutting down watch mode');\n }\n watcher.close();\n process.exit(0);\n });\n\n // Keep process alive\n await new Promise(() => {});\n }\n}\n","/**\n * Contract Scanner\n *\n * Scans server/contracts directory and extracts exported contracts\n */\n\nimport { readFileSync } from 'fs';\nimport { readdir, stat } from 'fs/promises';\nimport { join } from 'path';\nimport * as ts from 'typescript';\nimport type { HttpMethod, RouteContractMapping } from '../../core/types';\nimport { logger } from '../../../logger';\n\nconst scannerLogger = logger.child('contract-scanner');\n\n/**\n * Scan for contract files and extract contract exports\n *\n * All contracts must use absolute paths (e.g., path: '/teams/:id')\n *\n * @param contractsDir - Path to lib/contracts/ directory\n * @param packagePrefix - Optional package prefix to apply to all contract paths\n * @returns Array of contract-to-route mappings\n */\nexport async function scanContracts(contractsDir: string, packagePrefix?: string): Promise<RouteContractMapping[]>\n{\n scannerLogger.debug('Starting contract scan', { contractsDir, packagePrefix });\n const contractFiles = await scanContractFiles(contractsDir);\n scannerLogger.debug('Found contract files', { count: contractFiles.length, files: contractFiles });\n const mappings: RouteContractMapping[] = [];\n\n for (let i = 0; i < contractFiles.length; i++)\n {\n const filePath = contractFiles[i];\n scannerLogger.debug('Extracting contracts from file', { filePath });\n const exports = extractContractExports(filePath);\n scannerLogger.debug('Extracted contracts', { filePath, count: exports.length, contracts: exports.map(e => e.name) });\n\n for (let j = 0; j < exports.length; j++)\n {\n const contractExport = exports[j];\n scannerLogger.debug('Processing contract', { name: contractExport.name, method: contractExport.method, path: contractExport.path });\n\n // All contracts must use absolute paths\n if (!contractExport.path.startsWith('/'))\n {\n throw new Error(\n `Contract '${contractExport.name}' in ${filePath} must use absolute path. ` +\n `Found: '${contractExport.path}'. Use '/your-path' instead.`\n );\n }\n\n if(packagePrefix && !contractExport.path.startsWith(packagePrefix))\n {\n throw new Error(\n `Contract '${contractExport.name}' in ${filePath} must include package prefix. ` +\n `Expected path to start with '${packagePrefix}', but found: '${contractExport.path}'. ` +\n `Example: path: '${packagePrefix}/${contractExport.path}'`\n );\n }\n\n // Apply package prefix if exists\n mappings.push({\n method: contractExport.method,\n path: contractExport.path,\n contractName: contractExport.name,\n contractImportPath: getImportPath(filePath),\n routeFile: '',\n contractFile: filePath,\n hasQuery: contractExport.hasQuery,\n hasBody: contractExport.hasBody,\n hasParams: contractExport.hasParams\n });\n }\n }\n\n scannerLogger.info('Contract scan completed', { totalMappings: mappings.length });\n return mappings;\n}\n\n/**\n * Recursively scan for contract files in lib/contracts/\n *\n * Scans for all .ts, .js, .mjs files (excluding test and declaration files)\n */\nasync function scanContractFiles(dir: string, files: string[] = []): Promise<string[]>\n{\n try\n {\n const entries = await readdir(dir);\n\n for (let i = 0; i < entries.length; i++)\n {\n const entry = entries[i];\n const fullPath = join(dir, entry);\n const fileStat = await stat(fullPath);\n\n if (fileStat.isDirectory())\n {\n await scanContractFiles(fullPath, files);\n }\n else\n {\n // Scan all .ts, .js, .mjs files (excluding test and declaration files)\n if (\n (entry.endsWith('.ts') || entry.endsWith('.js') || entry.endsWith('.mjs')) &&\n !entry.endsWith('.d.ts') &&\n !entry.endsWith('.test.ts') &&\n !entry.endsWith('.test.js') &&\n !entry.endsWith('.test.mjs')\n )\n {\n files.push(fullPath);\n }\n }\n }\n }\n catch (error)\n {\n // Directory doesn't exist or not readable\n }\n\n return files;\n}\n\n/**\n * Contract export information\n */\ninterface ContractExport\n{\n name: string;\n method: HttpMethod;\n path: string;\n hasQuery?: boolean;\n hasBody?: boolean;\n hasParams?: boolean;\n}\n\n/**\n * Extract contract exports from a TypeScript file\n *\n * Multi-layer detection:\n * 1. satisfies RouteContract (most explicit)\n * 2. Contract name pattern + method/path properties (fallback)\n *\n * @example\n * // Layer 1: satisfies RouteContract\n * export const myContract = { ... } satisfies RouteContract;\n *\n * // Layer 2: Name pattern + validation\n * export const myContract = { method: 'GET', path: '/api' };\n */\nfunction extractContractExports(filePath: string): ContractExport[]\n{\n const sourceCode = readFileSync(filePath, 'utf-8');\n const sourceFile = ts.createSourceFile(\n filePath,\n sourceCode,\n ts.ScriptTarget.Latest,\n true\n );\n\n const exports: ContractExport[] = [];\n\n function visit(node: ts.Node): void\n {\n // Look for: export const xxxContract = { ... }\n if (ts.isVariableStatement(node))\n {\n // Check if it has export modifier\n const hasExport = node.modifiers?.some(\n m => m.kind === ts.SyntaxKind.ExportKeyword\n );\n\n if (hasExport && node.declarationList.declarations.length > 0)\n {\n const declaration = node.declarationList.declarations[0];\n\n if (\n ts.isVariableDeclaration(declaration) &&\n ts.isIdentifier(declaration.name) &&\n declaration.initializer\n )\n {\n const name = declaration.name.text;\n\n // Layer 1: Check for satisfies RouteContract\n const hasSatisfiesRouteContract = checkSatisfiesRouteContract(declaration.initializer);\n\n if (hasSatisfiesRouteContract)\n {\n const objectLiteral = extractObjectLiteral(declaration.initializer);\n\n if (objectLiteral)\n {\n const contractData = extractContractData(objectLiteral);\n\n if (contractData.method && contractData.path)\n {\n exports.push({\n name,\n method: contractData.method,\n path: contractData.path,\n hasQuery: contractData.hasQuery,\n hasBody: contractData.hasBody,\n hasParams: contractData.hasParams\n });\n }\n }\n return; // Found via satisfies, skip fallback\n }\n\n // Layer 2: Fallback to name pattern check\n if (isContractName(name))\n {\n const objectLiteral = extractObjectLiteral(declaration.initializer);\n\n if (objectLiteral)\n {\n const contractData = extractContractData(objectLiteral);\n\n // Require both method and path for fallback detection\n if (contractData.method && contractData.path)\n {\n exports.push({\n name,\n method: contractData.method,\n path: contractData.path,\n hasQuery: contractData.hasQuery,\n hasBody: contractData.hasBody,\n hasParams: contractData.hasParams\n });\n }\n }\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return exports;\n}\n\n/**\n * Check if declaration uses 'satisfies RouteContract'\n */\nfunction checkSatisfiesRouteContract(initializer: ts.Expression): boolean\n{\n if (!ts.isSatisfiesExpression(initializer))\n {\n return false;\n }\n\n const typeNode = initializer.type;\n\n // Check for RouteContract type reference\n if (ts.isTypeReferenceNode(typeNode) &&\n ts.isIdentifier(typeNode.typeName))\n {\n return typeNode.typeName.text === 'RouteContract';\n }\n\n return false;\n}\n\n/**\n * Extract object literal from various expression forms\n */\nfunction extractObjectLiteral(initializer: ts.Expression): ts.ObjectLiteralExpression | undefined\n{\n // Direct object literal: { ... }\n if (ts.isObjectLiteralExpression(initializer))\n {\n return initializer;\n }\n\n // satisfies expression: { ... } satisfies RouteContract\n if (ts.isSatisfiesExpression(initializer))\n {\n return extractObjectLiteral(initializer.expression);\n }\n\n // as expression: { ... } as const\n if (ts.isAsExpression(initializer))\n {\n return extractObjectLiteral(initializer.expression);\n }\n\n return undefined;\n}\n\n/**\n * Extract method, path, and parameter info from contract object literal\n */\nfunction extractContractData(objectLiteral: ts.ObjectLiteralExpression): {\n method?: HttpMethod;\n path?: string;\n hasQuery?: boolean;\n hasBody?: boolean;\n hasParams?: boolean;\n}\n{\n const result: {\n method?: HttpMethod;\n path?: string;\n hasQuery?: boolean;\n hasBody?: boolean;\n hasParams?: boolean;\n } = {};\n\n for (let i = 0; i < objectLiteral.properties.length; i++)\n {\n const prop = objectLiteral.properties[i];\n\n if (\n ts.isPropertyAssignment(prop) &&\n ts.isIdentifier(prop.name)\n )\n {\n const propName = prop.name.text;\n\n if (propName === 'method')\n {\n // Handle both 'GET' and 'GET' as const\n let value: string | undefined;\n if (ts.isStringLiteral(prop.initializer))\n {\n value = prop.initializer.text;\n }\n else if (ts.isAsExpression(prop.initializer) && ts.isStringLiteral(prop.initializer.expression))\n {\n value = prop.initializer.expression.text;\n }\n if (value) result.method = value as HttpMethod;\n }\n else if (propName === 'path')\n {\n // Handle both '/path' and '/path' as const\n let value: string | undefined;\n if (ts.isStringLiteral(prop.initializer))\n {\n value = prop.initializer.text;\n }\n else if (ts.isAsExpression(prop.initializer) && ts.isStringLiteral(prop.initializer.expression))\n {\n value = prop.initializer.expression.text;\n }\n if (value) result.path = value;\n }\n else if (propName === 'query')\n {\n // Has query property\n result.hasQuery = true;\n }\n else if (propName === 'body')\n {\n // Has body property\n result.hasBody = true;\n }\n else if (propName === 'params')\n {\n // Has params property\n result.hasParams = true;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Check if a name looks like a contract\n */\nfunction isContractName(name: string): boolean\n{\n return (\n name.indexOf('Contract') !== -1 ||\n name.indexOf('contract') !== -1 ||\n name.endsWith('Schema') ||\n name.endsWith('schema')\n );\n}\n\n/**\n * Get import path for contract file\n *\n * @example\n * /path/to/src/lib/contracts/teams.ts → @/lib/contracts/teams\n */\nfunction getImportPath(filePath: string): string\n{\n // Try to find src/ directory\n const srcIndex = filePath.indexOf('/src/');\n\n if (srcIndex === -1)\n {\n throw new Error(`Cannot determine import path for ${filePath}: /src/ directory not found`);\n }\n\n // Get path from src/ onwards (+5 to skip '/src/')\n // Remove file extension (.ts, .js, .mjs)\n let cleanPath = filePath.substring(srcIndex + 5);\n if (cleanPath.endsWith('.ts'))\n {\n cleanPath = cleanPath.slice(0, -3);\n }\n else if (cleanPath.endsWith('.js'))\n {\n cleanPath = cleanPath.slice(0, -3);\n }\n else if (cleanPath.endsWith('.mjs'))\n {\n cleanPath = cleanPath.slice(0, -4);\n }\n\n // Return as module path with @ prefix\n return '@/' + cleanPath;\n}","/**\n * Codegen Helper Utilities\n *\n * Helper functions for grouping and organizing contract mappings\n */\n\nimport type { RouteContractMapping } from '../../core/types';\n\n/**\n * Group mappings by resource\n */\nexport function groupByResource(mappings: RouteContractMapping[]): Record<string, RouteContractMapping[]>\n{\n const grouped: Record<string, RouteContractMapping[]> = {};\n\n for (let i = 0; i < mappings.length; i++)\n {\n const mapping = mappings[i];\n const resource = extractResourceName(mapping.path);\n\n if (!grouped[resource])\n {\n grouped[resource] = [];\n }\n\n grouped[resource].push(mapping);\n }\n\n return grouped;\n}\n\n/**\n * Extract resource name from path\n *\n * Examples:\n * - /users → users\n * - /users/:id → users\n * - /users/:id/posts → usersPosts\n * - /videos/upload-and-analyze → videosUploadAndAnalyze\n * - /_cms/labels → labels (with prefix='/_cms')\n * - /_cms/published-cache → publishedCache (with prefix='/_cms')\n */\nfunction extractResourceName(path: string): string\n{\n // Strip prefix from path if provided\n let processedPath = path;\n if (!processedPath.startsWith('/'))\n {\n processedPath = '/' + processedPath;\n }\n\n // Remove leading slash\n const segments = processedPath.slice(1).split('/').filter(s => s && s !== '*');\n\n // Remove dynamic segments\n const staticSegments: string[] = [];\n for (let i = 0; i < segments.length; i++)\n {\n const seg = segments[i];\n if (!seg.startsWith(':'))\n {\n staticSegments.push(seg);\n }\n }\n\n // Join with camelCase\n if (staticSegments.length === 0)\n {\n return 'root';\n }\n\n // Convert first segment (keep lowercase for first)\n const first = toCamelCase(staticSegments[0], false);\n\n if (staticSegments.length === 1)\n {\n return first;\n }\n\n // Convert to camelCase: users/posts → usersPosts, videos/upload-and-analyze → videosUploadAndAnalyze\n const result: string[] = [first];\n for (let i = 1; i < staticSegments.length; i++)\n {\n const seg = staticSegments[i];\n result.push(toCamelCase(seg, true));\n }\n\n return result.join('');\n}\n\n/**\n * Convert string to camelCase, handling hyphens\n *\n * @param str - Input string\n * @param capitalize - Capitalize first letter\n * @returns camelCase string\n *\n * Examples:\n * - toCamelCase('upload-and-analyze', true) → 'UploadAndAnalyze'\n * - toCamelCase('upload-and-analyze', false) → 'uploadAndAnalyze'\n * - toCamelCase('users', false) → 'users'\n */\nfunction toCamelCase(str: string, capitalize: boolean): string\n{\n // Split by hyphen or underscore\n const parts = str.split(/[-_]/);\n\n if (parts.length === 1)\n {\n // No hyphens/underscores\n return capitalize\n ? str.charAt(0).toUpperCase() + str.slice(1)\n : str;\n }\n\n // Convert to camelCase\n const result: string[] = [];\n for (let i = 0; i < parts.length; i++)\n {\n const part = parts[i];\n if (i === 0 && !capitalize)\n {\n result.push(part);\n }\n else\n {\n result.push(part.charAt(0).toUpperCase() + part.slice(1));\n }\n }\n\n return result.join('');\n}","/**\n * Client Code Generator\n *\n * Generates type-safe API client code from route-contract mappings\n */\n\nimport { mkdir, writeFile } from 'fs/promises';\nimport { groupByResource } from './helpers';\nimport type { ClientGenerationOptions, GenerationStats, RouteContractMapping } from '../../core/types';\n\n/**\n * Generate API client code\n */\nexport async function generateClient(\n mappings: RouteContractMapping[],\n options: ClientGenerationOptions\n): Promise<GenerationStats>\n{\n const startTime = Date.now();\n\n // Group by resource\n const grouped = groupByResource(mappings);\n const resourceNames = Object.keys(grouped);\n\n // Generate split files by resource\n await generateSplitClient(mappings, grouped, options);\n\n // Calculate stats\n return {\n routesScanned: mappings.length,\n contractsFound: mappings.length,\n contractFiles: countUniqueContractFiles(mappings),\n resourcesGenerated: resourceNames.length,\n methodsGenerated: mappings.length,\n duration: Date.now() - startTime\n };\n}\n\n/**\n * Generate file header\n */\nfunction generateHeader(): string\n{\n return `/**\n * Auto-generated API Client\n *\n * Generated by @spfn/core codegen\n * DO NOT EDIT MANUALLY\n *\n * @generated ${new Date().toISOString()}\n */\n\n`;\n}\n\n/**\n * Group contracts by their import path\n */\nfunction groupContractsByImportPath(mappings: RouteContractMapping[]): Record<string, string[]>\n{\n const groups: Record<string, Set<string>> = {};\n\n for (let i = 0; i < mappings.length; i++)\n {\n const mapping = mappings[i];\n const path = mapping.contractImportPath;\n\n if (!groups[path])\n {\n groups[path] = new Set();\n }\n\n groups[path].add(mapping.contractName);\n }\n\n // Convert Set to Array\n const result: Record<string, string[]> = {};\n const keys = Object.keys(groups);\n\n for (let i = 0; i < keys.length; i++)\n {\n const key = keys[i];\n result[key] = Array.from(groups[key]);\n }\n\n return result;\n}\n\n/**\n * Convert contract name to type name\n *\n * Examples:\n * - getTeamMembersContract -> GetTeamMembers\n * - createTeamMemberContract -> CreateTeamMember\n * - updateCompanyContract -> UpdateCompany\n */\nfunction generateTypeName(mapping: RouteContractMapping): string\n{\n let name = mapping.contractName;\n\n // Remove \"Contract\" suffix\n if (name.endsWith('Contract'))\n {\n name = name.slice(0, -8);\n }\n\n // Convert to PascalCase if not already\n if (name.length > 0)\n {\n name = name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n return name;\n}\n\n/**\n * Generate function name from contract name\n *\n * Examples:\n * - getLabelsContract -> getLabels\n * - createLabelContract -> createLabel\n * - updateLabelContract -> updateLabel\n */\nfunction generateFunctionName(mapping: RouteContractMapping): string\n{\n let name = mapping.contractName;\n\n // Remove \"Contract\" suffix\n if (name.endsWith('Contract'))\n {\n name = name.slice(0, -8);\n }\n\n return name;\n}\n\n/**\n * Generate a single function export\n */\nfunction generateFunctionCode(mapping: RouteContractMapping, options: ClientGenerationOptions): string\n{\n const functionName = generateFunctionName(mapping);\n const hasParams = mapping.hasParams || mapping.path.includes(':');\n const hasQuery = mapping.hasQuery || false;\n const hasBody = mapping.hasBody || false;\n\n let code = '';\n\n // JSDoc\n if (options.includeJsDoc !== false)\n {\n code += `/**\\n`;\n code += ` * ${mapping.method} ${mapping.path}\\n`;\n code += ` */\\n`;\n }\n\n // Function signature\n code += `export const ${functionName} = (`;\n\n // Parameters - use generated type names instead of InferContract\n const params: string[] = [];\n const typeName = generateTypeName(mapping);\n\n if (hasParams)\n {\n params.push(`params: ${typeName}Params`);\n }\n\n if (hasQuery)\n {\n params.push(`query?: ${typeName}Query`);\n }\n\n if (hasBody)\n {\n params.push(`body: ${typeName}Body`);\n }\n\n if (params.length > 0)\n {\n code += `options: { ${params.join(', ')} }`;\n }\n\n code += `) => `;\n\n // Call client with contract only (no basePath - contracts have absolute paths)\n code += `client.call(${mapping.contractName}`;\n\n if (params.length > 0)\n {\n code += `, options`;\n }\n\n code += `);\\n\\n`;\n\n return code;\n}\n\n/**\n * Count unique contract files\n */\nfunction countUniqueContractFiles(mappings: RouteContractMapping[]): number\n{\n const files = new Set<string>();\n\n for (let i = 0; i < mappings.length; i++)\n {\n if (mappings[i].contractFile)\n {\n files.add(mappings[i].contractFile as string);\n }\n }\n\n return files.size;\n}\n\n/**\n * Convert camelCase to kebab-case\n *\n * Examples:\n * - labels -> labels\n * - publishedCache -> published-cache\n * - usersPosts -> users-posts\n */\nfunction toKebabCase(str: string): string\n{\n if (str.length === 0)\n {\n return str;\n }\n\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .toLowerCase();\n}\n\n/**\n * Generate split API client files by resource\n */\nasync function generateSplitClient(\n _mappings: RouteContractMapping[],\n grouped: Record<string, RouteContractMapping[]>,\n options: ClientGenerationOptions\n): Promise<void>\n{\n // When splitting, outputPath should become a directory\n // e.g., /src/lib/api.ts -> /src/lib/api/\n const outputPath = options.outputPath;\n const outputDir = outputPath.endsWith('.ts') || outputPath.endsWith('.js')\n ? outputPath.replace(/\\.[jt]s$/, '')\n : outputPath;\n\n // Create output directory\n await mkdir(outputDir, { recursive: true });\n\n const resourceNames = Object.keys(grouped);\n\n // Generate individual resource files\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n\n const code = generateResourceFile(resourceName, routes, options);\n // Convert to kebab-case for file name\n const kebabName = toKebabCase(resourceName);\n const filePath = `${outputDir}/${kebabName}.ts`;\n\n await writeFile(filePath, code, 'utf-8');\n }\n\n // Generate index file\n const indexCode = generateIndexFile(grouped, options);\n const indexPath = `${outputDir}/index.ts`;\n\n await writeFile(indexPath, indexCode, 'utf-8');\n}\n\n/**\n * Generate a single resource file\n */\nfunction generateResourceFile(\n _resourceName: string,\n routes: RouteContractMapping[],\n options: ClientGenerationOptions\n): string\n{\n let code = '';\n\n // Header\n code += generateHeader();\n\n // Imports\n code += `import { client } from '@spfn/core/client';\\n`;\n\n if (options.includeTypes !== false)\n {\n code += `import type { InferContract } from '@spfn/core';\\n`;\n }\n\n code += `\\n`;\n\n // Contract imports\n const importGroups = groupContractsByImportPath(routes);\n const importPaths = Object.keys(importGroups);\n\n for (let i = 0; i < importPaths.length; i++)\n {\n const importPath = importPaths[i];\n const contracts = importGroups[importPath];\n\n code += `import { ${contracts.join(', ')} } from '${importPath}';\\n`;\n }\n\n code += `\\n`;\n\n // Types\n if (options.includeTypes !== false)\n {\n code += `// ============================================\\n`;\n code += `// Types\\n`;\n code += `// ============================================\\n\\n`;\n\n for (let i = 0; i < routes.length; i++)\n {\n const route = routes[i];\n const typeName = generateTypeName(route);\n const contractType = `typeof ${route.contractName}`;\n\n // Response type (always present)\n code += `export type ${typeName}Response = InferContract<${contractType}>['response'];\\n`;\n\n // Query type (if exists)\n if (route.hasQuery)\n {\n code += `export type ${typeName}Query = InferContract<${contractType}>['query'];\\n`;\n }\n\n // Params type (if exists)\n if (route.hasParams || route.path.includes(':'))\n {\n code += `export type ${typeName}Params = InferContract<${contractType}>['params'];\\n`;\n }\n\n // Body type (if exists)\n if (route.hasBody)\n {\n code += `export type ${typeName}Body = InferContract<${contractType}>['body'];\\n`;\n }\n\n code += `\\n`;\n }\n }\n\n // Generate individual function exports\n code += `// ============================================\\n`;\n code += `// API Functions\\n`;\n code += `// ============================================\\n\\n`;\n\n for (let i = 0; i < routes.length; i++)\n {\n const route = routes[i];\n code += generateFunctionCode(route, options);\n }\n\n return code;\n}\n\n/**\n * Generate index file that combines all resources\n */\nfunction generateIndexFile(\n grouped: Record<string, RouteContractMapping[]>,\n options: ClientGenerationOptions\n): string\n{\n let code = '';\n const apiName = options.apiName || 'api';\n const resourceNames = Object.keys(grouped);\n\n // Header\n code += generateHeader();\n\n // Re-export client\n code += `export { client } from '@spfn/core/client';\\n\\n`;\n\n // Re-export only types from resource modules (use kebab-case for file names)\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n const kebabName = toKebabCase(resourceName);\n\n // Collect all type names for this resource\n const typeNames: string[] = [];\n for (let j = 0; j < routes.length; j++)\n {\n const route = routes[j];\n const typeName = generateTypeName(route);\n\n // Always export Response type\n typeNames.push(`${typeName}Response`);\n\n // Conditionally export other types\n if (route.hasQuery)\n {\n typeNames.push(`${typeName}Query`);\n }\n if (route.hasParams || route.path.includes(':'))\n {\n typeNames.push(`${typeName}Params`);\n }\n if (route.hasBody)\n {\n typeNames.push(`${typeName}Body`);\n }\n }\n\n if (typeNames.length > 0)\n {\n code += `export type { ${typeNames.join(', ')} } from './${kebabName}';\\n`;\n }\n }\n\n code += `\\n`;\n\n // Import all functions from each resource file\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n const kebabName = toKebabCase(resourceName);\n\n // Get all function names for this resource\n const functionNames = routes.map(route => generateFunctionName(route));\n\n code += `import { ${functionNames.join(', ')} } from './${kebabName}';\\n`;\n }\n\n code += `\\n`;\n\n // Combined API object with all functions flattened\n code += `/**\\n`;\n code += ` * Type-safe API client\\n`;\n code += ` */\\n`;\n code += `export const ${apiName} = {\\n`;\n\n // Add all functions from all resources\n let isFirst = true;\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n\n for (let j = 0; j < routes.length; j++)\n {\n const route = routes[j];\n const functionName = generateFunctionName(route);\n\n if (!isFirst)\n {\n code += `,\\n`;\n }\n\n code += ` ${functionName}`;\n isFirst = false;\n }\n }\n\n code += `\\n} as const;\\n`;\n\n return code;\n}","/**\n * Contract Generator\n *\n * Generates type-safe API client from contract definitions\n *\n * Features:\n * - Automatic scanning of contract files\n * - Type-safe client generation with InferContract\n * - Split output by resource for better code organization\n * - Incremental updates when single files change (smart regeneration)\n */\n\nimport { join } from 'path';\nimport { existsSync, readFileSync } from 'fs';\nimport type { Generator, GeneratorOptions, GeneratorTrigger } from '../../core/generator';\nimport { scanContracts } from './scanner';\nimport { generateClient } from './emitter';\nimport { logger } from '../../../logger';\nimport type { RouteContractMapping, ClientGenerationOptions } from '../../core/types';\n\nconst contractLogger = logger.child('contract-gen');\n\n/** Default paths */\nconst DEFAULT_CONTRACTS_DIR = 'src/lib/contracts';\nconst DEFAULT_OUTPUT_PATH = 'src/lib/api';\n\nexport interface ContractGeneratorConfig\n{\n /** Contracts directory (default: src/lib/contracts) */\n contractsDir?: string;\n\n /** Output directory (default: src/lib/api) */\n outputPath?: string;\n\n /** Base URL for API client */\n baseUrl?: string;\n\n /** When to run this generator (default: ['watch', 'manual', 'build']) */\n runOn?: GeneratorTrigger[];\n}\n\n/**\n * Cache for incremental updates\n */\ninterface ContractCache\n{\n /** All scanned contracts */\n contracts: RouteContractMapping[];\n\n /** Timestamp of last scan */\n lastScan: number;\n}\n\nlet contractCache: ContractCache | null = null;\n\n/**\n * Check if a file change requires full regeneration\n *\n * We need full regen if:\n * - New file added\n * - File deleted\n * - Cache doesn't exist\n */\nfunction needsFullRegeneration(\n event: 'add' | 'change' | 'unlink'\n): boolean\n{\n // New files or deletions always require full scan\n if (event === 'add' || event === 'unlink')\n {\n return true;\n }\n\n // No cache means first run\n if (!contractCache)\n {\n return true;\n }\n\n // For 'change' events, we can do smart regen\n // (only if the file still exports the same contracts)\n return false;\n}\n\n/**\n * Helper to create client generation options\n */\nfunction createClientOptions(\n contractsDir: string,\n outputPath: string,\n baseUrl?: string,\n apiName?: string\n): ClientGenerationOptions\n{\n return {\n routesDir: contractsDir,\n outputPath,\n baseUrl,\n apiName,\n includeTypes: true,\n includeJsDoc: true,\n splitByResource: true\n };\n}\n\n/**\n * Generate API name from prefix\n *\n * Examples:\n * - /_cms -> cmsApi\n * - /_auth -> authApi\n * - /api -> api\n * - undefined -> api\n *\n * @param prefix - Package prefix from spfn config\n * @returns API name in camelCase\n */\nfunction generateApiName(prefix?: string): string\n{\n if (!prefix || prefix === '/api')\n {\n return 'api';\n }\n\n // Remove leading slash and underscores/hyphens\n // /_cms -> cms\n // /_auth -> auth\n const name = prefix.replace(/^\\/[_-]?/, '').replace(/[_-]/g, '');\n\n if (!name)\n {\n return 'api';\n }\n\n // Convert to camelCase and append 'Api'\n return `${name}Api`;\n}\n\n/**\n * Read prefix from package.json\n *\n * @param cwd - Project directory\n * @returns Prefix from spfn config or undefined\n */\nfunction readPrefixFromPackageJson(cwd: string): string | undefined\n{\n try\n {\n const packageJsonPath = join(cwd, 'package.json');\n\n if (!existsSync(packageJsonPath))\n {\n return undefined;\n }\n\n const content = readFileSync(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(content);\n\n return packageJson.spfn?.prefix;\n }\n catch (error)\n {\n // Ignore errors, return undefined\n return undefined;\n }\n}\n\nexport function createContractGenerator(config: ContractGeneratorConfig = {}): Generator\n{\n // Resolve paths once\n const contractsDir = config.contractsDir ?? DEFAULT_CONTRACTS_DIR;\n const outputPath = config.outputPath ?? DEFAULT_OUTPUT_PATH;\n const runOn = config.runOn ?? ['watch', 'manual', 'build']; // Default excludes 'start'\n\n return {\n name: 'contract',\n watchPatterns: [\n `${contractsDir}/**/*.ts`,\n ],\n runOn,\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const cwd = options.cwd;\n const fullContractsDir = join(cwd, contractsDir);\n const fullOutputPath = join(cwd, outputPath);\n\n // Read prefix from package.json once at the start\n const prefix = readPrefixFromPackageJson(cwd);\n const apiName = generateApiName(prefix);\n\n try\n {\n // Check if contracts directory exists\n if (!existsSync(fullContractsDir))\n {\n if (options.debug)\n {\n contractLogger.warn(`No contracts directory found at ${contractsDir}`);\n }\n return;\n }\n\n // Check for incremental update opportunity\n const changedFile = options.trigger?.changedFile;\n if (changedFile && !needsFullRegeneration(changedFile.event))\n {\n if (options.debug)\n {\n contractLogger.info('Attempting incremental update', {\n file: changedFile.path,\n event: changedFile.event\n });\n }\n\n // Try incremental update\n const success = await attemptIncrementalUpdate({\n cwd,\n contractsDir: fullContractsDir,\n outputPath: fullOutputPath,\n changedFilePath: changedFile.path,\n baseUrl: config.baseUrl,\n apiName,\n debug: options.debug\n });\n\n if (success)\n {\n if (options.debug)\n {\n contractLogger.info('Incremental update successful');\n }\n return;\n }\n\n // Fall through to full regeneration if incremental failed\n if (options.debug)\n {\n contractLogger.info('Incremental update failed, doing full regen');\n }\n }\n\n // Full regeneration\n const allContracts = await scanContracts(fullContractsDir, prefix);\n if (allContracts.length === 0)\n {\n if (options.debug)\n {\n contractLogger.warn('No contracts found');\n }\n\n contractCache = null;\n return;\n }\n\n // Generate client (apiName already calculated at start of function)\n const clientOptions = createClientOptions(fullContractsDir, fullOutputPath, config.baseUrl, apiName);\n const stats = await generateClient(allContracts, clientOptions);\n\n // Update cache\n contractCache = {\n contracts: allContracts,\n lastScan: Date.now()\n };\n\n if (options.debug)\n {\n contractLogger.info('Client generated', {\n endpoints: stats.methodsGenerated,\n resources: stats.resourcesGenerated,\n duration: stats.duration,\n mode: changedFile ? 'incremental-fallback' : 'full'\n });\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n contractLogger.error('Generation failed', err);\n throw err;\n }\n }\n };\n}\n\n/**\n * Options for incremental update\n */\ninterface IncrementalUpdateOptions\n{\n cwd: string;\n contractsDir: string;\n outputPath: string;\n changedFilePath: string;\n baseUrl?: string;\n apiName: string;\n debug?: boolean;\n}\n\n/**\n * Attempt incremental update for a single file change\n *\n * Strategy:\n * 1. Rescan the entire directory to get updated contracts\n * 2. Compare with cached contracts to find what changed\n * 3. Skip regeneration if no contract signatures changed (e.g., formatting only)\n * 4. Otherwise, do full client generation (contracts are interconnected)\n *\n * Returns true if successful, false if full regen is needed\n */\nasync function attemptIncrementalUpdate(options: IncrementalUpdateOptions): Promise<boolean>\n{\n const { cwd, contractsDir, outputPath, changedFilePath, baseUrl, apiName, debug } = options;\n\n if (!contractCache)\n {\n return false; // No cache, need full regen\n }\n\n try\n {\n const fullPath = join(cwd, changedFilePath);\n\n if (!existsSync(fullPath))\n {\n // File deleted during watch, need full regen\n return false;\n }\n\n // Rescan the entire directory to get updated contracts\n // (This is still faster than full client generation)\n const updatedContracts = await scanContracts(contractsDir);\n\n if (updatedContracts.length === 0)\n {\n contractCache = null;\n return false;\n }\n\n // Compare with cached contracts to find what changed\n const changedContracts = findChangedContracts(\n contractCache.contracts,\n updatedContracts,\n changedFilePath\n );\n\n if (changedContracts.size === 0)\n {\n if (debug)\n {\n contractLogger.info('No contract changes detected, skipping regeneration');\n }\n return true; // No changes, skip regen\n }\n\n // Regenerate everything since contracts are interconnected (apiName passed as parameter)\n // (A safer approach than trying to regenerate only affected resources)\n const clientOptions = createClientOptions(contractsDir, outputPath, baseUrl, apiName);\n const stats = await generateClient(updatedContracts, clientOptions);\n\n // Update cache\n contractCache = {\n contracts: updatedContracts,\n lastScan: Date.now()\n };\n\n if (debug)\n {\n contractLogger.info('Incremental update successful', {\n changedContracts: changedContracts.size,\n endpoints: stats.methodsGenerated,\n resources: stats.resourcesGenerated,\n duration: stats.duration\n });\n }\n\n return true;\n }\n catch (error)\n {\n if (debug)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n contractLogger.warn('Incremental update failed', err);\n }\n return false;\n }\n}\n\n/**\n * Find contracts that changed in the given file\n */\nfunction findChangedContracts(\n oldContracts: RouteContractMapping[],\n newContracts: RouteContractMapping[],\n changedFilePath: string\n): Set<string>\n{\n const changed = new Set<string>();\n\n // Find contracts from the changed file in both old and new\n const oldInFile = oldContracts.filter(c => c.contractFile?.includes(changedFilePath));\n const newInFile = newContracts.filter(c => c.contractFile?.includes(changedFilePath));\n\n // If contract count changed, mark all as changed\n if (oldInFile.length !== newInFile.length)\n {\n newInFile.forEach(c => changed.add(c.contractName));\n return changed;\n }\n\n // Compare contract signatures\n for (const newContract of newInFile)\n {\n const oldContract = oldInFile.find(c => c.contractName === newContract.contractName);\n\n if (!oldContract)\n {\n changed.add(newContract.contractName);\n continue;\n }\n\n // Check if contract signature changed\n if (\n oldContract.method !== newContract.method ||\n oldContract.path !== newContract.path ||\n oldContract.hasQuery !== newContract.hasQuery ||\n oldContract.hasBody !== newContract.hasBody ||\n oldContract.hasParams !== newContract.hasParams\n )\n {\n changed.add(newContract.contractName);\n }\n }\n\n return changed;\n}","/**\n * Codegen Configuration Loader\n *\n * Loads codegen configuration from .spfnrc.json or package.json\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createJiti } from 'jiti';\nimport type { Generator } from './generator.js';\nimport { logger } from '../../logger';\n\nconst configLogger = logger.child('config');\n\nexport interface CodegenConfig\n{\n generators?: Array<\n | { path: string } // Custom generator via file path\n | ({ name: string; enabled?: boolean } & Record<string, any>) // Package-based generator: \"package:name\" or built-in \"name\"\n >;\n}\n\n/**\n * Load codegen configuration from .spfnrc.json or package.json\n */\nexport function loadCodegenConfig(cwd: string): CodegenConfig\n{\n // 1. Check .spfnrc.json\n const rcPath = join(cwd, '.spfnrc.json');\n if (existsSync(rcPath))\n {\n try\n {\n const content = readFileSync(rcPath, 'utf-8');\n const config = JSON.parse(content);\n\n if (config.codegen)\n {\n configLogger.info('Loaded config from .spfnrc.json');\n return config.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse .spfnrc.json', error as Error);\n }\n }\n\n // 2. Check package.json\n const pkgPath = join(cwd, 'package.json');\n if (existsSync(pkgPath))\n {\n try\n {\n const content = readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n\n if (pkg.spfn?.codegen)\n {\n configLogger.info('Loaded config from package.json');\n return pkg.spfn.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse package.json', error as Error);\n }\n }\n\n // 3. Default configuration\n configLogger.info('Using default config');\n return {\n generators: [\n { name: '@spfn/core:contract', enabled: true }\n ]\n };\n}\n\n/**\n * Load generator from package\n *\n * Supports format: \"package:generator-name\" or \"@scope/package:generator-name\"\n */\nasync function loadGeneratorFromPackage(\n packageName: string,\n generatorName: string,\n config: Record<string, any>\n): Promise<Generator | null>\n{\n try\n {\n // Try to load package/generators export\n const generatorsModule = await import(`${packageName}/generators`);\n\n // Look for generator by name in registry\n if (generatorsModule.generators?.[generatorName])\n {\n const createFn = generatorsModule.generators[generatorName];\n const generator = createFn(config);\n configLogger.info(`Loaded ${packageName}:${generatorName}`);\n return generator;\n }\n\n // Fallback: try conventional name (createXxxGenerator)\n const conventionalName = `create${capitalize(generatorName)}Generator`;\n if (generatorsModule[conventionalName])\n {\n const createFn = generatorsModule[conventionalName];\n const generator = createFn(config);\n configLogger.info(`Loaded ${packageName}:${generatorName} (via ${conventionalName})`);\n return generator;\n }\n\n configLogger.warn(\n `Generator \"${generatorName}\" not found in ${packageName}/generators. ` +\n `Expected: generators.${generatorName} or ${conventionalName}`\n );\n return null;\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.warn(\n `Failed to load ${packageName}:${generatorName}. ` +\n `Make sure ${packageName} is installed. Error: ${err.message}`\n );\n return null;\n }\n}\n\n/**\n * Capitalize first letter\n */\nfunction capitalize(str: string): string\n{\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Create generator instances from configuration\n */\nexport async function createGeneratorsFromConfig(config: CodegenConfig, cwd: string): Promise<Generator[]>\n{\n const generators: Generator[] = [];\n\n if (!config.generators || config.generators.length === 0)\n {\n return generators;\n }\n\n for (const generatorConfig of config.generators)\n {\n try\n {\n // Custom generator (via file path)\n if ('path' in generatorConfig)\n {\n const generatorPath = generatorConfig.path.startsWith('.')\n ? join(cwd, generatorConfig.path)\n : generatorConfig.path;\n\n configLogger.info(`Loading custom generator: ${generatorPath}`);\n\n let module: any;\n\n // Use jiti for .ts files, regular import for .js\n if (generatorPath.endsWith('.ts'))\n {\n const jiti = createJiti(cwd, {\n interopDefault: true\n });\n module = jiti(generatorPath);\n }\n else\n {\n module = await import(generatorPath);\n }\n\n const createGenerator = module.default || module.createGenerator || module;\n\n if (typeof createGenerator === 'function')\n {\n const generator = createGenerator();\n generators.push(generator);\n configLogger.info(`Custom generator loaded: ${generator.name}`);\n }\n else\n {\n configLogger.warn(`Invalid generator at ${generatorPath}: expected function`);\n }\n }\n // Package-based generator: \"package:name\" or \"@scope/package:name\"\n else if ('name' in generatorConfig && generatorConfig.name.includes(':'))\n {\n if (generatorConfig.enabled !== false)\n {\n const [packageName, generatorName] = generatorConfig.name.split(':');\n const { enabled, name, ...generatorOptions } = generatorConfig;\n\n const generator = await loadGeneratorFromPackage(\n packageName,\n generatorName,\n generatorOptions\n );\n\n if (generator)\n {\n generators.push(generator);\n }\n }\n }\n // Unknown generator name format\n else if ('name' in generatorConfig)\n {\n configLogger.warn(\n `Invalid generator name \"${generatorConfig.name}\". ` +\n `Use package:name format (e.g., \"@spfn/core:contract\")`\n );\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.error('Failed to load generator', err);\n }\n }\n\n return generators;\n}"]}
|
|
1
|
+
{"version":3,"sources":["../../src/logger/adapters/pino.ts","../../src/logger/types.ts","../../src/logger/formatters.ts","../../src/logger/logger.ts","../../src/logger/transports/console.ts","../../src/logger/transports/file.ts","../../src/logger/config.ts","../../src/logger/adapters/custom.ts","../../src/logger/adapter-factory.ts","../../src/codegen/core/orchestrator.ts","../../src/codegen/built-in/contract/scanner.ts","../../src/codegen/built-in/contract/helpers.ts","../../src/codegen/built-in/contract/emitter.ts","../../src/codegen/built-in/contract/index.ts","../../src/codegen/core/config-loader.ts"],"names":["newPath","existsSync","mkdirSync","join","unlinkSync","chokidarWatch","capitalize","readFileSync"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Pino Logger Adapter\n *\n * High-performance logger adapter using Pino with pretty-print for development and JSON for production.\n */\n\nimport pino from 'pino';\nimport type { LoggerAdapter, AdapterConfig, LogLevel } from './types';\n\n/**\n * Pino Logger Adapter\n */\nexport class PinoAdapter implements LoggerAdapter\n{\n private logger: pino.Logger;\n\n constructor(config: AdapterConfig)\n {\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n // Try to use pino-pretty in development if available (optional dependency)\n const transport = isDevelopment ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'HH:MM:ss.l',\n ignore: 'pid,hostname',\n singleLine: false,\n messageFormat: '{module} {msg}',\n errorLikeObjectKeys: ['err', 'error'],\n },\n } : undefined;\n\n // Development: pretty print (if pino-pretty available) or JSON\n // Production: JSON output\n try\n {\n this.logger = pino({\n level: config.level,\n\n // 기본 필드\n base: config.module ? { module: config.module } : undefined,\n\n // Transport (pretty print in development if available)\n transport,\n });\n }\n catch (error)\n {\n // Fallback: pino-pretty not available, use plain JSON\n this.logger = pino({\n level: config.level,\n base: config.module ? { module: config.module } : undefined,\n });\n }\n }\n\n child(module: string): LoggerAdapter\n {\n const childLogger = new PinoAdapter({ level: this.logger.level as LogLevel, module });\n childLogger.logger = this.logger.child({ module });\n return childLogger;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(context || {}, message);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(context || {}, message);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.warn(errorOrContext || {}, message);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.error(errorOrContext || {}, message);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.fatal(errorOrContext || {}, message);\n }\n }\n\n async close(): Promise<void>\n {\n // Pino는 자동으로 flush됨\n // 필요시 pino.final() 사용 가능\n }\n}","/**\n * Logger Type Definitions\n *\n * 로깅 시스템 타입 정의\n *\n * ✅ 구현 완료:\n * - LogLevel 타입 정의\n * - LogMetadata 인터페이스\n * - Transport 인터페이스\n * - 환경별 설정 타입\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현체)\n * - src/logger/config.ts (설정)\n */\n\n/**\n * 로그 레벨\n * debug < info < warn < error < fatal\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * 로그 레벨 우선순위\n */\nexport const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n fatal: 4,\n};\n\n/**\n * 로그 메타데이터\n */\nexport interface LogMetadata\n{\n timestamp: Date;\n level: LogLevel;\n message: string;\n module?: string;\n error?: Error;\n context?: Record<string, unknown>;\n}\n\n/**\n * Transport 인터페이스\n * 모든 Transport는 이 인터페이스를 구현해야 함\n */\nexport interface Transport\n{\n /**\n * Transport 이름\n */\n name: string;\n\n /**\n * 최소 로그 레벨 (이 레벨 이상만 처리)\n */\n level: LogLevel;\n\n /**\n * 활성화 여부\n */\n enabled: boolean;\n\n /**\n * 로그 처리 함수\n */\n log(metadata: LogMetadata): Promise<void>;\n\n /**\n * Transport 종료 (리소스 정리)\n */\n close?(): Promise<void>;\n}\n\n/**\n * Logger 설정\n */\nexport interface LoggerConfig\n{\n /**\n * 기본 로그 레벨\n */\n level: LogLevel;\n\n /**\n * 모듈명 (context)\n */\n module?: string;\n\n /**\n * Transport 리스트\n */\n transports: Transport[];\n}\n\n/**\n * Transport 설정 (공통)\n */\nexport interface TransportConfig\n{\n level: LogLevel;\n enabled: boolean;\n}\n\n/**\n * Console Transport 설정\n */\nexport interface ConsoleTransportConfig extends TransportConfig\n{\n colorize?: boolean;\n}\n\n/**\n * File Transport 설정\n */\nexport interface FileTransportConfig extends TransportConfig\n{\n logDir: string;\n maxFileSize?: number; // bytes\n maxFiles?: number; // 최대 로그 파일 개수\n}\n\n/**\n * Slack Transport 설정\n */\nexport interface SlackTransportConfig extends TransportConfig\n{\n webhookUrl: string;\n channel?: string;\n username?: string;\n}\n\n/**\n * Email Transport 설정\n */\nexport interface EmailTransportConfig extends TransportConfig\n{\n from: string;\n to: string[];\n smtpHost: string;\n smtpPort: number;\n smtpUser?: string;\n smtpPassword?: string;\n}","/**\n * Logger Formatters\n *\n * Log formatting utilities for console, JSON, Slack, and Email outputs with sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata } from './types';\n\n/**\n * 민감 정보로 간주되는 키 목록\n * 이 키들을 포함하는 필드는 자동으로 마스킹됨\n */\nconst SENSITIVE_KEYS = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'accesstoken',\n 'access_token',\n 'refreshtoken',\n 'refresh_token',\n 'authorization',\n 'auth',\n 'cookie',\n 'session',\n 'sessionid',\n 'session_id',\n 'privatekey',\n 'private_key',\n 'creditcard',\n 'credit_card',\n 'cardnumber',\n 'card_number',\n 'cvv',\n 'ssn',\n 'pin',\n];\n\n/**\n * 마스킹된 값\n */\nconst MASKED_VALUE = '***MASKED***';\n\n/**\n * 키가 민감 정보를 포함하는지 확인\n */\nfunction isSensitiveKey(key: string): boolean\n{\n const lowerKey = key.toLowerCase();\n return SENSITIVE_KEYS.some(sensitive => lowerKey.includes(sensitive));\n}\n\n/**\n * 민감 정보 마스킹\n * Context 객체에서 민감한 정보(비밀번호, 토큰 등)를 마스킹\n *\n * @param data - 원본 데이터\n * @returns 마스킹된 데이터\n */\nexport function maskSensitiveData(data: unknown): unknown\n{\n // null, undefined 처리\n if (data === null || data === undefined)\n {\n return data;\n }\n\n // 배열 처리\n if (Array.isArray(data))\n {\n return data.map(item => maskSensitiveData(item));\n }\n\n // 객체 처리\n if (typeof data === 'object')\n {\n const masked: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data))\n {\n if (isSensitiveKey(key))\n {\n // 민감 정보 키는 마스킹\n masked[key] = MASKED_VALUE;\n }\n else if (typeof value === 'object' && value !== null)\n {\n // 중첩된 객체는 재귀 처리\n masked[key] = maskSensitiveData(value);\n }\n else\n {\n // 일반 값은 그대로 유지\n masked[key] = value;\n }\n }\n\n return masked;\n }\n\n // 기본 타입은 그대로 반환\n return data;\n}\n\n/**\n * ANSI 컬러 코드\n */\nconst COLORS = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n\n // 로그 레벨 컬러\n debug: '\\x1b[36m', // cyan\n info: '\\x1b[32m', // green\n warn: '\\x1b[33m', // yellow\n error: '\\x1b[31m', // red\n fatal: '\\x1b[35m', // magenta\n\n // 추가 컬러\n gray: '\\x1b[90m',\n};\n\n/**\n * 로그 레벨을 컬러 문자열로 변환\n */\nexport function colorizeLevel(level: LogLevel): string\n{\n const color = COLORS[level];\n const levelStr = level.toUpperCase().padEnd(5);\n return `${color}${levelStr}${COLORS.reset}`;\n}\n\n/**\n * 타임스탬프 포맷 (ISO 8601)\n */\nexport function formatTimestamp(date: Date): string\n{\n return date.toISOString();\n}\n\n/**\n * 타임스탬프 포맷 (사람이 읽기 쉬운 형식)\n */\nexport function formatTimestampHuman(date: Date): string\n{\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n const seconds = String(date.getSeconds()).padStart(2, '0');\n const ms = String(date.getMilliseconds()).padStart(3, '0');\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`;\n}\n\n/**\n * 에러 객체를 문자열로 변환 (스택 트레이스 포함)\n */\nexport function formatError(error: Error): string\n{\n const lines: string[] = [];\n\n lines.push(`${error.name}: ${error.message}`);\n\n if (error.stack)\n {\n const stackLines = error.stack.split('\\n').slice(1);\n lines.push(...stackLines);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Context 객체를 문자열로 변환\n */\nexport function formatContext(context: Record<string, unknown>): string\n{\n try\n {\n return JSON.stringify(context, null, 2);\n }\n catch (error)\n {\n return '[Context serialization failed]';\n }\n}\n\n/**\n * 콘솔용 컬러 포맷\n */\nexport function formatConsole(metadata: LogMetadata, colorize = true): string\n{\n const parts: string[] = [];\n\n // [타임스탬프]\n const timestamp = formatTimestampHuman(metadata.timestamp);\n if (colorize)\n {\n parts.push(`${COLORS.gray}[${timestamp}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${timestamp}]`);\n }\n\n // [module=value]\n if (metadata.module)\n {\n if (colorize)\n {\n parts.push(`${COLORS.dim}[module=${metadata.module}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[module=${metadata.module}]`);\n }\n }\n\n // Context를 각각 [key=value] 형태로 추가\n if (metadata.context && Object.keys(metadata.context).length > 0)\n {\n Object.entries(metadata.context).forEach(([key, value]) =>\n {\n const valueStr = typeof value === 'string' ? value : String(value);\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Slack 메시지 포맷\n */\nexport function formatSlack(metadata: LogMetadata): string\n{\n const emoji = {\n debug: ':bug:',\n info: ':information_source:',\n warn: ':warning:',\n error: ':x:',\n fatal: ':fire:',\n };\n\n const parts: string[] = [];\n\n parts.push(`${emoji[metadata.level]} *${metadata.level.toUpperCase()}*`);\n\n if (metadata.module)\n {\n parts.push(`\\`[${metadata.module}]\\``);\n }\n\n parts.push(metadata.message);\n\n let message = parts.join(' ');\n\n if (metadata.context)\n {\n message += '\\n```\\n' + JSON.stringify(metadata.context, null, 2) + '\\n```';\n }\n\n if (metadata.error)\n {\n message += '\\n```\\n' + formatError(metadata.error) + '\\n```';\n }\n\n return message;\n}\n\n/**\n * Email 제목 생성\n */\nexport function formatEmailSubject(metadata: LogMetadata): string\n{\n const prefix = `[${metadata.level.toUpperCase()}]`;\n const module = metadata.module ? `[${metadata.module}]` : '';\n\n return `${prefix}${module} ${metadata.message}`;\n}\n\n/**\n * Email 본문 생성 (HTML)\n */\nexport function formatEmailBody(metadata: LogMetadata): string\n{\n const parts: string[] = [];\n\n parts.push('<html>');\n parts.push('<body style=\"font-family: monospace; padding: 20px;\">');\n\n // 헤더\n parts.push(`<h2 style=\"color: ${getEmailColor(metadata.level)};\">`);\n parts.push(`${metadata.level.toUpperCase()}`);\n parts.push('</h2>');\n\n // 시간\n parts.push('<p>');\n parts.push(`<strong>Timestamp:</strong> ${formatTimestamp(metadata.timestamp)}`);\n parts.push('</p>');\n\n // 모듈\n if (metadata.module)\n {\n parts.push('<p>');\n parts.push(`<strong>Module:</strong> ${metadata.module}`);\n parts.push('</p>');\n }\n\n // 메시지\n parts.push('<p>');\n parts.push(`<strong>Message:</strong> ${metadata.message}`);\n parts.push('</p>');\n\n // Context\n if (metadata.context)\n {\n parts.push('<h3>Context</h3>');\n parts.push('<pre style=\"background: #f4f4f4; padding: 10px; border-radius: 4px;\">');\n parts.push(JSON.stringify(metadata.context, null, 2));\n parts.push('</pre>');\n }\n\n // 에러\n if (metadata.error)\n {\n parts.push('<h3>Error Stack Trace</h3>');\n parts.push('<pre style=\"background: #fff0f0; padding: 10px; border-radius: 4px;\">');\n parts.push(formatError(metadata.error));\n parts.push('</pre>');\n }\n\n parts.push('</body>');\n parts.push('</html>');\n\n return parts.join('\\n');\n}\n\n/**\n * Email 레벨별 컬러\n */\nfunction getEmailColor(level: LogLevel): string\n{\n const colors: Record<LogLevel, string> = {\n debug: '#00BCD4',\n info: '#4CAF50',\n warn: '#FF9800',\n error: '#F44336',\n fatal: '#9C27B0',\n };\n\n return colors[level];\n}","/**\n * Logger Class\n *\n * Central logging class with multiple transports, child loggers, and sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata, LoggerConfig, Transport } from './types';\nimport { LOG_LEVEL_PRIORITY } from './types';\nimport { maskSensitiveData } from './formatters';\n\n/**\n * Logger class\n */\nexport class Logger\n{\n private readonly config: LoggerConfig;\n private readonly module?: string;\n\n constructor(config: LoggerConfig)\n {\n this.config = config;\n this.module = config.module;\n }\n\n /**\n * Get current log level\n */\n get level(): LogLevel\n {\n return this.config.level;\n }\n\n /**\n * Create child logger (per module)\n */\n child(module: string): Logger\n {\n return new Logger({\n ...this.config,\n module,\n });\n }\n\n /**\n * Debug log\n */\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.log('debug', message, undefined, context);\n }\n\n /**\n * Info log\n */\n info(message: string, context?: Record<string, unknown>): void\n {\n this.log('info', message, undefined, context);\n }\n\n /**\n * Warn log\n */\n warn(message: string, context?: Record<string, unknown>): void;\n warn(message: string, error: Error, context?: Record<string, unknown>): void;\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('warn', message, errorOrContext, context);\n }\n else\n {\n this.log('warn', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Error log\n */\n error(message: string, context?: Record<string, unknown>): void;\n error(message: string, error: Error, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('error', message, errorOrContext, context);\n }\n else\n {\n this.log('error', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Fatal log\n */\n fatal(message: string, context?: Record<string, unknown>): void;\n fatal(message: string, error: Error, context?: Record<string, unknown>): void;\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('fatal', message, errorOrContext, context);\n }\n else\n {\n this.log('fatal', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Log processing (internal)\n */\n private log(level: LogLevel, message: string, error?: Error, context?: Record<string, unknown>): void\n {\n // Early return if log level is below configured level\n // This prevents unnecessary metadata creation and processing\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level])\n {\n return;\n }\n\n const metadata: LogMetadata = {\n timestamp: new Date(),\n level,\n message,\n module: this.module,\n error,\n // Mask sensitive information in context to prevent credential leaks\n context: context ? maskSensitiveData(context) as Record<string, unknown> : undefined,\n };\n\n // Pass to all enabled Transports\n this.processTransports(metadata);\n }\n\n /**\n * Process Transports\n */\n private processTransports(metadata: LogMetadata): void\n {\n const promises = this.config.transports\n .filter(transport => transport.enabled)\n .map(transport => this.safeTransportLog(transport, metadata));\n\n // Async processing to prevent Transport errors from blocking logs\n Promise.all(promises).catch(error =>\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport error: ${errorMessage}\\n`);\n });\n }\n\n /**\n * Transport log (error-safe)\n */\n private async safeTransportLog(transport: Transport, metadata: LogMetadata): Promise<void>\n {\n try\n {\n await transport.log(metadata);\n }\n catch (error)\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport \"${transport.name}\" failed: ${errorMessage}\\n`);\n }\n }\n\n /**\n * Close all Transports\n */\n async close(): Promise<void>\n {\n const closePromises = this.config.transports\n .filter(transport => transport.close)\n .map(transport => transport.close!());\n\n await Promise.all(closePromises);\n }\n}","/**\n * Console Transport\n *\n * 콘솔 출력 Transport\n *\n * ✅ 구현 완료:\n * - 콘솔 출력 (stdout/stderr)\n * - 컬러 출력 지원\n * - 로그 레벨별 스트림 분리 (warn/error/fatal → stderr)\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (Transport 인터페이스)\n * - src/logger/formatters.ts (포맷터)\n * - src/logger/config.ts (설정)\n */\n\nimport type { Transport, LogMetadata, LogLevel, ConsoleTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatConsole } from '../formatters';\n\n/**\n * Console Transport\n */\nexport class ConsoleTransport implements Transport\n{\n public readonly name = 'console';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private colorize: boolean;\n\n constructor(config: ConsoleTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.colorize = config.colorize ?? true;\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // 포맷팅\n const message = formatConsole(metadata, this.colorize);\n\n // warn/error/fatal은 stderr로, 나머지는 stdout으로\n if (metadata.level === 'warn' || metadata.level === 'error' || metadata.level === 'fatal')\n {\n console.error(message);\n }\n else\n {\n console.log(message);\n }\n }\n}","/**\n * File Transport\n *\n * File output transport with date and size-based rotation, automatic cleanup.\n */\n\nimport { createWriteStream, existsSync, mkdirSync, statSync, readdirSync, unlinkSync, renameSync } from 'fs';\nimport type { WriteStream } from 'fs';\nimport { join } from 'path';\nimport type { Transport, LogMetadata, LogLevel, FileTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatJSON } from '../formatters';\n\n/**\n * File Transport\n */\nexport class FileTransport implements Transport\n{\n public readonly name = 'file';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private readonly logDir: string;\n private readonly maxFileSize: number;\n private readonly maxFiles: number;\n private currentStream: WriteStream | null = null;\n private currentFilename: string | null = null;\n\n constructor(config: FileTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.logDir = config.logDir;\n this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024; // 10MB\n this.maxFiles = config.maxFiles ?? 10;\n\n // 로그 디렉토리가 없으면 생성\n if (!existsSync(this.logDir))\n {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // JSON 포맷으로 변환\n const message = formatJSON(metadata);\n\n // 파일명: YYYY-MM-DD.log\n const filename = this.getLogFilename(metadata.timestamp);\n\n // 날짜가 변경되면 스트림 교체\n if (this.currentFilename !== filename)\n {\n await this.rotateStream(filename);\n await this.cleanOldFiles(); // 오래된 파일 정리\n }\n // 파일 크기 체크 및 로테이션\n else if (this.currentFilename)\n {\n await this.checkAndRotateBySize();\n }\n\n // 스트림에 쓰기\n if (this.currentStream)\n {\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.write(message + '\\n', 'utf-8', (error: Error | null | undefined) =>\n {\n if (error)\n {\n // 파일 쓰기 실패 시 stderr로 출력 (fallback)\n process.stderr.write(`[FileTransport] Failed to write log: ${error.message}\\n`);\n reject(error);\n }\n else\n {\n resolve();\n }\n });\n });\n }\n }\n\n /**\n * 스트림 교체 (날짜 변경 시)\n */\n private async rotateStream(filename: string): Promise<void>\n {\n // 기존 스트림 닫기\n if (this.currentStream)\n {\n await this.closeStream();\n }\n\n // 새 스트림 생성\n const filepath = join(this.logDir, filename);\n\n this.currentStream = createWriteStream(filepath, {\n flags: 'a', // append mode\n encoding: 'utf-8',\n });\n\n this.currentFilename = filename;\n\n // 스트림 에러 핸들링\n this.currentStream.on('error', (error) =>\n {\n process.stderr.write(`[FileTransport] Stream error: ${error.message}\\n`);\n // 에러 발생 시 스트림 초기화\n this.currentStream = null;\n this.currentFilename = null;\n });\n }\n\n /**\n * 현재 스트림 닫기\n */\n private async closeStream(): Promise<void>\n {\n if (!this.currentStream)\n {\n return;\n }\n\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.end((error: Error | null | undefined) =>\n {\n if (error)\n {\n reject(error);\n }\n else\n {\n this.currentStream = null;\n this.currentFilename = null;\n resolve();\n }\n });\n });\n }\n\n /**\n * 파일 크기 체크 및 크기 기반 로테이션\n */\n private async checkAndRotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n const filepath = join(this.logDir, this.currentFilename);\n\n // 파일이 존재하지 않으면 스킵\n if (!existsSync(filepath))\n {\n return;\n }\n\n try\n {\n const stats = statSync(filepath);\n\n // 파일 크기가 maxFileSize를 초과하면 로테이션\n if (stats.size >= this.maxFileSize)\n {\n await this.rotateBySize();\n }\n }\n catch (error)\n {\n // 파일 stat 실패 시 무시\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 크기 기반 로테이션 수행\n * 예: 2025-01-01.log -> 2025-01-01.1.log, 2025-01-01.1.log -> 2025-01-01.2.log\n */\n private async rotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n // 기존 스트림 닫기\n await this.closeStream();\n\n const baseName = this.currentFilename.replace(/\\.log$/, '');\n const files = readdirSync(this.logDir);\n\n // 현재 날짜의 로그 파일들 찾기 (예: 2025-01-01.log, 2025-01-01.1.log, ...)\n const relatedFiles = files\n .filter(file => file.startsWith(baseName) && file.endsWith('.log'))\n .sort()\n .reverse(); // 역순 정렬로 높은 번호부터 처리\n\n // 기존 파일들을 번호 증가시켜 이동 (예: .1.log -> .2.log)\n for (const file of relatedFiles)\n {\n const match = file.match(/\\.(\\d+)\\.log$/);\n if (match)\n {\n const oldNum = parseInt(match[1], 10);\n const newNum = oldNum + 1;\n const oldPath = join(this.logDir, file);\n const newPath = join(this.logDir, `${baseName}.${newNum}.log`);\n\n try\n {\n renameSync(oldPath, newPath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}\\n`);\n }\n }\n }\n\n // 현재 파일을 .1.log로 이동\n const currentPath = join(this.logDir, this.currentFilename);\n const newPath = join(this.logDir, `${baseName}.1.log`);\n\n try\n {\n if (existsSync(currentPath))\n {\n renameSync(currentPath, newPath);\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}\\n`);\n }\n\n // 새 스트림 생성 (동일한 파일명으로)\n await this.rotateStream(this.currentFilename);\n }\n\n /**\n * 오래된 로그 파일 정리\n * maxFiles 개수를 초과하는 로그 파일 삭제\n */\n private async cleanOldFiles(): Promise<void>\n {\n try\n {\n // 디렉토리가 존재하지 않으면 스킵\n if (!existsSync(this.logDir))\n {\n return;\n }\n\n const files = readdirSync(this.logDir);\n\n // .log로 끝나는 파일만 필터링 후 수정 시간 기준 정렬\n const logFiles = files\n .filter(file => file.endsWith('.log'))\n .map(file =>\n {\n const filepath = join(this.logDir, file);\n const stats = statSync(filepath);\n return { file, mtime: stats.mtime };\n })\n .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); // 최신 파일이 앞으로\n\n // maxFiles를 초과하는 오래된 파일들 삭제\n if (logFiles.length > this.maxFiles)\n {\n const filesToDelete = logFiles.slice(this.maxFiles);\n\n for (const { file } of filesToDelete)\n {\n const filepath = join(this.logDir, file);\n try\n {\n unlinkSync(filepath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to delete old file \"${file}\": ${errorMessage}\\n`);\n }\n }\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 날짜별 로그 파일명 생성\n */\n private getLogFilename(date: Date): string\n {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}.log`;\n }\n\n async close(): Promise<void>\n {\n // 스트림 정리\n await this.closeStream();\n }\n}","/**\n * Logger Configuration\n *\n * Environment-based logger configuration with validation for console, file, Slack, and Email transports.\n */\n\nimport { existsSync, accessSync, constants, mkdirSync, writeFileSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type {\n LogLevel,\n ConsoleTransportConfig,\n FileTransportConfig,\n SlackTransportConfig,\n EmailTransportConfig,\n} from './types';\n\n/**\n * Check if file logging is enabled (for self-hosted)\n */\nexport function isFileLoggingEnabled(): boolean\n{\n return process.env.LOGGER_FILE_ENABLED === 'true';\n}\n\n/**\n * Get default log level by environment\n */\nexport function getDefaultLogLevel(): LogLevel\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment)\n {\n return 'debug';\n }\n\n if (isProduction)\n {\n return 'info';\n }\n\n // Test environment\n return 'warn';\n}\n\n/**\n * Console Transport configuration\n */\nexport function getConsoleConfig(): ConsoleTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'debug',\n enabled: true,\n colorize: !isProduction, // Dev: colored output, Production: plain text\n };\n}\n\n/**\n * File Transport configuration\n */\nexport function getFileConfig(): FileTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'info',\n enabled: isProduction, // File logging in production only\n logDir: process.env.LOG_DIR || './logs',\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n };\n}\n\n/**\n * Slack Transport configuration\n */\nexport function getSlackConfig(): SlackTransportConfig | null\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return null; // Disabled if not configured\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'error', // Send error and above to Slack\n enabled: isProduction, // Enabled in production only\n webhookUrl,\n channel: process.env.SLACK_CHANNEL,\n username: process.env.SLACK_USERNAME || 'Logger Bot',\n };\n}\n\n/**\n * Email Transport configuration\n */\nexport function getEmailConfig(): EmailTransportConfig | null\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // Disabled if required settings are missing\n if (!smtpHost || !smtpPort || !emailFrom || !emailTo)\n {\n return null;\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'fatal', // Send fatal level only via email\n enabled: isProduction, // Enabled in production only\n from: emailFrom,\n to: emailTo.split(',').map(email => email.trim()),\n smtpHost,\n smtpPort: parseInt(smtpPort, 10),\n smtpUser: process.env.SMTP_USER,\n smtpPassword: process.env.SMTP_PASSWORD,\n };\n}\n\n/**\n * Validate directory path and write permissions\n */\nfunction validateDirectoryWritable(dirPath: string): void\n{\n // Check if directory exists\n if (!existsSync(dirPath))\n {\n // Try to create directory\n try\n {\n mkdirSync(dirPath, { recursive: true });\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to create log directory \"${dirPath}\": ${errorMessage}`);\n }\n }\n\n // Check write permission\n try\n {\n accessSync(dirPath, constants.W_OK);\n }\n catch\n {\n throw new Error(`Log directory \"${dirPath}\" is not writable. Please check permissions.`);\n }\n\n // Try to write a test file\n const testFile = join(dirPath, '.logger-write-test');\n try\n {\n writeFileSync(testFile, 'test', 'utf-8');\n unlinkSync(testFile);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Cannot write to log directory \"${dirPath}\": ${errorMessage}`);\n }\n}\n\n/**\n * Validate file transport configuration\n */\nfunction validateFileConfig(): void\n{\n if (!isFileLoggingEnabled())\n {\n return; // File logging disabled, skip validation\n }\n\n const logDir = process.env.LOG_DIR;\n\n // Check if LOG_DIR is set\n if (!logDir)\n {\n throw new Error(\n 'LOG_DIR environment variable is required when LOGGER_FILE_ENABLED=true. ' +\n 'Example: LOG_DIR=/var/log/myapp'\n );\n }\n\n // Validate directory\n validateDirectoryWritable(logDir);\n}\n\n/**\n * Validate Slack transport configuration\n */\nfunction validateSlackConfig(): void\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return; // Slack disabled, skip validation\n }\n\n // Validate webhook URL format\n if (!webhookUrl.startsWith('https://hooks.slack.com/'))\n {\n throw new Error(\n `Invalid SLACK_WEBHOOK_URL: \"${webhookUrl}\". ` +\n 'Slack webhook URLs must start with \"https://hooks.slack.com/\"'\n );\n }\n}\n\n/**\n * Validate Email transport configuration\n */\nfunction validateEmailConfig(): void\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // If any email config is set, all required fields must be present\n const hasAnyEmailConfig = smtpHost || smtpPort || emailFrom || emailTo;\n if (!hasAnyEmailConfig)\n {\n return; // Email disabled, skip validation\n }\n\n // Validate all required fields\n const missingFields: string[] = [];\n if (!smtpHost) missingFields.push('SMTP_HOST');\n if (!smtpPort) missingFields.push('SMTP_PORT');\n if (!emailFrom) missingFields.push('EMAIL_FROM');\n if (!emailTo) missingFields.push('EMAIL_TO');\n\n if (missingFields.length > 0)\n {\n throw new Error(\n `Email transport configuration incomplete. Missing: ${missingFields.join(', ')}. ` +\n 'Either set all required fields or remove all email configuration.'\n );\n }\n\n // Validate SMTP port is a number\n const port = parseInt(smtpPort!, 10);\n if (isNaN(port) || port < 1 || port > 65535)\n {\n throw new Error(\n `Invalid SMTP_PORT: \"${smtpPort}\". Must be a number between 1 and 65535.`\n );\n }\n\n // Validate email format (basic check)\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(emailFrom!))\n {\n throw new Error(`Invalid EMAIL_FROM format: \"${emailFrom}\"`);\n }\n\n // Validate email recipients\n const recipients = emailTo!.split(',').map(e => e.trim());\n for (const email of recipients)\n {\n if (!emailRegex.test(email))\n {\n throw new Error(`Invalid email address in EMAIL_TO: \"${email}\"`);\n }\n }\n}\n\n/**\n * Validate environment variables\n */\nfunction validateEnvironment(): void\n{\n const nodeEnv = process.env.NODE_ENV;\n\n if (!nodeEnv)\n {\n process.stderr.write(\n '[Logger] Warning: NODE_ENV is not set. Defaulting to test environment.\\n'\n );\n }\n // Allow any NODE_ENV value (development, production, test, staging, local, etc.)\n // No validation needed - users can use custom environments\n}\n\n/**\n * Validate all logger configuration\n * Throws an error if configuration is invalid\n */\nexport function validateConfig(): void\n{\n try\n {\n validateEnvironment();\n validateFileConfig();\n validateSlackConfig();\n validateEmailConfig();\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n throw new Error(`[Logger] Configuration validation failed: ${error.message}`);\n }\n throw error;\n }\n}","/**\n * Custom Logger Adapter\n *\n * 자체 구현한 Logger를 사용하는 Adapter\n *\n * ✅ 구현 완료:\n * - 기존 Logger 클래스 래핑\n * - Transport 시스템 (Console, File)\n * - Child logger 지원\n *\n * 💡 용도:\n * - Pino 의존성 제거 필요시\n * - 커스텀 Transport 필요시\n * - 완전한 제어가 필요한 경우\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현)\n * - src/logger/adapters/types.ts (인터페이스)\n */\n\nimport { Logger } from '../logger';\nimport { ConsoleTransport } from '../transports/console';\nimport { FileTransport } from '../transports/file';\nimport { getConsoleConfig, getFileConfig } from '../config';\nimport type { LoggerAdapter, AdapterConfig } from './types';\nimport type { Transport } from '../types';\n\n/**\n * Transport 초기화\n */\nfunction initializeTransports(): Transport[]\n{\n const transports: Transport[] = [];\n\n // Console Transport (항상 활성화)\n const consoleConfig = getConsoleConfig();\n transports.push(new ConsoleTransport(consoleConfig));\n\n // File Transport (프로덕션에서만 활성화)\n const fileConfig = getFileConfig();\n if (fileConfig.enabled)\n {\n transports.push(new FileTransport(fileConfig));\n }\n\n return transports;\n}\n\n/**\n * Custom Logger Adapter\n */\nexport class CustomAdapter implements LoggerAdapter\n{\n private logger: Logger;\n\n constructor(config: AdapterConfig)\n {\n this.logger = new Logger({\n level: config.level,\n module: config.module,\n transports: initializeTransports(),\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const adapter = new CustomAdapter({ level: this.logger.level, module });\n adapter.logger = this.logger.child(module);\n return adapter;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(message, context);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn(message, errorOrContext, context);\n }\n else\n {\n this.logger.warn(message, errorOrContext);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error(message, errorOrContext, context);\n }\n else\n {\n this.logger.error(message, errorOrContext);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal(message, errorOrContext, context);\n }\n else\n {\n this.logger.fatal(message, errorOrContext);\n }\n }\n\n async close(): Promise<void>\n {\n await this.logger.close();\n }\n}","/**\n * Logger Adapter Factory\n *\n * Adapter creation and initialization logic\n */\n\nimport { PinoAdapter } from './adapters/pino.js';\nimport { CustomAdapter } from './adapters/custom.js';\nimport { getDefaultLogLevel, validateConfig } from './config.js';\nimport type { LoggerAdapter } from './adapters/types.js';\n\n/**\n * Adapter type\n */\ntype AdapterType = 'pino' | 'custom';\n\n/**\n * Create adapter instance\n */\nfunction createAdapter(type: AdapterType): LoggerAdapter\n{\n const level = getDefaultLogLevel();\n\n switch (type)\n {\n case 'pino':\n return new PinoAdapter({ level });\n\n case 'custom':\n return new CustomAdapter({ level });\n\n default:\n return new PinoAdapter({ level });\n }\n}\n\n/**\n * Read adapter type from environment variable\n */\nfunction getAdapterType(): AdapterType\n{\n const adapterEnv = process.env.LOGGER_ADAPTER as AdapterType;\n\n if (adapterEnv === 'custom' || adapterEnv === 'pino')\n {\n return adapterEnv;\n }\n\n // Default: pino\n return 'pino';\n}\n\n/**\n * Initialize logger with configuration validation\n */\nfunction initializeLogger(): LoggerAdapter\n{\n // Validate configuration before creating logger\n validateConfig();\n\n // Create and return logger instance\n return createAdapter(getAdapterType());\n}\n\n/**\n * Singleton Logger instance\n */\nexport const logger: LoggerAdapter = initializeLogger();","/**\n * Codegen Orchestrator\n *\n * Manages multiple code generators and coordinates their execution\n */\n\nimport { watch as chokidarWatch } from 'chokidar';\nimport { join, relative } from 'path';\nimport mm from 'micromatch';\nimport type { Generator, GeneratorOptions, GeneratorTrigger } from './generator.js';\nimport { logger } from '../../logger';\n\nconst orchestratorLogger = logger.child('orchestrator');\n\nexport interface OrchestratorOptions\n{\n /** List of generators to orchestrate */\n generators: Generator[];\n\n /** Project root directory */\n cwd?: string;\n\n /** Enable debug logging */\n debug?: boolean;\n}\n\nexport class CodegenOrchestrator\n{\n private readonly generators: Generator[];\n private readonly cwd: string;\n private readonly debug: boolean;\n private isGenerating = false;\n private pendingRegenerations = new Set<string>();\n\n constructor(options: OrchestratorOptions)\n {\n this.generators = options.generators;\n this.cwd = options.cwd ?? process.cwd();\n this.debug = options.debug ?? false;\n }\n\n /**\n * Check if generator should run for given trigger\n */\n private shouldRun(generator: Generator, trigger: GeneratorTrigger): boolean\n {\n const runOn = generator.runOn ?? ['watch', 'manual', 'build'];\n return runOn.includes(trigger);\n }\n\n /**\n * Run all generators once\n *\n * @param trigger - How the generators are being triggered\n */\n async generateAll(trigger: GeneratorTrigger = 'manual'): Promise<void>\n {\n if (this.debug)\n {\n orchestratorLogger.info('Running all generators', {\n count: this.generators.length,\n names: this.generators.map(g => g.name),\n trigger\n });\n }\n\n for (const generator of this.generators)\n {\n // Check if generator should run for this trigger\n if (!this.shouldRun(generator, trigger))\n {\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Skipped (runOn: ${generator.runOn?.join(', ') ?? 'default'})`);\n }\n continue;\n }\n\n try\n {\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug,\n trigger: {\n type: trigger\n }\n };\n\n await generator.generate(genOptions);\n\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Generated successfully`);\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] Generation failed`, err);\n }\n }\n }\n\n /**\n * Start watch mode\n */\n async watch(): Promise<void>\n {\n // Initial generation with 'watch' trigger\n await this.generateAll('watch');\n\n // Collect all watch patterns from generators\n const allPatterns = this.generators.flatMap(g => g.watchPatterns);\n\n if (allPatterns.length === 0)\n {\n orchestratorLogger.warn('No watch patterns defined, exiting watch mode');\n return;\n }\n\n // Extract directories to watch from patterns\n // For pattern like \"watched/**/*.ts\", watch \"watched\" directory\n const dirsToWatch = new Set<string>();\n for (const pattern of allPatterns)\n {\n // Extract base directory from glob pattern (e.g., \"src/**/*.ts\" -> \"src\")\n const baseDir = pattern.split('**')[0].replace(/\\/$/, '') || '.';\n dirsToWatch.add(join(this.cwd, baseDir));\n }\n\n const watchDirs = Array.from(dirsToWatch);\n\n if (this.debug)\n {\n orchestratorLogger.info('Starting watch mode', {\n patterns: allPatterns,\n watchDirs,\n cwd: this.cwd\n });\n }\n\n const watcher = chokidarWatch(watchDirs, {\n ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50\n }\n });\n\n const handleChange = async (absolutePath: string, event: 'add' | 'change' | 'unlink') =>\n {\n // Convert absolute path to relative path for pattern matching\n const filePath = relative(this.cwd, absolutePath);\n\n if (this.isGenerating)\n {\n this.pendingRegenerations.add(absolutePath);\n return;\n }\n\n this.isGenerating = true;\n this.pendingRegenerations.clear();\n\n if (this.debug)\n {\n orchestratorLogger.info(`File ${event}`, { file: filePath });\n }\n\n // Find matching generators\n for (const generator of this.generators)\n {\n // Check if generator should run for 'watch' trigger\n if (!this.shouldRun(generator, 'watch'))\n {\n continue;\n }\n\n const matches = generator.watchPatterns.some(pattern =>\n mm.isMatch(filePath, pattern)\n );\n\n if (matches)\n {\n try\n {\n // Call generate() with trigger information\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug,\n trigger: {\n type: 'watch',\n changedFile: {\n path: filePath,\n event\n }\n }\n };\n\n await generator.generate(genOptions);\n\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Regenerated`);\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] Regeneration failed`, err);\n }\n }\n }\n\n this.isGenerating = false;\n\n // Process pending regenerations\n if (this.pendingRegenerations.size > 0)\n {\n const next = Array.from(this.pendingRegenerations)[0];\n await handleChange(next, 'change');\n }\n };\n\n watcher\n .on('add', (path) => handleChange(path, 'add'))\n .on('change', (path) => handleChange(path, 'change'))\n .on('unlink', (path) => handleChange(path, 'unlink'));\n\n // Cleanup on exit\n process.on('SIGINT', () =>\n {\n if (this.debug)\n {\n orchestratorLogger.info('Shutting down watch mode');\n }\n watcher.close();\n process.exit(0);\n });\n\n // Keep process alive\n await new Promise(() => {});\n }\n}\n","/**\n * Contract Scanner\n *\n * Scans server/contracts directory and extracts exported contracts\n */\n\nimport { readFileSync } from 'fs';\nimport { readdir, stat } from 'fs/promises';\nimport { join } from 'path';\nimport * as ts from 'typescript';\nimport type { HttpMethod, RouteContractMapping } from '../../core/types';\nimport { logger } from '../../../logger';\n\nconst scannerLogger = logger.child('contract-scanner');\n\n/**\n * Scan for contract files and extract contract exports\n *\n * All contracts must use absolute paths (e.g., path: '/teams/:id')\n *\n * @param contractsDir - Path to lib/contracts/ directory\n * @param packagePrefix - Optional package prefix to apply to all contract paths\n * @returns Array of contract-to-route mappings\n */\nexport async function scanContracts(contractsDir: string, packagePrefix?: string): Promise<RouteContractMapping[]>\n{\n scannerLogger.debug('Starting contract scan', { contractsDir, packagePrefix });\n const contractFiles = await scanContractFiles(contractsDir);\n scannerLogger.debug('Found contract files', { count: contractFiles.length, files: contractFiles });\n const mappings: RouteContractMapping[] = [];\n\n for (let i = 0; i < contractFiles.length; i++)\n {\n const filePath = contractFiles[i];\n scannerLogger.debug('Extracting contracts from file', { filePath });\n const exports = extractContractExports(filePath);\n scannerLogger.debug('Extracted contracts', { filePath, count: exports.length, contracts: exports.map(e => e.name) });\n\n for (let j = 0; j < exports.length; j++)\n {\n const contractExport = exports[j];\n scannerLogger.debug('Processing contract', { name: contractExport.name, method: contractExport.method, path: contractExport.path });\n\n // All contracts must use absolute paths\n if (!contractExport.path.startsWith('/'))\n {\n throw new Error(\n `Contract '${contractExport.name}' in ${filePath} must use absolute path. ` +\n `Found: '${contractExport.path}'. Use '/your-path' instead.`\n );\n }\n\n if(packagePrefix && !contractExport.path.startsWith(packagePrefix))\n {\n throw new Error(\n `Contract '${contractExport.name}' in ${filePath} must include package prefix. ` +\n `Expected path to start with '${packagePrefix}', but found: '${contractExport.path}'. ` +\n `Example: path: '${packagePrefix}/${contractExport.path}'`\n );\n }\n\n // Apply package prefix if exists\n mappings.push({\n method: contractExport.method,\n path: contractExport.path,\n contractName: contractExport.name,\n contractImportPath: getImportPath(filePath),\n routeFile: '',\n contractFile: filePath,\n hasQuery: contractExport.hasQuery,\n hasBody: contractExport.hasBody,\n hasParams: contractExport.hasParams\n });\n }\n }\n\n scannerLogger.info('Contract scan completed', { totalMappings: mappings.length });\n return mappings;\n}\n\n/**\n * Recursively scan for contract files in lib/contracts/\n *\n * Scans for all .ts, .js, .mjs files (excluding test and declaration files)\n */\nasync function scanContractFiles(dir: string, files: string[] = []): Promise<string[]>\n{\n try\n {\n const entries = await readdir(dir);\n\n for (let i = 0; i < entries.length; i++)\n {\n const entry = entries[i];\n const fullPath = join(dir, entry);\n const fileStat = await stat(fullPath);\n\n if (fileStat.isDirectory())\n {\n await scanContractFiles(fullPath, files);\n }\n else\n {\n // Scan all .ts, .js, .mjs files (excluding test and declaration files)\n if (\n (entry.endsWith('.ts') || entry.endsWith('.js') || entry.endsWith('.mjs')) &&\n !entry.endsWith('.d.ts') &&\n !entry.endsWith('.test.ts') &&\n !entry.endsWith('.test.js') &&\n !entry.endsWith('.test.mjs')\n )\n {\n files.push(fullPath);\n }\n }\n }\n }\n catch (error)\n {\n // Directory doesn't exist or not readable\n }\n\n return files;\n}\n\n/**\n * Contract export information\n */\ninterface ContractExport\n{\n name: string;\n method: HttpMethod;\n path: string;\n hasQuery?: boolean;\n hasBody?: boolean;\n hasParams?: boolean;\n}\n\n/**\n * Extract contract exports from a TypeScript file\n *\n * Multi-layer detection:\n * 1. satisfies RouteContract (most explicit)\n * 2. Contract name pattern + method/path properties (fallback)\n *\n * @example\n * // Layer 1: satisfies RouteContract\n * export const myContract = { ... } satisfies RouteContract;\n *\n * // Layer 2: Name pattern + validation\n * export const myContract = { method: 'GET', path: '/api' };\n */\nfunction extractContractExports(filePath: string): ContractExport[]\n{\n const sourceCode = readFileSync(filePath, 'utf-8');\n const sourceFile = ts.createSourceFile(\n filePath,\n sourceCode,\n ts.ScriptTarget.Latest,\n true\n );\n\n const exports: ContractExport[] = [];\n\n function visit(node: ts.Node): void\n {\n // Look for: export const xxxContract = { ... }\n if (ts.isVariableStatement(node))\n {\n // Check if it has export modifier\n const hasExport = node.modifiers?.some(\n m => m.kind === ts.SyntaxKind.ExportKeyword\n );\n\n if (hasExport && node.declarationList.declarations.length > 0)\n {\n const declaration = node.declarationList.declarations[0];\n\n if (\n ts.isVariableDeclaration(declaration) &&\n ts.isIdentifier(declaration.name) &&\n declaration.initializer\n )\n {\n const name = declaration.name.text;\n\n // Layer 1: Check for satisfies RouteContract\n const hasSatisfiesRouteContract = checkSatisfiesRouteContract(declaration.initializer);\n\n if (hasSatisfiesRouteContract)\n {\n const objectLiteral = extractObjectLiteral(declaration.initializer);\n\n if (objectLiteral)\n {\n const contractData = extractContractData(objectLiteral);\n\n if (contractData.method && contractData.path)\n {\n exports.push({\n name,\n method: contractData.method,\n path: contractData.path,\n hasQuery: contractData.hasQuery,\n hasBody: contractData.hasBody,\n hasParams: contractData.hasParams\n });\n }\n }\n return; // Found via satisfies, skip fallback\n }\n\n // Layer 2: Fallback to name pattern check\n if (isContractName(name))\n {\n const objectLiteral = extractObjectLiteral(declaration.initializer);\n\n if (objectLiteral)\n {\n const contractData = extractContractData(objectLiteral);\n\n // Require both method and path for fallback detection\n if (contractData.method && contractData.path)\n {\n exports.push({\n name,\n method: contractData.method,\n path: contractData.path,\n hasQuery: contractData.hasQuery,\n hasBody: contractData.hasBody,\n hasParams: contractData.hasParams\n });\n }\n }\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return exports;\n}\n\n/**\n * Check if declaration uses 'satisfies RouteContract'\n */\nfunction checkSatisfiesRouteContract(initializer: ts.Expression): boolean\n{\n if (!ts.isSatisfiesExpression(initializer))\n {\n return false;\n }\n\n const typeNode = initializer.type;\n\n // Check for RouteContract type reference\n if (ts.isTypeReferenceNode(typeNode) &&\n ts.isIdentifier(typeNode.typeName))\n {\n return typeNode.typeName.text === 'RouteContract';\n }\n\n return false;\n}\n\n/**\n * Extract object literal from various expression forms\n */\nfunction extractObjectLiteral(initializer: ts.Expression): ts.ObjectLiteralExpression | undefined\n{\n // Direct object literal: { ... }\n if (ts.isObjectLiteralExpression(initializer))\n {\n return initializer;\n }\n\n // satisfies expression: { ... } satisfies RouteContract\n if (ts.isSatisfiesExpression(initializer))\n {\n return extractObjectLiteral(initializer.expression);\n }\n\n // as expression: { ... } as const\n if (ts.isAsExpression(initializer))\n {\n return extractObjectLiteral(initializer.expression);\n }\n\n return undefined;\n}\n\n/**\n * Extract method, path, and parameter info from contract object literal\n */\nfunction extractContractData(objectLiteral: ts.ObjectLiteralExpression): {\n method?: HttpMethod;\n path?: string;\n hasQuery?: boolean;\n hasBody?: boolean;\n hasParams?: boolean;\n}\n{\n const result: {\n method?: HttpMethod;\n path?: string;\n hasQuery?: boolean;\n hasBody?: boolean;\n hasParams?: boolean;\n } = {};\n\n for (let i = 0; i < objectLiteral.properties.length; i++)\n {\n const prop = objectLiteral.properties[i];\n\n if (\n ts.isPropertyAssignment(prop) &&\n ts.isIdentifier(prop.name)\n )\n {\n const propName = prop.name.text;\n\n if (propName === 'method')\n {\n // Handle both 'GET' and 'GET' as const\n let value: string | undefined;\n if (ts.isStringLiteral(prop.initializer))\n {\n value = prop.initializer.text;\n }\n else if (ts.isAsExpression(prop.initializer) && ts.isStringLiteral(prop.initializer.expression))\n {\n value = prop.initializer.expression.text;\n }\n if (value) result.method = value as HttpMethod;\n }\n else if (propName === 'path')\n {\n // Handle both '/path' and '/path' as const\n let value: string | undefined;\n if (ts.isStringLiteral(prop.initializer))\n {\n value = prop.initializer.text;\n }\n else if (ts.isAsExpression(prop.initializer) && ts.isStringLiteral(prop.initializer.expression))\n {\n value = prop.initializer.expression.text;\n }\n if (value) result.path = value;\n }\n else if (propName === 'query')\n {\n // Has query property\n result.hasQuery = true;\n }\n else if (propName === 'body')\n {\n // Has body property\n result.hasBody = true;\n }\n else if (propName === 'params')\n {\n // Has params property\n result.hasParams = true;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Check if a name looks like a contract\n */\nfunction isContractName(name: string): boolean\n{\n return (\n name.indexOf('Contract') !== -1 ||\n name.indexOf('contract') !== -1 ||\n name.endsWith('Schema') ||\n name.endsWith('schema')\n );\n}\n\n/**\n * Get import path for contract file\n *\n * @example\n * /path/to/src/lib/contracts/teams.ts → @/lib/contracts/teams\n */\nfunction getImportPath(filePath: string): string\n{\n // Try to find src/ directory\n const srcIndex = filePath.indexOf('/src/');\n\n if (srcIndex === -1)\n {\n throw new Error(`Cannot determine import path for ${filePath}: /src/ directory not found`);\n }\n\n // Get path from src/ onwards (+5 to skip '/src/')\n // Remove file extension (.ts, .js, .mjs)\n let cleanPath = filePath.substring(srcIndex + 5);\n if (cleanPath.endsWith('.ts'))\n {\n cleanPath = cleanPath.slice(0, -3);\n }\n else if (cleanPath.endsWith('.js'))\n {\n cleanPath = cleanPath.slice(0, -3);\n }\n else if (cleanPath.endsWith('.mjs'))\n {\n cleanPath = cleanPath.slice(0, -4);\n }\n\n // Return as module path with @ prefix\n return '@/' + cleanPath;\n}","/**\n * Codegen Helper Utilities\n *\n * Helper functions for grouping and organizing contract mappings\n */\n\nimport type { RouteContractMapping } from '../../core/types';\n\n/**\n * Group mappings by resource\n */\nexport function groupByResource(mappings: RouteContractMapping[]): Record<string, RouteContractMapping[]>\n{\n const grouped: Record<string, RouteContractMapping[]> = {};\n\n for (let i = 0; i < mappings.length; i++)\n {\n const mapping = mappings[i];\n const resource = extractResourceName(mapping.path);\n\n if (!grouped[resource])\n {\n grouped[resource] = [];\n }\n\n grouped[resource].push(mapping);\n }\n\n return grouped;\n}\n\n/**\n * Extract resource name from path\n *\n * Examples:\n * - /users → users\n * - /users/:id → users\n * - /users/:id/posts → usersPosts\n * - /videos/upload-and-analyze → videosUploadAndAnalyze\n * - /_cms/labels → labels (with prefix='/_cms')\n * - /_cms/published-cache → publishedCache (with prefix='/_cms')\n */\nfunction extractResourceName(path: string): string\n{\n // Strip prefix from path if provided\n let processedPath = path;\n if (!processedPath.startsWith('/'))\n {\n processedPath = '/' + processedPath;\n }\n\n // Remove leading slash\n const segments = processedPath.slice(1).split('/').filter(s => s && s !== '*');\n\n // Remove dynamic segments\n const staticSegments: string[] = [];\n for (let i = 0; i < segments.length; i++)\n {\n const seg = segments[i];\n if (!seg.startsWith(':'))\n {\n staticSegments.push(seg);\n }\n }\n\n // Join with camelCase\n if (staticSegments.length === 0)\n {\n return 'root';\n }\n\n // Convert first segment (keep lowercase for first)\n const first = toCamelCase(staticSegments[0], false);\n\n if (staticSegments.length === 1)\n {\n return first;\n }\n\n // Convert to camelCase: users/posts → usersPosts, videos/upload-and-analyze → videosUploadAndAnalyze\n const result: string[] = [first];\n for (let i = 1; i < staticSegments.length; i++)\n {\n const seg = staticSegments[i];\n result.push(toCamelCase(seg, true));\n }\n\n return result.join('');\n}\n\n/**\n * Convert string to camelCase, handling hyphens\n *\n * @param str - Input string\n * @param capitalize - Capitalize first letter\n * @returns camelCase string\n *\n * Examples:\n * - toCamelCase('upload-and-analyze', true) → 'UploadAndAnalyze'\n * - toCamelCase('upload-and-analyze', false) → 'uploadAndAnalyze'\n * - toCamelCase('users', false) → 'users'\n */\nfunction toCamelCase(str: string, capitalize: boolean): string\n{\n // Split by hyphen or underscore\n const parts = str.split(/[-_]/);\n\n if (parts.length === 1)\n {\n // No hyphens/underscores\n return capitalize\n ? str.charAt(0).toUpperCase() + str.slice(1)\n : str;\n }\n\n // Convert to camelCase\n const result: string[] = [];\n for (let i = 0; i < parts.length; i++)\n {\n const part = parts[i];\n if (i === 0 && !capitalize)\n {\n result.push(part);\n }\n else\n {\n result.push(part.charAt(0).toUpperCase() + part.slice(1));\n }\n }\n\n return result.join('');\n}","/**\n * Client Code Generator\n *\n * Generates type-safe API client code from route-contract mappings\n */\n\nimport { mkdir, writeFile } from 'fs/promises';\nimport { groupByResource } from './helpers';\nimport type { ClientGenerationOptions, GenerationStats, RouteContractMapping } from '../../core/types';\n\n/**\n * Generate API client code\n */\nexport async function generateClient(\n mappings: RouteContractMapping[],\n options: ClientGenerationOptions\n): Promise<GenerationStats>\n{\n const startTime = Date.now();\n\n // Group by resource\n const grouped = groupByResource(mappings);\n const resourceNames = Object.keys(grouped);\n\n // Generate split files by resource\n await generateSplitClient(mappings, grouped, options);\n\n // Calculate stats\n return {\n routesScanned: mappings.length,\n contractsFound: mappings.length,\n contractFiles: countUniqueContractFiles(mappings),\n resourcesGenerated: resourceNames.length,\n methodsGenerated: mappings.length,\n duration: Date.now() - startTime\n };\n}\n\n/**\n * Generate file header\n */\nfunction generateHeader(): string\n{\n return `/**\n * Auto-generated API Client\n *\n * Generated by @spfn/core codegen\n * DO NOT EDIT MANUALLY\n *\n * @generated ${new Date().toISOString()}\n */\n\n`;\n}\n\n/**\n * Group contracts by their import path\n */\nfunction groupContractsByImportPath(mappings: RouteContractMapping[]): Record<string, string[]>\n{\n const groups: Record<string, Set<string>> = {};\n\n for (let i = 0; i < mappings.length; i++)\n {\n const mapping = mappings[i];\n const path = mapping.contractImportPath;\n\n if (!groups[path])\n {\n groups[path] = new Set();\n }\n\n groups[path].add(mapping.contractName);\n }\n\n // Convert Set to Array\n const result: Record<string, string[]> = {};\n const keys = Object.keys(groups);\n\n for (let i = 0; i < keys.length; i++)\n {\n const key = keys[i];\n result[key] = Array.from(groups[key]);\n }\n\n return result;\n}\n\n/**\n * Convert contract name to type name\n *\n * Examples:\n * - getTeamMembersContract -> GetTeamMembers\n * - createTeamMemberContract -> CreateTeamMember\n * - updateCompanyContract -> UpdateCompany\n */\nfunction generateTypeName(mapping: RouteContractMapping): string\n{\n let name = mapping.contractName;\n\n // Remove \"Contract\" suffix\n if (name.endsWith('Contract'))\n {\n name = name.slice(0, -8);\n }\n\n // Convert to PascalCase if not already\n if (name.length > 0)\n {\n name = name.charAt(0).toUpperCase() + name.slice(1);\n }\n\n return name;\n}\n\n/**\n * Generate function name from contract name\n *\n * Examples:\n * - getLabelsContract -> getLabels\n * - createLabelContract -> createLabel\n * - updateLabelContract -> updateLabel\n */\nfunction generateFunctionName(mapping: RouteContractMapping): string\n{\n let name = mapping.contractName;\n\n // Remove \"Contract\" suffix\n if (name.endsWith('Contract'))\n {\n name = name.slice(0, -8);\n }\n\n return name;\n}\n\n/**\n * Generate a single function export\n */\nfunction generateFunctionCode(mapping: RouteContractMapping, options: ClientGenerationOptions): string\n{\n const functionName = generateFunctionName(mapping);\n const hasParams = mapping.hasParams || mapping.path.includes(':');\n const hasQuery = mapping.hasQuery || false;\n const hasBody = mapping.hasBody || false;\n\n let code = '';\n\n // JSDoc\n if (options.includeJsDoc !== false)\n {\n code += `/**\\n`;\n code += ` * ${mapping.method} ${mapping.path}\\n`;\n code += ` */\\n`;\n }\n\n // Function signature\n code += `export const ${functionName} = (`;\n\n // Parameters - use generated type names instead of InferContract\n const params: string[] = [];\n const typeName = generateTypeName(mapping);\n\n if (hasParams)\n {\n params.push(`params: ${typeName}Params`);\n }\n\n if (hasQuery)\n {\n params.push(`query?: ${typeName}Query`);\n }\n\n if (hasBody)\n {\n params.push(`body: ${typeName}Body`);\n }\n\n if (params.length > 0)\n {\n code += `options: { ${params.join(', ')} }`;\n }\n\n code += `) => `;\n\n // Call client with contract only (no basePath - contracts have absolute paths)\n code += `client.call(${mapping.contractName}`;\n\n if (params.length > 0)\n {\n code += `, options`;\n }\n\n code += `);\\n\\n`;\n\n return code;\n}\n\n/**\n * Count unique contract files\n */\nfunction countUniqueContractFiles(mappings: RouteContractMapping[]): number\n{\n const files = new Set<string>();\n\n for (let i = 0; i < mappings.length; i++)\n {\n if (mappings[i].contractFile)\n {\n files.add(mappings[i].contractFile as string);\n }\n }\n\n return files.size;\n}\n\n/**\n * Convert camelCase to kebab-case\n *\n * Examples:\n * - labels -> labels\n * - publishedCache -> published-cache\n * - usersPosts -> users-posts\n */\nfunction toKebabCase(str: string): string\n{\n if (str.length === 0)\n {\n return str;\n }\n\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .toLowerCase();\n}\n\n/**\n * Generate split API client files by resource\n */\nasync function generateSplitClient(\n _mappings: RouteContractMapping[],\n grouped: Record<string, RouteContractMapping[]>,\n options: ClientGenerationOptions\n): Promise<void>\n{\n // When splitting, outputPath should become a directory\n // e.g., /src/lib/api.ts -> /src/lib/api/\n const outputPath = options.outputPath;\n const outputDir = outputPath.endsWith('.ts') || outputPath.endsWith('.js')\n ? outputPath.replace(/\\.[jt]s$/, '')\n : outputPath;\n\n // Create output directory\n await mkdir(outputDir, { recursive: true });\n\n const resourceNames = Object.keys(grouped);\n\n // Generate individual resource files\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n\n const code = generateResourceFile(resourceName, routes, options);\n // Convert to kebab-case for file name\n const kebabName = toKebabCase(resourceName);\n const filePath = `${outputDir}/${kebabName}.ts`;\n\n await writeFile(filePath, code, 'utf-8');\n }\n\n // Generate index file\n const indexCode = generateIndexFile(grouped, options);\n const indexPath = `${outputDir}/index.ts`;\n\n await writeFile(indexPath, indexCode, 'utf-8');\n}\n\n/**\n * Generate a single resource file\n */\nfunction generateResourceFile(\n _resourceName: string,\n routes: RouteContractMapping[],\n options: ClientGenerationOptions\n): string\n{\n let code = '';\n\n // Header\n code += generateHeader();\n\n // Imports\n code += `import { client } from '@spfn/core/client';\\n`;\n\n if (options.includeTypes !== false)\n {\n code += `import type { InferContract } from '@spfn/core';\\n`;\n }\n\n code += `\\n`;\n\n // Contract imports\n const importGroups = groupContractsByImportPath(routes);\n const importPaths = Object.keys(importGroups);\n\n for (let i = 0; i < importPaths.length; i++)\n {\n const importPath = importPaths[i];\n const contracts = importGroups[importPath];\n\n code += `import { ${contracts.join(', ')} } from '${importPath}';\\n`;\n }\n\n code += `\\n`;\n\n // Types\n if (options.includeTypes !== false)\n {\n code += `// ============================================\\n`;\n code += `// Types\\n`;\n code += `// ============================================\\n\\n`;\n\n for (let i = 0; i < routes.length; i++)\n {\n const route = routes[i];\n const typeName = generateTypeName(route);\n const contractType = `typeof ${route.contractName}`;\n\n // Response type (always present)\n code += `export type ${typeName}Response = InferContract<${contractType}>['response'];\\n`;\n\n // Query type (if exists)\n if (route.hasQuery)\n {\n code += `export type ${typeName}Query = InferContract<${contractType}>['query'];\\n`;\n }\n\n // Params type (if exists)\n if (route.hasParams || route.path.includes(':'))\n {\n code += `export type ${typeName}Params = InferContract<${contractType}>['params'];\\n`;\n }\n\n // Body type (if exists)\n if (route.hasBody)\n {\n code += `export type ${typeName}Body = InferContract<${contractType}>['body'];\\n`;\n }\n\n code += `\\n`;\n }\n }\n\n // Generate individual function exports\n code += `// ============================================\\n`;\n code += `// API Functions\\n`;\n code += `// ============================================\\n\\n`;\n\n for (let i = 0; i < routes.length; i++)\n {\n const route = routes[i];\n code += generateFunctionCode(route, options);\n }\n\n return code;\n}\n\n/**\n * Generate index file that combines all resources\n */\nfunction generateIndexFile(\n grouped: Record<string, RouteContractMapping[]>,\n options: ClientGenerationOptions\n): string\n{\n let code = '';\n const apiName = options.apiName || 'api';\n const resourceNames = Object.keys(grouped);\n\n // Header\n code += generateHeader();\n\n // Re-export client\n code += `export { client } from '@spfn/core/client';\\n\\n`;\n\n // Re-export only types from resource modules (use kebab-case for file names)\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n const kebabName = toKebabCase(resourceName);\n\n // Collect all type names for this resource\n const typeNames: string[] = [];\n for (let j = 0; j < routes.length; j++)\n {\n const route = routes[j];\n const typeName = generateTypeName(route);\n\n // Always export Response type\n typeNames.push(`${typeName}Response`);\n\n // Conditionally export other types\n if (route.hasQuery)\n {\n typeNames.push(`${typeName}Query`);\n }\n if (route.hasParams || route.path.includes(':'))\n {\n typeNames.push(`${typeName}Params`);\n }\n if (route.hasBody)\n {\n typeNames.push(`${typeName}Body`);\n }\n }\n\n if (typeNames.length > 0)\n {\n code += `export type { ${typeNames.join(', ')} } from './${kebabName}';\\n`;\n }\n }\n\n code += `\\n`;\n\n // Import all functions from each resource file\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n const kebabName = toKebabCase(resourceName);\n\n // Get all function names for this resource\n const functionNames = routes.map(route => generateFunctionName(route));\n\n code += `import { ${functionNames.join(', ')} } from './${kebabName}';\\n`;\n }\n\n code += `\\n`;\n\n // Combined API object with all functions flattened\n code += `/**\\n`;\n code += ` * Type-safe API client\\n`;\n code += ` */\\n`;\n code += `export const ${apiName} = {\\n`;\n\n // Add all functions from all resources\n let isFirst = true;\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n\n for (let j = 0; j < routes.length; j++)\n {\n const route = routes[j];\n const functionName = generateFunctionName(route);\n\n if (!isFirst)\n {\n code += `,\\n`;\n }\n\n code += ` ${functionName}`;\n isFirst = false;\n }\n }\n\n code += `\\n} as const;\\n`;\n\n return code;\n}","/**\n * Contract Generator\n *\n * Generates type-safe API client from contract definitions\n *\n * Features:\n * - Automatic scanning of contract files\n * - Type-safe client generation with InferContract\n * - Split output by resource for better code organization\n * - Incremental updates when single files change (smart regeneration)\n */\n\nimport { join } from 'path';\nimport { existsSync, readFileSync } from 'fs';\nimport type { Generator, GeneratorOptions, GeneratorTrigger } from '../../core/generator';\nimport { scanContracts } from './scanner';\nimport { generateClient } from './emitter';\nimport { logger } from '../../../logger';\nimport type { RouteContractMapping, ClientGenerationOptions } from '../../core/types';\n\nconst contractLogger = logger.child('contract-gen');\n\n/** Default paths */\nconst DEFAULT_CONTRACTS_DIR = 'src/lib/contracts';\nconst DEFAULT_OUTPUT_PATH = 'src/lib/api';\n\nexport interface ContractGeneratorConfig\n{\n /** Contracts directory (default: src/lib/contracts) */\n contractsDir?: string;\n\n /** Output directory (default: src/lib/api) */\n outputPath?: string;\n\n /** Base URL for API client */\n baseUrl?: string;\n\n /** When to run this generator (default: ['watch', 'manual', 'build']) */\n runOn?: GeneratorTrigger[];\n}\n\n/**\n * Cache for incremental updates\n */\ninterface ContractCache\n{\n /** All scanned contracts */\n contracts: RouteContractMapping[];\n\n /** Timestamp of last scan */\n lastScan: number;\n}\n\nlet contractCache: ContractCache | null = null;\n\n/**\n * Check if a file change requires full regeneration\n *\n * We need full regen if:\n * - New file added\n * - File deleted\n * - Cache doesn't exist\n */\nfunction needsFullRegeneration(\n event: 'add' | 'change' | 'unlink'\n): boolean\n{\n // New files or deletions always require full scan\n if (event === 'add' || event === 'unlink')\n {\n return true;\n }\n\n // No cache means first run\n if (!contractCache)\n {\n return true;\n }\n\n // For 'change' events, we can do smart regen\n // (only if the file still exports the same contracts)\n return false;\n}\n\n/**\n * Helper to create client generation options\n */\nfunction createClientOptions(\n contractsDir: string,\n outputPath: string,\n baseUrl?: string,\n apiName?: string\n): ClientGenerationOptions\n{\n return {\n routesDir: contractsDir,\n outputPath,\n baseUrl,\n apiName,\n includeTypes: true,\n includeJsDoc: true,\n splitByResource: true\n };\n}\n\n/**\n * Generate API name from prefix\n *\n * Examples:\n * - /_cms -> cmsApi\n * - /_auth -> authApi\n * - /api -> api\n * - undefined -> api\n *\n * @param prefix - Package prefix from spfn config\n * @returns API name in camelCase\n */\nfunction generateApiName(prefix?: string): string\n{\n if (!prefix || prefix === '/api')\n {\n return 'api';\n }\n\n // Remove leading slash and underscores/hyphens\n // /_cms -> cms\n // /_auth -> auth\n const name = prefix.replace(/^\\/[_-]?/, '').replace(/[_-]/g, '');\n\n if (!name)\n {\n return 'api';\n }\n\n // Convert to camelCase and append 'Api'\n return `${name}Api`;\n}\n\n/**\n * Read prefix from package.json\n *\n * @param cwd - Project directory\n * @returns Prefix from spfn config or undefined\n */\nfunction readPrefixFromPackageJson(cwd: string): string | undefined\n{\n try\n {\n const packageJsonPath = join(cwd, 'package.json');\n\n if (!existsSync(packageJsonPath))\n {\n return undefined;\n }\n\n const content = readFileSync(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(content);\n\n return packageJson.spfn?.prefix;\n }\n catch (error)\n {\n // Ignore errors, return undefined\n return undefined;\n }\n}\n\nexport function createContractGenerator(config: ContractGeneratorConfig = {}): Generator\n{\n // Resolve paths once\n const contractsDir = config.contractsDir ?? DEFAULT_CONTRACTS_DIR;\n const outputPath = config.outputPath ?? DEFAULT_OUTPUT_PATH;\n const runOn = config.runOn ?? ['watch', 'manual', 'build']; // Default excludes 'start'\n\n return {\n name: 'contract',\n watchPatterns: [\n `${contractsDir}/**/*.ts`,\n ],\n runOn,\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const cwd = options.cwd;\n const fullContractsDir = join(cwd, contractsDir);\n const fullOutputPath = join(cwd, outputPath);\n\n // Read prefix from package.json once at the start\n const prefix = readPrefixFromPackageJson(cwd);\n const apiName = generateApiName(prefix);\n\n try\n {\n // Check if contracts directory exists\n if (!existsSync(fullContractsDir))\n {\n if (options.debug)\n {\n contractLogger.warn(`No contracts directory found at ${contractsDir}`);\n }\n return;\n }\n\n // Check for incremental update opportunity\n const changedFile = options.trigger?.changedFile;\n if (changedFile && !needsFullRegeneration(changedFile.event))\n {\n if (options.debug)\n {\n contractLogger.info('Attempting incremental update', {\n file: changedFile.path,\n event: changedFile.event\n });\n }\n\n // Try incremental update\n const success = await attemptIncrementalUpdate({\n cwd,\n contractsDir: fullContractsDir,\n outputPath: fullOutputPath,\n changedFilePath: changedFile.path,\n baseUrl: config.baseUrl,\n apiName,\n debug: options.debug\n });\n\n if (success)\n {\n if (options.debug)\n {\n contractLogger.info('Incremental update successful');\n }\n return;\n }\n\n // Fall through to full regeneration if incremental failed\n if (options.debug)\n {\n contractLogger.info('Incremental update failed, doing full regen');\n }\n }\n\n // Full regeneration\n const allContracts = await scanContracts(fullContractsDir, prefix);\n if (allContracts.length === 0)\n {\n if (options.debug)\n {\n contractLogger.warn('No contracts found');\n }\n\n contractCache = null;\n return;\n }\n\n // Generate client (apiName already calculated at start of function)\n const clientOptions = createClientOptions(fullContractsDir, fullOutputPath, config.baseUrl, apiName);\n const stats = await generateClient(allContracts, clientOptions);\n\n // Update cache\n contractCache = {\n contracts: allContracts,\n lastScan: Date.now()\n };\n\n if (options.debug)\n {\n contractLogger.info('Client generated', {\n endpoints: stats.methodsGenerated,\n resources: stats.resourcesGenerated,\n duration: stats.duration,\n mode: changedFile ? 'incremental-fallback' : 'full'\n });\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n contractLogger.error('Generation failed', err);\n throw err;\n }\n }\n };\n}\n\n/**\n * Options for incremental update\n */\ninterface IncrementalUpdateOptions\n{\n cwd: string;\n contractsDir: string;\n outputPath: string;\n changedFilePath: string;\n baseUrl?: string;\n apiName: string;\n debug?: boolean;\n}\n\n/**\n * Attempt incremental update for a single file change\n *\n * Strategy:\n * 1. Rescan the entire directory to get updated contracts\n * 2. Compare with cached contracts to find what changed\n * 3. Skip regeneration if no contract signatures changed (e.g., formatting only)\n * 4. Otherwise, do full client generation (contracts are interconnected)\n *\n * Returns true if successful, false if full regen is needed\n */\nasync function attemptIncrementalUpdate(options: IncrementalUpdateOptions): Promise<boolean>\n{\n const { cwd, contractsDir, outputPath, changedFilePath, baseUrl, apiName, debug } = options;\n\n if (!contractCache)\n {\n return false; // No cache, need full regen\n }\n\n try\n {\n const fullPath = join(cwd, changedFilePath);\n\n if (!existsSync(fullPath))\n {\n // File deleted during watch, need full regen\n return false;\n }\n\n // Rescan the entire directory to get updated contracts\n // (This is still faster than full client generation)\n const updatedContracts = await scanContracts(contractsDir);\n\n if (updatedContracts.length === 0)\n {\n contractCache = null;\n return false;\n }\n\n // Compare with cached contracts to find what changed\n const changedContracts = findChangedContracts(\n contractCache.contracts,\n updatedContracts,\n changedFilePath\n );\n\n if (changedContracts.size === 0)\n {\n if (debug)\n {\n contractLogger.info('No contract changes detected, skipping regeneration');\n }\n return true; // No changes, skip regen\n }\n\n // Regenerate everything since contracts are interconnected (apiName passed as parameter)\n // (A safer approach than trying to regenerate only affected resources)\n const clientOptions = createClientOptions(contractsDir, outputPath, baseUrl, apiName);\n const stats = await generateClient(updatedContracts, clientOptions);\n\n // Update cache\n contractCache = {\n contracts: updatedContracts,\n lastScan: Date.now()\n };\n\n if (debug)\n {\n contractLogger.info('Incremental update successful', {\n changedContracts: changedContracts.size,\n endpoints: stats.methodsGenerated,\n resources: stats.resourcesGenerated,\n duration: stats.duration\n });\n }\n\n return true;\n }\n catch (error)\n {\n if (debug)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n contractLogger.warn('Incremental update failed', err);\n }\n return false;\n }\n}\n\n/**\n * Find contracts that changed in the given file\n */\nfunction findChangedContracts(\n oldContracts: RouteContractMapping[],\n newContracts: RouteContractMapping[],\n changedFilePath: string\n): Set<string>\n{\n const changed = new Set<string>();\n\n // Find contracts from the changed file in both old and new\n const oldInFile = oldContracts.filter(c => c.contractFile?.includes(changedFilePath));\n const newInFile = newContracts.filter(c => c.contractFile?.includes(changedFilePath));\n\n // If contract count changed, mark all as changed\n if (oldInFile.length !== newInFile.length)\n {\n newInFile.forEach(c => changed.add(c.contractName));\n return changed;\n }\n\n // Compare contract signatures\n for (const newContract of newInFile)\n {\n const oldContract = oldInFile.find(c => c.contractName === newContract.contractName);\n\n if (!oldContract)\n {\n changed.add(newContract.contractName);\n continue;\n }\n\n // Check if contract signature changed\n if (\n oldContract.method !== newContract.method ||\n oldContract.path !== newContract.path ||\n oldContract.hasQuery !== newContract.hasQuery ||\n oldContract.hasBody !== newContract.hasBody ||\n oldContract.hasParams !== newContract.hasParams\n )\n {\n changed.add(newContract.contractName);\n }\n }\n\n return changed;\n}","/**\n * Codegen Configuration Loader\n *\n * Loads codegen configuration from .spfnrc.json or package.json\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createJiti } from 'jiti';\nimport type { Generator } from './generator.js';\nimport { logger } from '../../logger';\n\nconst configLogger = logger.child('config');\n\nexport interface CodegenConfig\n{\n generators?: Array<\n | { path: string } // Custom generator via file path\n | ({ name: string; enabled?: boolean } & Record<string, any>) // Package-based generator: \"package:name\" or built-in \"name\"\n >;\n}\n\n/**\n * Load codegen configuration from .spfnrc.json or package.json\n */\nexport function loadCodegenConfig(cwd: string): CodegenConfig\n{\n // 1. Check .spfnrc.json\n const rcPath = join(cwd, '.spfnrc.json');\n if (existsSync(rcPath))\n {\n try\n {\n const content = readFileSync(rcPath, 'utf-8');\n const config = JSON.parse(content);\n\n if (config.codegen)\n {\n configLogger.info('Loaded config from .spfnrc.json');\n return config.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse .spfnrc.json', error as Error);\n }\n }\n\n // 2. Check package.json\n const pkgPath = join(cwd, 'package.json');\n if (existsSync(pkgPath))\n {\n try\n {\n const content = readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n\n if (pkg.spfn?.codegen)\n {\n configLogger.info('Loaded config from package.json');\n return pkg.spfn.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse package.json', error as Error);\n }\n }\n\n // 3. Default configuration\n configLogger.info('Using default config');\n return {\n generators: [\n { name: '@spfn/core:contract', enabled: true }\n ]\n };\n}\n\n/**\n * Load generator from package\n *\n * Supports format: \"package:generator-name\" or \"@scope/package:generator-name\"\n */\nasync function loadGeneratorFromPackage(\n packageName: string,\n generatorName: string,\n config: Record<string, any>\n): Promise<Generator | null>\n{\n try\n {\n // Try to load package/generators export\n const generatorsModule = await import(`${packageName}/generators`);\n\n // Look for generator by name in registry\n if (generatorsModule.generators?.[generatorName])\n {\n const createFn = generatorsModule.generators[generatorName];\n const generator = createFn(config);\n configLogger.info(`Loaded ${packageName}:${generatorName}`);\n return generator;\n }\n\n // Fallback: try conventional name (createXxxGenerator)\n const conventionalName = `create${capitalize(generatorName)}Generator`;\n if (generatorsModule[conventionalName])\n {\n const createFn = generatorsModule[conventionalName];\n const generator = createFn(config);\n configLogger.info(`Loaded ${packageName}:${generatorName} (via ${conventionalName})`);\n return generator;\n }\n\n configLogger.warn(\n `Generator \"${generatorName}\" not found in ${packageName}/generators. ` +\n `Expected: generators.${generatorName} or ${conventionalName}`\n );\n return null;\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.warn(\n `Failed to load ${packageName}:${generatorName}. ` +\n `Make sure ${packageName} is installed. Error: ${err.message}`\n );\n return null;\n }\n}\n\n/**\n * Capitalize first letter\n */\nfunction capitalize(str: string): string\n{\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Create generator instances from configuration\n */\nexport async function createGeneratorsFromConfig(config: CodegenConfig, cwd: string): Promise<Generator[]>\n{\n const generators: Generator[] = [];\n\n if (!config.generators || config.generators.length === 0)\n {\n return generators;\n }\n\n for (const generatorConfig of config.generators)\n {\n try\n {\n // Custom generator (via file path)\n if ('path' in generatorConfig)\n {\n const generatorPath = generatorConfig.path.startsWith('.')\n ? join(cwd, generatorConfig.path)\n : generatorConfig.path;\n\n configLogger.info(`Loading custom generator: ${generatorPath}`);\n\n let module: any;\n\n // Use jiti for .ts files, regular import for .js\n if (generatorPath.endsWith('.ts'))\n {\n const jiti = createJiti(cwd, {\n interopDefault: true\n });\n module = jiti(generatorPath);\n }\n else\n {\n module = await import(generatorPath);\n }\n\n const createGenerator = module.default || module.createGenerator || module;\n\n if (typeof createGenerator === 'function')\n {\n const generator = createGenerator();\n generators.push(generator);\n configLogger.info(`Custom generator loaded: ${generator.name}`);\n }\n else\n {\n configLogger.warn(`Invalid generator at ${generatorPath}: expected function`);\n }\n }\n // Package-based generator: \"package:name\" or \"@scope/package:name\"\n else if ('name' in generatorConfig && generatorConfig.name.includes(':'))\n {\n if (generatorConfig.enabled !== false)\n {\n const [packageName, generatorName] = generatorConfig.name.split(':');\n const { enabled, name, ...generatorOptions } = generatorConfig;\n\n const generator = await loadGeneratorFromPackage(\n packageName,\n generatorName,\n generatorOptions\n );\n\n if (generator)\n {\n generators.push(generator);\n }\n }\n }\n // Unknown generator name format\n else if ('name' in generatorConfig)\n {\n configLogger.warn(\n `Invalid generator name \"${generatorConfig.name}\". ` +\n `Use package:name format (e.g., \"@spfn/core:contract\")`\n );\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.error('Failed to load generator', err);\n }\n }\n\n return generators;\n}"]}
|