@spfn/core 0.1.0-alpha.86 → 0.2.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1046 -384
- package/dist/boss-D-fGtVgM.d.ts +187 -0
- package/dist/cache/index.d.ts +13 -33
- package/dist/cache/index.js +14 -703
- package/dist/cache/index.js.map +1 -1
- package/dist/codegen/index.d.ts +167 -17
- package/dist/codegen/index.js +76 -1419
- package/dist/codegen/index.js.map +1 -1
- package/dist/config/index.d.ts +1191 -0
- package/dist/config/index.js +264 -0
- package/dist/config/index.js.map +1 -0
- package/dist/db/index.d.ts +728 -59
- package/dist/db/index.js +1028 -1225
- package/dist/db/index.js.map +1 -1
- package/dist/env/index.d.ts +579 -308
- package/dist/env/index.js +438 -930
- package/dist/env/index.js.map +1 -1
- package/dist/errors/index.d.ts +417 -29
- package/dist/errors/index.js +359 -98
- package/dist/errors/index.js.map +1 -1
- package/dist/event/index.d.ts +108 -0
- package/dist/event/index.js +122 -0
- package/dist/event/index.js.map +1 -0
- package/dist/job/index.d.ts +172 -0
- package/dist/job/index.js +361 -0
- package/dist/job/index.js.map +1 -0
- package/dist/logger/index.d.ts +20 -79
- package/dist/logger/index.js +82 -387
- package/dist/logger/index.js.map +1 -1
- package/dist/middleware/index.d.ts +2 -11
- package/dist/middleware/index.js +49 -703
- package/dist/middleware/index.js.map +1 -1
- package/dist/nextjs/index.d.ts +120 -0
- package/dist/nextjs/index.js +416 -0
- package/dist/nextjs/index.js.map +1 -0
- package/dist/{client/nextjs/index.d.ts → nextjs/server.d.ts} +288 -262
- package/dist/nextjs/server.js +568 -0
- package/dist/nextjs/server.js.map +1 -0
- package/dist/route/index.d.ts +667 -25
- package/dist/route/index.js +437 -1287
- package/dist/route/index.js.map +1 -1
- package/dist/route/types.d.ts +38 -0
- package/dist/route/types.js +3 -0
- package/dist/route/types.js.map +1 -0
- package/dist/server/index.d.ts +201 -67
- package/dist/server/index.js +921 -3182
- package/dist/server/index.js.map +1 -1
- package/dist/types-BGl4QL1w.d.ts +77 -0
- package/dist/types-DRG2XMTR.d.ts +157 -0
- package/package.json +56 -48
- package/dist/auto-loader-JFaZ9gON.d.ts +0 -80
- package/dist/client/index.d.ts +0 -358
- package/dist/client/index.js +0 -357
- package/dist/client/index.js.map +0 -1
- package/dist/client/nextjs/index.js +0 -371
- package/dist/client/nextjs/index.js.map +0 -1
- package/dist/codegen/generators/index.d.ts +0 -19
- package/dist/codegen/generators/index.js +0 -1404
- package/dist/codegen/generators/index.js.map +0 -1
- package/dist/database-errors-BNNmLTJE.d.ts +0 -86
- package/dist/events/index.d.ts +0 -183
- package/dist/events/index.js +0 -77
- package/dist/events/index.js.map +0 -1
- package/dist/index-DHiAqhKv.d.ts +0 -101
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -3674
- package/dist/index.js.map +0 -1
- package/dist/types/index.d.ts +0 -121
- package/dist/types/index.js +0 -38
- package/dist/types/index.js.map +0 -1
- package/dist/types-BXibIEyj.d.ts +0 -60
package/dist/env/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../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/factory.ts","../../src/env/config.ts","../../src/env/loader.ts","../../src/env/validator.ts"],"names":["newPath","existsSync","mkdirSync","join","unlinkSync","dotenvConfig"],"mappings":"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","file":"index.js","sourcesContent":["/**\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 let valueStr: string;\n if (typeof value === 'string')\n {\n valueStr = value;\n }\n else if (typeof value === 'object' && value !== null)\n {\n try\n {\n valueStr = JSON.stringify(value);\n }\n catch (error)\n {\n valueStr = '[circular]';\n }\n }\n else\n {\n valueStr = String(value);\n }\n\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 * Logger Factory\n *\n * Creates and initializes the logger instance with configured transports\n */\n\nimport { Logger } from './logger.js';\nimport { ConsoleTransport } from './transports/console.js';\nimport { FileTransport } from './transports/file.js';\nimport { getDefaultLogLevel, getConsoleConfig, getFileConfig, validateConfig } from './config.js';\nimport type { Transport } from './types.js';\n\n/**\n * Initialize transports based on environment and configuration\n */\nfunction initializeTransports(): Transport[]\n{\n const transports: Transport[] = [];\n\n // Console Transport (always enabled)\n const consoleConfig = getConsoleConfig();\n transports.push(new ConsoleTransport(consoleConfig));\n\n // File Transport (enabled in production or via config)\n const fileConfig = getFileConfig();\n if (fileConfig.enabled)\n {\n transports.push(new FileTransport(fileConfig));\n }\n\n // Future: Add more transports (Slack, Email, etc.)\n // if (config.slack?.enabled) {\n // transports.push(new SlackTransport(config.slack));\n // }\n\n return transports;\n}\n\n/**\n * Initialize logger with configuration validation\n */\nfunction initializeLogger(): Logger\n{\n // Validate configuration before creating logger\n validateConfig();\n\n // Create logger with configured transports\n return new Logger({\n level: getDefaultLogLevel(),\n transports: initializeTransports(),\n });\n}\n\n/**\n * Singleton Logger instance\n */\nexport const logger: Logger = initializeLogger();","/**\n * Environment Variable Management - Configuration Types\n *\n * Type definitions for centralized environment variable loading\n */\n\n/**\n * Options for loading environment variables\n */\nexport interface LoadEnvironmentOptions\n{\n /**\n * Base directory for .env files\n * @default process.cwd()\n */\n basePath?: string;\n\n /**\n * Additional custom paths to load\n * Loaded after standard files\n * @default []\n */\n customPaths?: string[];\n\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Override NODE_ENV for file selection\n * @default process.env.NODE_ENV\n */\n nodeEnv?: string;\n\n /**\n * Required environment variables\n * Throws error if any are missing after loading\n * @default []\n */\n required?: string[];\n\n /**\n * Skip loading if environment already loaded\n * Set to false to force reload (useful for testing)\n * @default true\n */\n useCache?: boolean;\n}\n\n/**\n * Result of environment loading operation\n */\nexport interface LoadResult\n{\n /**\n * Whether loading was successful overall\n */\n success: boolean;\n\n /**\n * Files that were successfully loaded\n */\n loaded: string[];\n\n /**\n * Files that failed to load (with reasons)\n */\n failed: Array<{ path: string; reason: string }>;\n\n /**\n * Environment variables that were parsed from files\n */\n parsed: Record<string, string>;\n\n /**\n * Error messages if any critical errors occurred\n */\n errors?: string[];\n\n /**\n * Warning messages for non-critical issues\n */\n warnings: string[];\n}\n\n/**\n * Options for getting environment variables\n */\nexport interface GetEnvOptions\n{\n /**\n * Throw error if variable not found\n * @default false\n */\n required?: boolean;\n\n /**\n * Default value if variable not found\n * Only used if required is false\n */\n default?: string;\n\n /**\n * Custom validation function\n * Return true if valid, false if invalid\n */\n validator?: (value: string) => boolean;\n\n /**\n * Custom error message for validation failure\n */\n validationError?: string;\n}\n\n/**\n * Standard environment file names in priority order\n *\n * Next.js-style loading behavior:\n * - development: .env → .env.development → .env.local → .env.development.local\n * - production: .env → .env.production → .env.local → .env.production.local\n * - test: .env → .env.test → (skip .env.local) → .env.test.local\n *\n * Note: .env.local is excluded in test environment for proper test isolation\n */\nexport const ENV_FILE_PRIORITY = [\n '.env', // Base configuration (lowest priority)\n '.env.{NODE_ENV}', // Environment-specific\n '.env.local', // Local overrides (excluded in test)\n '.env.{NODE_ENV}.local', // Local environment-specific (highest priority)\n] as const;\n\n/**\n * Environment files that should only be loaded in test environment\n */\nexport const TEST_ONLY_FILES = [\n '.env.test',\n '.env.test.local',\n] as const;\n","/**\n * Environment Variable Management - Core Loader\n *\n * Centralized singleton environment variable loader with dotenv priority support\n */\n\nimport { config as dotenvConfig } from 'dotenv';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { logger } from '../logger';\nimport type {\n LoadEnvironmentOptions,\n LoadResult,\n GetEnvOptions,\n} from './config.js';\nimport { ENV_FILE_PRIORITY, TEST_ONLY_FILES } from './config.js';\n\nconst envLogger = logger.child('environment');\n\n/**\n * Singleton state\n */\nlet environmentLoaded = false;\nlet cachedLoadResult: LoadResult | undefined;\n\n/**\n * Build list of environment files to load based on NODE_ENV\n *\n * Next.js-style behavior:\n * - .env.local is excluded in test environment for test isolation\n * - Test files (.env.test*) are excluded in non-test environments\n * - If NODE_ENV is not set, .env and .env.local are loaded\n *\n * @param basePath - Base directory for .env files\n * @param nodeEnv - Current NODE_ENV value (empty string if not set)\n * @returns Array of absolute file paths to load in priority order\n */\nfunction buildFileList(basePath: string, nodeEnv: string): string[]\n{\n const files: string[] = [];\n\n // If NODE_ENV is not set, load .env and .env.local (Next.js style)\n if (!nodeEnv)\n {\n files.push(join(basePath, '.env'));\n files.push(join(basePath, '.env.local'));\n return files;\n }\n\n for (const pattern of ENV_FILE_PRIORITY)\n {\n const fileName = pattern.replace('{NODE_ENV}', nodeEnv);\n\n // Skip .env.local in test environment (Next.js-style)\n if (nodeEnv === 'test' && fileName === '.env.local')\n {\n continue;\n }\n\n // Skip duplicate .env.local when NODE_ENV=local\n // (.env.{NODE_ENV} becomes .env.local, same as .env.local pattern)\n if (nodeEnv === 'local' && pattern === '.env.local')\n {\n continue;\n }\n\n // Skip test files in non-test environments\n if (nodeEnv !== 'test' && TEST_ONLY_FILES.includes(fileName as any))\n {\n continue;\n }\n\n files.push(join(basePath, fileName));\n }\n\n return files;\n}\n\n/**\n * Load a single environment file\n *\n * @param filePath - Absolute path to .env file\n * @param debug - Whether to log debug information\n * @returns Object with success status and parsed variables\n */\nfunction loadSingleFile(\n filePath: string,\n debug: boolean\n): { success: boolean; parsed: Record<string, string>; error?: string }\n{\n if (!existsSync(filePath))\n {\n if (debug)\n {\n envLogger.debug('Environment file not found (optional)', {\n path: filePath,\n });\n }\n return { success: false, parsed: {}, error: 'File not found' };\n }\n\n try\n {\n const result = dotenvConfig({ path: filePath });\n\n if (result.error)\n {\n envLogger.warn('Failed to parse environment file', {\n path: filePath,\n error: result.error.message,\n });\n return {\n success: false,\n parsed: {},\n error: result.error.message,\n };\n }\n\n const parsed = result.parsed || {};\n\n if (debug)\n {\n envLogger.debug('Environment file loaded successfully', {\n path: filePath,\n variables: Object.keys(parsed),\n count: Object.keys(parsed).length,\n });\n }\n\n return { success: true, parsed };\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n envLogger.error('Error loading environment file', {\n path: filePath,\n error: message,\n });\n return { success: false, parsed: {}, error: message };\n }\n}\n\n/**\n * Validate required environment variables\n *\n * @param required - Array of required variable names\n * @param debug - Whether to log debug information\n * @throws Error if any required variables are missing\n */\nfunction validateRequiredVars(required: string[], debug: boolean): void\n{\n const missing: string[] = [];\n\n for (const varName of required)\n {\n if (!process.env[varName])\n {\n missing.push(varName);\n }\n }\n\n if (missing.length > 0)\n {\n const error = `Required environment variables missing: ${missing.join(', ')}`;\n envLogger.error('Environment validation failed', {\n missing,\n required,\n });\n throw new Error(error);\n }\n\n if (debug)\n {\n envLogger.debug('Required environment variables validated', {\n required,\n allPresent: true,\n });\n }\n}\n\n/**\n * Load environment variables from .env files with Next.js-style priority\n *\n * Loading behavior by environment:\n * - (no NODE_ENV): .env → .env.local\n * - development: .env → .env.development → .env.local → .env.development.local\n * - production: .env → .env.production → .env.local → .env.production.local\n * - test: .env → .env.test → (skip .env.local) → .env.test.local\n * - local: .env → .env.local → .env.local.local (duplicate .env.local prevented)\n * - staging/qa/etc: .env → .env.{NODE_ENV} → .env.local → .env.{NODE_ENV}.local\n *\n * Notes:\n * - .env.local is excluded in test environment for proper test isolation\n * - Any custom NODE_ENV value is supported (staging, qa, uat, preview, etc.)\n * - If NODE_ENV is not set, .env and .env.local are loaded\n *\n * @param options - Loading options\n * @returns Load result with success status and loaded variables\n *\n * @example\n * ```typescript\n * // Simple usage (no NODE_ENV set)\n * const result = loadEnvironment();\n *\n * // With NODE_ENV=local\n * process.env.NODE_ENV = 'local';\n * const result = loadEnvironment({\n * debug: true,\n * required: ['DATABASE_URL'],\n * });\n *\n * // With custom environment\n * process.env.NODE_ENV = 'staging';\n * const result = loadEnvironment();\n * ```\n */\nexport function loadEnvironment(options: LoadEnvironmentOptions = {}): LoadResult\n{\n const {\n basePath = process.cwd(),\n customPaths = [],\n debug = false,\n nodeEnv = process.env.NODE_ENV || '',\n required = [],\n useCache = true,\n } = options;\n\n // Return cached result if available\n if (useCache && environmentLoaded && cachedLoadResult)\n {\n if (debug)\n {\n envLogger.debug('Returning cached environment', {\n loaded: cachedLoadResult.loaded.length,\n variables: Object.keys(cachedLoadResult.parsed).length,\n });\n }\n return cachedLoadResult;\n }\n\n if (debug)\n {\n envLogger.debug('Loading environment variables', {\n basePath,\n nodeEnv,\n customPaths,\n required,\n });\n }\n\n const result: LoadResult = {\n success: true,\n loaded: [],\n failed: [],\n parsed: {},\n warnings: [],\n };\n\n // Build standard file list\n const standardFiles = buildFileList(basePath, nodeEnv);\n const allFiles = [...standardFiles, ...customPaths];\n\n if (debug)\n {\n envLogger.debug('Environment files to load', {\n standardFiles,\n customPaths,\n total: allFiles.length,\n });\n }\n\n // Load files in reverse order (highest priority first)\n // This is because dotenv doesn't override existing variables\n // So loading high-priority files first ensures they take precedence\n const reversedFiles = [...allFiles].reverse();\n\n // Load each file in reverse order\n for (const filePath of reversedFiles)\n {\n const fileResult = loadSingleFile(filePath, debug);\n\n if (fileResult.success)\n {\n result.loaded.push(filePath);\n Object.assign(result.parsed, fileResult.parsed);\n\n // Warn if NODE_ENV is set in .env files (Next.js style)\n if (fileResult.parsed['NODE_ENV'])\n {\n const fileName = filePath.split('/').pop() || filePath;\n result.warnings.push(\n `NODE_ENV found in ${fileName}. ` +\n `It's recommended to set NODE_ENV via CLI (e.g., 'spfn dev', 'spfn build') ` +\n `instead of .env files for consistent environment behavior.`\n );\n }\n }\n else if (fileResult.error)\n {\n result.failed.push({\n path: filePath,\n reason: fileResult.error,\n });\n }\n }\n\n // Log summary\n if (debug || result.loaded.length > 0)\n {\n envLogger.info('Environment loading complete', {\n loaded: result.loaded.length,\n failed: result.failed.length,\n variables: Object.keys(result.parsed).length,\n files: result.loaded,\n });\n }\n\n // Validate required variables\n if (required.length > 0)\n {\n try\n {\n validateRequiredVars(required, debug);\n }\n catch (error)\n {\n result.success = false;\n result.errors = [\n error instanceof Error ? error.message : 'Validation failed',\n ];\n throw error;\n }\n }\n\n // Log warnings after validation\n if (result.warnings.length > 0)\n {\n for (const warning of result.warnings)\n {\n envLogger.warn(warning);\n }\n }\n\n // Cache result\n environmentLoaded = true;\n cachedLoadResult = result;\n\n return result;\n}\n\n/**\n * Get an environment variable with optional validation\n *\n * @param key - Environment variable name\n * @param options - Get options (default, required, validator)\n * @returns Variable value or undefined\n * @throws Error if required and not found, or validation fails\n *\n * @example\n * ```typescript\n * // Simple get\n * const dbUrl = getEnvVar('DATABASE_URL');\n *\n * // With default\n * const port = getEnvVar('PORT', { default: '3000' });\n *\n * // Required\n * const apiKey = getEnvVar('API_KEY', { required: true });\n *\n * // With validation\n * const url = getEnvVar('API_URL', {\n * validator: (val) => val.startsWith('https://'),\n * validationError: 'API_URL must use HTTPS',\n * });\n * ```\n */\nexport function getEnvVar(key: string, options: GetEnvOptions = {}): string | undefined\n{\n const {\n required = false,\n default: defaultValue,\n validator,\n validationError,\n } = options;\n\n const value = process.env[key];\n\n // Handle missing value\n if (value === undefined || value === '')\n {\n if (required)\n {\n throw new Error(`Required environment variable not found: ${key}`);\n }\n return defaultValue;\n }\n\n // Validate if validator provided\n if (validator && !validator(value))\n {\n const message = validationError || `Invalid value for environment variable: ${key}`;\n throw new Error(message);\n }\n\n return value;\n}\n\n/**\n * Get a required environment variable\n *\n * @param key - Environment variable name\n * @returns Variable value\n * @throws Error if not found\n *\n * @example\n * ```typescript\n * const dbUrl = requireEnvVar('DATABASE_URL');\n * ```\n */\nexport function requireEnvVar(key: string): string\n{\n return getEnvVar(key, { required: true })!;\n}\n\n/**\n * Check if an environment variable exists\n *\n * @param key - Environment variable name\n * @returns True if variable exists and is non-empty\n *\n * @example\n * ```typescript\n * if (hasEnvVar('REDIS_URL')) {\n * // Use Redis\n * }\n * ```\n */\nexport function hasEnvVar(key: string): boolean\n{\n const value = process.env[key];\n return value !== undefined && value !== '';\n}\n\n/**\n * Get multiple environment variables at once\n *\n * @param keys - Array of environment variable names\n * @returns Object mapping keys to values (undefined if not found)\n *\n * @example\n * ```typescript\n * const { DATABASE_URL, REDIS_URL } = getEnvVars([\n * 'DATABASE_URL',\n * 'REDIS_URL',\n * ]);\n * ```\n */\nexport function getEnvVars(keys: string[]): Record<string, string | undefined>\n{\n const result: Record<string, string | undefined> = {};\n\n for (const key of keys)\n {\n result[key] = process.env[key];\n }\n\n return result;\n}\n\n/**\n * Check if environment has been loaded\n *\n * @returns True if loadEnvironment has been called successfully\n *\n * @example\n * ```typescript\n * if (!isEnvironmentLoaded()) {\n * loadEnvironment();\n * }\n * ```\n */\nexport function isEnvironmentLoaded(): boolean\n{\n return environmentLoaded;\n}\n\n/**\n * Reset environment loading state\n * FOR TESTING ONLY - DO NOT USE IN PRODUCTION\n *\n * @example\n * ```typescript\n * // In test cleanup\n * afterEach(() => {\n * resetEnvironment();\n * });\n * ```\n */\nexport function resetEnvironment(): void\n{\n environmentLoaded = false;\n cachedLoadResult = undefined;\n}","/**\n * Environment Variable Management - Validators\n *\n * Common validation functions for environment variables\n */\n\n/**\n * Validate that a value is a valid URL\n *\n * @param value - Value to validate\n * @param options - Validation options\n * @returns True if valid URL, false otherwise\n *\n * @example\n * ```typescript\n * const apiUrl = getEnvVar('API_URL', {\n * validator: validateUrl,\n * });\n * ```\n */\nexport function validateUrl(\n value: string,\n options: { protocol?: 'http' | 'https' | 'any' } = {}\n): boolean\n{\n const { protocol = 'any' } = options;\n\n try\n {\n const url = new URL(value);\n\n if (protocol === 'http' && url.protocol !== 'http:')\n {\n return false;\n }\n\n if (protocol === 'https' && url.protocol !== 'https:')\n {\n return false;\n }\n\n return true;\n }\n catch\n {\n return false;\n }\n}\n\n/**\n * Create a URL validator with specific protocol requirement\n *\n * @param protocol - Required protocol ('http', 'https', or 'any')\n * @returns Validator function\n *\n * @example\n * ```typescript\n * const apiUrl = getEnvVar('API_URL', {\n * validator: createUrlValidator('https'),\n * validationError: 'API_URL must use HTTPS',\n * });\n * ```\n */\nexport function createUrlValidator(protocol: 'http' | 'https' | 'any' = 'any')\n{\n return (value: string) => validateUrl(value, { protocol });\n}\n\n/**\n * Validate that a value is a valid number\n *\n * @param value - Value to validate\n * @param options - Validation options\n * @returns True if valid number, false otherwise\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * validator: (val) => validateNumber(val, { min: 1, max: 65535 }),\n * });\n * ```\n */\nexport function validateNumber(\n value: string,\n options: { min?: number; max?: number; integer?: boolean } = {}\n): boolean\n{\n const { min, max, integer = false } = options;\n\n // Reject empty strings (Number('') returns 0 which is misleading)\n if (value.trim() === '')\n {\n return false;\n }\n\n const num = Number(value);\n\n if (isNaN(num))\n {\n return false;\n }\n\n if (integer && !Number.isInteger(num))\n {\n return false;\n }\n\n if (min !== undefined && num < min)\n {\n return false;\n }\n\n if (max !== undefined && num > max)\n {\n return false;\n }\n\n return true;\n}\n\n/**\n * Create a number validator with specific constraints\n *\n * @param options - Validation constraints\n * @returns Validator function\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * validator: createNumberValidator({ min: 1, max: 65535, integer: true }),\n * validationError: 'PORT must be an integer between 1 and 65535',\n * });\n * ```\n */\nexport function createNumberValidator(\n options: { min?: number; max?: number; integer?: boolean } = {}\n)\n{\n return (value: string) => validateNumber(value, options);\n}\n\n/**\n * Validate that a value is a valid boolean string\n *\n * @param value - Value to validate\n * @returns True if valid boolean string, false otherwise\n *\n * @example\n * ```typescript\n * const debugMode = getEnvVar('DEBUG', {\n * validator: validateBoolean,\n * });\n * ```\n */\nexport function validateBoolean(value: string): boolean\n{\n const normalized = value.toLowerCase().trim();\n return ['true', 'false', '1', '0', 'yes', 'no'].includes(normalized);\n}\n\n/**\n * Parse a boolean environment variable\n *\n * @param value - Value to parse\n * @returns Boolean value\n *\n * @example\n * ```typescript\n * const debug = parseBoolean(getEnvVar('DEBUG', { default: 'false' })!);\n * ```\n */\nexport function parseBoolean(value: string): boolean\n{\n const normalized = value.toLowerCase().trim();\n return ['true', '1', 'yes'].includes(normalized);\n}\n\n/**\n * Validate that a value is one of allowed options\n *\n * @param value - Value to validate\n * @param allowed - Array of allowed values\n * @param caseInsensitive - Whether to perform case-insensitive comparison\n * @returns True if value is in allowed list, false otherwise\n *\n * @example\n * ```typescript\n * const env = getEnvVar('NODE_ENV', {\n * validator: (val) => validateEnum(val, ['development', 'production', 'test']),\n * });\n * ```\n */\nexport function validateEnum(\n value: string,\n allowed: string[],\n caseInsensitive = false\n): boolean\n{\n if (caseInsensitive)\n {\n const normalizedValue = value.toLowerCase();\n const normalizedAllowed = allowed.map((v) => v.toLowerCase());\n return normalizedAllowed.includes(normalizedValue);\n }\n\n return allowed.includes(value);\n}\n\n/**\n * Create an enum validator with specific allowed values\n *\n * @param allowed - Array of allowed values\n * @param caseInsensitive - Whether to perform case-insensitive comparison\n * @returns Validator function\n *\n * @example\n * ```typescript\n * const logLevel = getEnvVar('LOG_LEVEL', {\n * validator: createEnumValidator(['debug', 'info', 'warn', 'error']),\n * validationError: 'LOG_LEVEL must be one of: debug, info, warn, error',\n * });\n * ```\n */\nexport function createEnumValidator(allowed: string[], caseInsensitive = false)\n{\n return (value: string) => validateEnum(value, allowed, caseInsensitive);\n}\n\n/**\n * Validate that a value matches a regular expression\n *\n * @param value - Value to validate\n * @param pattern - Regular expression pattern\n * @returns True if value matches pattern, false otherwise\n *\n * @example\n * ```typescript\n * const apiKey = getEnvVar('API_KEY', {\n * validator: (val) => validatePattern(val, /^[A-Za-z0-9_-]{32}$/),\n * });\n * ```\n */\nexport function validatePattern(value: string, pattern: RegExp): boolean\n{\n return pattern.test(value);\n}\n\n/**\n * Create a pattern validator with specific regex\n *\n * @param pattern - Regular expression pattern\n * @returns Validator function\n *\n * @example\n * ```typescript\n * const apiKey = getEnvVar('API_KEY', {\n * validator: createPatternValidator(/^[A-Za-z0-9_-]{32}$/),\n * validationError: 'API_KEY must be 32 alphanumeric characters',\n * });\n * ```\n */\nexport function createPatternValidator(pattern: RegExp)\n{\n return (value: string) => validatePattern(value, pattern);\n}\n\n/**\n * Validate that a value is not empty\n *\n * @param value - Value to validate\n * @returns True if not empty, false otherwise\n *\n * @example\n * ```typescript\n * const name = getEnvVar('APP_NAME', {\n * validator: validateNotEmpty,\n * });\n * ```\n */\nexport function validateNotEmpty(value: string): boolean\n{\n return value.trim().length > 0;\n}\n\n/**\n * Validate that a value has minimum length\n *\n * @param value - Value to validate\n * @param minLength - Minimum required length\n * @returns True if meets minimum length, false otherwise\n *\n * @example\n * ```typescript\n * const password = getEnvVar('DB_PASSWORD', {\n * validator: (val) => validateMinLength(val, 8),\n * });\n * ```\n */\nexport function validateMinLength(value: string, minLength: number): boolean\n{\n return value.length >= minLength;\n}\n\n/**\n * Create a minimum length validator\n *\n * @param minLength - Minimum required length\n * @returns Validator function\n *\n * @example\n * ```typescript\n * const password = getEnvVar('DB_PASSWORD', {\n * validator: createMinLengthValidator(8),\n * validationError: 'DB_PASSWORD must be at least 8 characters',\n * });\n * ```\n */\nexport function createMinLengthValidator(minLength: number)\n{\n return (value: string) => validateMinLength(value, minLength);\n}\n\n/**\n * Combine multiple validators with AND logic\n *\n * @param validators - Array of validator functions\n * @returns Combined validator function\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * validator: combineValidators([\n * validateNotEmpty,\n * createNumberValidator({ min: 1, max: 65535, integer: true }),\n * ]),\n * });\n * ```\n */\nexport function combineValidators(validators: Array<(value: string) => boolean>)\n{\n return (value: string) => validators.every((validator) => validator(value));\n}\n\n/**\n * Validate PostgreSQL connection string\n *\n * @param value - Value to validate\n * @returns True if valid PostgreSQL URL, false otherwise\n *\n * @example\n * ```typescript\n * const dbUrl = getEnvVar('DATABASE_URL', {\n * validator: validatePostgresUrl,\n * });\n * ```\n */\nexport function validatePostgresUrl(value: string): boolean\n{\n try\n {\n const url = new URL(value);\n return url.protocol === 'postgres:' || url.protocol === 'postgresql:';\n }\n catch\n {\n return false;\n }\n}\n\n/**\n * Validate Redis connection string\n *\n * @param value - Value to validate\n * @returns True if valid Redis URL, false otherwise\n *\n * @example\n * ```typescript\n * const redisUrl = getEnvVar('REDIS_URL', {\n * validator: validateRedisUrl,\n * });\n * ```\n */\nexport function validateRedisUrl(value: string): boolean\n{\n try\n {\n const url = new URL(value);\n return url.protocol === 'redis:' || url.protocol === 'rediss:';\n }\n catch\n {\n return false;\n }\n}"]}
|
|
1
|
+
{"version":3,"sources":["../../src/env/validator.ts","../../src/env/schema.ts","../../src/env/registry.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Environment Variable Management - Parsers\n *\n * Parser functions that transform and validate environment variable strings.\n * All parsers follow the pattern: (value: string) => T or throw Error\n */\n\n// ============================================================================\n// Core Types\n// ============================================================================\n\n/**\n * Parser function that transforms and validates a string value\n * @throws Error if validation fails\n */\nexport type Parser<T> = (value: string) => T;\n\n// ============================================================================\n// String Parsers\n// ============================================================================\n\n/**\n * Parse a non-empty string\n *\n * @param value - Value to parse\n * @returns Trimmed string\n * @throws Error if string is empty after trimming\n *\n * @example\n * ```typescript\n * const name = getEnvVar('APP_NAME', {\n * validator: parseString,\n * });\n * ```\n */\nexport function parseString(value: string): string\n{\n const trimmed = value.trim();\n\n if (trimmed.length === 0)\n {\n throw new Error('Value cannot be empty');\n }\n\n return trimmed;\n}\n\n/**\n * Create a string parser with validation rules\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const apiKey = getEnvVar('API_KEY', {\n * validator: createStringParser({\n * minLength: 32,\n * pattern: /^[A-Za-z0-9_-]+$/,\n * }),\n * });\n * ```\n */\nexport function createStringParser(\n options: {\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n trim?: boolean;\n } = {}\n): Parser<string>\n{\n return (value: string): string =>\n {\n const { minLength, maxLength, pattern, trim = true } = options;\n\n let result = trim ? value.trim() : value;\n\n // Empty check\n if (result.length === 0)\n {\n throw new Error('Value cannot be empty');\n }\n\n // Length validation\n if (minLength !== undefined && result.length < minLength)\n {\n throw new Error(`Must be at least ${minLength} characters long (current: ${result.length})`);\n }\n\n if (maxLength !== undefined && result.length > maxLength)\n {\n throw new Error(`Must be at most ${maxLength} characters long (current: ${result.length})`);\n }\n\n // Pattern validation\n if (pattern && !pattern.test(result))\n {\n throw new Error(`Must match pattern ${pattern}`);\n }\n\n return result;\n };\n}\n\n// ============================================================================\n// Boolean Parser\n// ============================================================================\n\n/**\n * Parse a boolean environment variable\n *\n * Accepts: 'true', '1', 'yes' (case-insensitive) → true\n * 'false', '0', 'no' (case-insensitive) → false\n *\n * @param value - Value to parse\n * @returns Boolean value\n * @throws Error if value is not a valid boolean string\n *\n * @example\n * ```typescript\n * const debug = getEnvVar('DEBUG', {\n * default: 'false',\n * validator: parseBoolean,\n * });\n * ```\n */\nexport function parseBoolean(value: string): boolean\n{\n const normalized = value.toLowerCase().trim();\n\n if (['true', '1', 'yes'].includes(normalized))\n {\n return true;\n }\n\n if (['false', '0', 'no'].includes(normalized))\n {\n return false;\n }\n\n throw new Error(\n `Must be a boolean value (true/false, 1/0, yes/no), got: ${value}`\n );\n}\n\n// ============================================================================\n// Number Parsers\n// ============================================================================\n\n/**\n * Parse and validate number\n *\n * @param value - Value to parse\n * @param options - Validation options\n * @returns Parsed number\n * @throws Error if invalid number or constraint violation\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * default: '3000',\n * validator: (val) => parseNumber(val, { min: 1, max: 65535, integer: true }),\n * });\n * ```\n */\nexport function parseNumber(\n value: string,\n options: { min?: number; max?: number; integer?: boolean } = {}\n): number\n{\n const { min, max, integer = false } = options;\n\n // Reject empty strings\n if (value.trim() === '')\n {\n throw new Error('Value cannot be empty');\n }\n\n const num = Number(value);\n\n if (isNaN(num))\n {\n throw new Error(`Must be a valid number, got: ${value}`);\n }\n\n if (integer && !Number.isInteger(num))\n {\n throw new Error(`Must be an integer, got: ${value}`);\n }\n\n if (min !== undefined && num < min)\n {\n throw new Error(`Must be at least ${min}, got: ${num}`);\n }\n\n if (max !== undefined && num > max)\n {\n throw new Error(`Must be at most ${max}, got: ${num}`);\n }\n\n return num;\n}\n\n/**\n * Create a number parser with specific constraints\n *\n * @param options - Validation constraints\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const port = getEnvVar('PORT', {\n * default: '3000',\n * validator: createNumberParser({ min: 1, max: 65535, integer: true }),\n * });\n * ```\n */\nexport function createNumberParser(\n options: { min?: number; max?: number; integer?: boolean } = {}\n): Parser<number>\n{\n return (value: string) => parseNumber(value, options);\n}\n\n/**\n * Parse integer with optional constraints\n *\n * @param value - Value to parse\n * @param options - Min/max constraints\n * @returns Parsed integer\n * @throws Error if invalid or out of range\n *\n * @example\n * ```typescript\n * const retries = getEnvVar('MAX_RETRIES', {\n * default: '3',\n * validator: (val) => parseInteger(val, { min: 1, max: 10 }),\n * });\n * ```\n */\nexport function parseInteger(\n value: string,\n options: { min?: number; max?: number } = {}\n): number\n{\n return parseNumber(value, { ...options, integer: true });\n}\n\n/**\n * Parse float/decimal number with optional constraints\n *\n * @param value - Value to parse\n * @param options - Min/max constraints\n * @returns Parsed decimal number\n * @throws Error if invalid or out of range\n *\n * @example\n * ```typescript\n * const ratio = getEnvVar('CACHE_RATIO', {\n * default: '0.75',\n * validator: (val) => parseDecimal(val, { min: 0, max: 1 }),\n * });\n * ```\n */\nexport function parseDecimal(\n value: string,\n options: { min?: number; max?: number } = {}\n): number\n{\n return parseNumber(value, { ...options, integer: false });\n}\n\n// ============================================================================\n// URL Parsers\n// ============================================================================\n\n/**\n * Parse and validate URL\n *\n * @param value - Value to parse\n * @param options - Validation options\n * @returns Validated URL string\n * @throws Error if invalid URL or protocol mismatch\n *\n * @example\n * ```typescript\n * const apiUrl = getEnvVar('API_URL', {\n * validator: (val) => parseUrl(val, { protocol: 'https' }),\n * });\n * ```\n */\nexport function parseUrl(\n value: string,\n options: { protocol?: 'http' | 'https' | 'any' } = {}\n): string\n{\n const { protocol = 'any' } = options;\n\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n throw new Error(`Invalid URL: ${value}`);\n }\n throw error;\n }\n\n // Validate protocol\n if (protocol === 'http' && url.protocol !== 'http:')\n {\n throw new Error(`URL must use HTTP protocol, got ${url.protocol}`);\n }\n\n if (protocol === 'https' && url.protocol !== 'https:')\n {\n throw new Error(`URL must use HTTPS protocol, got ${url.protocol}`);\n }\n\n return value;\n}\n\n/**\n * Create a URL parser with specific protocol requirement\n *\n * @param protocol - Required protocol ('http', 'https', or 'any')\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const apiUrl = getEnvVar('API_URL', {\n * validator: createUrlParser('https'),\n * });\n * ```\n */\nexport function createUrlParser(protocol: 'http' | 'https' | 'any' = 'any'): Parser<string>\n{\n return (value: string) => parseUrl(value, { protocol });\n}\n\n/**\n * Parse PostgreSQL connection string\n *\n * @param value - Value to parse\n * @returns Validated PostgreSQL URL string\n * @throws Error if invalid PostgreSQL URL\n *\n * @example\n * ```typescript\n * const dbUrl = getEnvVar('DATABASE_URL', {\n * required: true,\n * validator: parsePostgresUrl,\n * });\n * ```\n */\nexport function parsePostgresUrl(value: string): string\n{\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n throw new Error(`Invalid PostgreSQL URL: ${value}`);\n }\n throw error;\n }\n\n // Validate protocol\n if (url.protocol !== 'postgres:' && url.protocol !== 'postgresql:')\n {\n throw new Error(\n `Must be a PostgreSQL URL (postgres:// or postgresql://), got ${url.protocol}`\n );\n }\n\n return value;\n}\n\n/**\n * Parse Redis connection string\n *\n * @param value - Value to parse\n * @returns Validated Redis URL string\n * @throws Error if invalid Redis URL\n *\n * @example\n * ```typescript\n * const redisUrl = getEnvVar('REDIS_URL', {\n * required: true,\n * validator: parseRedisUrl,\n * });\n * ```\n */\nexport function parseRedisUrl(value: string): string\n{\n // Parse URL (may throw TypeError)\n let url: URL;\n try\n {\n url = new URL(value);\n }\n catch (error)\n {\n if (error instanceof TypeError)\n {\n throw new Error(`Invalid Redis URL: ${value}`);\n }\n throw error;\n }\n\n // Validate protocol\n if (url.protocol !== 'redis:' && url.protocol !== 'rediss:')\n {\n throw new Error(\n `Must be a Redis URL (redis:// or rediss://), got ${url.protocol}`\n );\n }\n\n return value;\n}\n\n// ============================================================================\n// Enum Parser\n// ============================================================================\n\n/**\n * Parse and validate enum value\n *\n * @param value - Value to parse\n * @param allowed - Array of allowed values\n * @param caseInsensitive - Whether to perform case-insensitive comparison\n * @returns Validated enum value\n * @throws Error if value not in allowed list\n *\n * @example\n * ```typescript\n * const env = getEnvVar('NODE_ENV', {\n * validator: (val) => parseEnum(val, ['development', 'production', 'test']),\n * });\n * ```\n */\nexport function parseEnum(\n value: string,\n allowed: string[],\n caseInsensitive = false\n): string\n{\n if (caseInsensitive)\n {\n const normalizedValue = value.toLowerCase();\n const normalizedAllowed = allowed.map((v) => v.toLowerCase());\n const index = normalizedAllowed.indexOf(normalizedValue);\n\n if (index === -1)\n {\n throw new Error(\n `Must be one of [${allowed.join(', ')}], got: ${value}`\n );\n }\n\n return allowed[index]; // Return original case from allowed list\n }\n\n if (!allowed.includes(value))\n {\n throw new Error(\n `Must be one of [${allowed.join(', ')}], got: ${value}`\n );\n }\n\n return value;\n}\n\n/**\n * Create an enum parser with specific allowed values\n *\n * @param allowed - Array of allowed values\n * @param caseInsensitive - Whether to perform case-insensitive comparison\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const logLevel = getEnvVar('LOG_LEVEL', {\n * default: 'info',\n * validator: createEnumParser(['debug', 'info', 'warn', 'error']),\n * });\n * ```\n */\nexport function createEnumParser(allowed: string[], caseInsensitive = false): Parser<string>\n{\n return (value: string) => parseEnum(value, allowed, caseInsensitive);\n}\n\n// ============================================================================\n// JSON Parser\n// ============================================================================\n\n/**\n * Parse JSON string\n *\n * @param value - JSON string to parse\n * @returns Parsed JSON value\n * @throws Error if invalid JSON\n *\n * @example\n * ```typescript\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: parseJson,\n * });\n * ```\n */\nexport function parseJson<T = any>(value: string): T\n{\n try\n {\n return JSON.parse(value) as T;\n }\n catch (error)\n {\n throw new Error(\n `Invalid JSON: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n}\n\n/**\n * Create a typed JSON parser\n *\n * @returns Parser function\n *\n * @example\n * ```typescript\n * interface Config {\n * host: string;\n * port: number;\n * }\n *\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: createJsonParser<Config>(),\n * });\n * ```\n */\nexport function createJsonParser<T>(): Parser<T>\n{\n return (value: string) => parseJson<T>(value);\n}\n\n// ============================================================================\n// Array Parser\n// ============================================================================\n\n/**\n * Parse comma-separated values into array\n *\n * @param value - Comma-separated string\n * @param options - Parser options\n * @returns Array of strings\n *\n * @example\n * ```typescript\n * const hosts = getEnvVar('ALLOWED_HOSTS', {\n * validator: parseArray,\n * });\n * // \"localhost,example.com,api.example.com\" → ['localhost', 'example.com', 'api.example.com']\n * ```\n */\nexport function parseArray(\n value: string,\n options: {\n separator?: string;\n trim?: boolean;\n filter?: (item: string) => boolean;\n } = {}\n): string[]\n{\n const { separator = ',', trim = true, filter } = options;\n\n if (value.trim() === '')\n {\n return [];\n }\n\n let items = value.split(separator);\n\n if (trim)\n {\n items = items.map((item) => item.trim());\n }\n\n if (filter)\n {\n items = items.filter(filter);\n }\n\n return items;\n}\n\n/**\n * Create an array parser with item parser\n *\n * @param itemParser - Parser to apply to each array item\n * @param options - Array parsing options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * // Parse comma-separated ports\n * const ports = getEnvVar('PORTS', {\n * validator: createArrayParser(\n * createNumberParser({ min: 1, max: 65535, integer: true })\n * ),\n * });\n * // \"3000,4000,5000\" → [3000, 4000, 5000]\n * ```\n */\nexport function createArrayParser<T>(\n itemParser: Parser<T>,\n options: { separator?: string } = {}\n): Parser<T[]>\n{\n return (value: string): T[] =>\n {\n const items = parseArray(value, options);\n\n return items.map((item, index) =>\n {\n try\n {\n return itemParser(item);\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Invalid item at index ${index}: ${message}`);\n }\n });\n };\n}\n\n// ============================================================================\n// Secure Secret Parser\n// ============================================================================\n\n/**\n * Calculate Shannon entropy of a string\n * Returns entropy in bits per character\n *\n * @param str - String to calculate entropy for\n * @returns Entropy value (0 to ~6.6 bits for printable ASCII)\n *\n * @example\n * ```typescript\n * const entropy = calculateEntropy('my-secret-key');\n * // Higher entropy = more random\n * // - Random lowercase: ~4.7 bits/char\n * // - Random alphanumeric: ~5.2 bits/char\n * // - Random printable ASCII: ~6.6 bits/char\n * // - \"aaaaaaa...\": ~0 bits/char\n * ```\n */\nfunction calculateEntropy(str: string): number\n{\n const len = str.length;\n const frequencies = new Map<string, number>();\n\n // Count character frequencies\n for (const char of str)\n {\n frequencies.set(char, (frequencies.get(char) || 0) + 1);\n }\n\n // Calculate Shannon entropy\n let entropy = 0;\n for (const count of frequencies.values())\n {\n const probability = count / len;\n entropy -= probability * Math.log2(probability);\n }\n\n return entropy;\n}\n\n/**\n * Create a secure secret parser with entropy validation\n *\n * Validates cryptographic secrets for sufficient length, character diversity, and randomness.\n * Uses Shannon entropy to measure randomness quality.\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const sessionSecret = getEnvVar('SESSION_SECRET', {\n * validator: createSecureSecretParser({\n * minLength: 32, // Minimum 256-bit\n * minUniqueChars: 16, // Character diversity\n * minEntropy: 3.5, // Shannon entropy (bits/char)\n * }),\n * });\n * ```\n */\nexport function createSecureSecretParser(\n options: {\n minLength?: number;\n minUniqueChars?: number;\n minEntropy?: number;\n } = {}\n): Parser<string>\n{\n const {\n minLength = 32,\n minUniqueChars = 16,\n minEntropy = 3.5,\n } = options;\n\n return (value: string): string =>\n {\n const length = value.length;\n const uniqueChars = new Set(value).size;\n const entropy = calculateEntropy(value);\n\n // Check length (minimum for cryptographic strength)\n if (length < minLength)\n {\n throw new Error(\n `Secret too short: ${length} characters (minimum: ${minLength})`\n );\n }\n\n // Check unique character diversity\n if (uniqueChars < minUniqueChars)\n {\n throw new Error(\n `Secret has low diversity: ${uniqueChars} unique characters (minimum: ${minUniqueChars})`\n );\n }\n\n // Check Shannon entropy (randomness quality)\n // Reference values:\n // - Random lowercase: ~4.7 bits/char\n // - Random alphanumeric: ~5.2 bits/char\n // - Random printable ASCII: ~6.6 bits/char\n // - \"aaaaaaa...\": ~0 bits/char\n // - \"abcabcabc...\": ~1.58 bits/char\n if (entropy < minEntropy)\n {\n throw new Error(\n `Secret has low entropy: ${entropy.toFixed(2)} bits/char (minimum: ${minEntropy}). Use a more random secret.`\n );\n }\n\n return value;\n };\n}\n\n// ============================================================================\n// Password Parser\n// ============================================================================\n\n/**\n * Create a password strength parser\n *\n * Validates password strength based on configurable requirements.\n * Useful for enforcing password policies in environment variables or user input.\n *\n * @param options - Validation options\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const adminPassword = getEnvVar('ADMIN_PASSWORD', {\n * validator: createPasswordParser({\n * minLength: 12,\n * requireUppercase: true,\n * requireLowercase: true,\n * requireNumber: true,\n * requireSpecial: true,\n * }),\n * });\n * ```\n */\nexport function createPasswordParser(\n options: {\n minLength?: number;\n requireUppercase?: boolean;\n requireLowercase?: boolean;\n requireNumber?: boolean;\n requireSpecial?: boolean;\n } = {}\n): Parser<string>\n{\n const {\n minLength = 8,\n requireUppercase = true,\n requireLowercase = true,\n requireNumber = true,\n requireSpecial = true,\n } = options;\n\n return (value: string): string =>\n {\n const errors: string[] = [];\n\n // Length check\n if (value.length < minLength)\n {\n errors.push(`Must be at least ${minLength} characters`);\n }\n\n // Uppercase check\n if (requireUppercase && !/[A-Z]/.test(value))\n {\n errors.push('Must contain at least one uppercase letter');\n }\n\n // Lowercase check\n if (requireLowercase && !/[a-z]/.test(value))\n {\n errors.push('Must contain at least one lowercase letter');\n }\n\n // Number check\n if (requireNumber && !/[0-9]/.test(value))\n {\n errors.push('Must contain at least one number');\n }\n\n // Special character check\n if (requireSpecial && !/[^A-Za-z0-9]/.test(value))\n {\n errors.push('Must contain at least one special character');\n }\n\n if (errors.length > 0)\n {\n throw new Error(`Password validation failed: ${errors.join(', ')}`);\n }\n\n return value;\n };\n}\n\n// ============================================================================\n// Parser Composition\n// ============================================================================\n\n/**\n * Chain multiple parsers sequentially\n *\n * Each parser receives the output of the previous parser.\n * Useful for multi-step validation/transformation.\n *\n * @param parsers - Array of parser functions\n * @returns Combined parser function\n *\n * @example\n * ```typescript\n * const apiKey = getEnvVar('API_KEY', {\n * validator: chain(\n * parseString,\n * createStringParser({ minLength: 32, pattern: /^[A-Za-z0-9_-]+$/ }),\n * ),\n * });\n * ```\n */\nexport function chain<T>(...parsers: Array<Parser<T>>): Parser<T>\n{\n return (value: string): T =>\n {\n let result = value as any;\n\n for (const parser of parsers)\n {\n result = parser(result);\n }\n\n return result;\n };\n}\n\n/**\n * Apply parser with fallback value\n *\n * If parser throws, returns fallback instead.\n * Useful for optional environment variables with complex parsing.\n *\n * @param parser - Parser to attempt\n * @param fallback - Fallback value if parsing fails\n * @returns Parser function\n *\n * @example\n * ```typescript\n * const config = getEnvVar('CONFIG_JSON', {\n * validator: withFallback(parseJson, { host: 'localhost', port: 3000 }),\n * });\n * ```\n */\nexport function withFallback<T>(parser: Parser<T>, fallback: T): Parser<T>\n{\n return (value: string): T =>\n {\n try\n {\n return parser(value);\n }\n catch\n {\n return fallback;\n }\n };\n}\n\n/**\n * Make parser optional\n *\n * Returns undefined for empty strings instead of throwing.\n *\n * @param parser - Parser to make optional\n * @returns Parser function that returns T | undefined\n *\n * @example\n * ```typescript\n * const redisUrl = getEnvVar('REDIS_URL', {\n * validator: optional(parseRedisUrl),\n * });\n * // Empty string → undefined\n * // Valid URL → parsed URL\n * // Invalid URL → throws\n * ```\n */\nexport function optional<T>(parser: Parser<T>): Parser<T | undefined>\n{\n return (value: string): T | undefined =>\n {\n if (value.trim() === '')\n {\n return undefined;\n }\n\n return parser(value);\n };\n}","/**\n * Environment Variable Schema Definition System\n *\n * 환경변수에 메타데이터를 정의하여 중앙 관리, 문서화, 검증을 지원합니다.\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envUrl({\n * description: 'Database connection',\n * required: true,\n * validator: parsePostgresUrl,\n * sensitive: true,\n * })\n * });\n * ```\n *\n * @module env/schema\n */\n\nimport { parseBoolean, parseNumber, parseJson } from './validator';\n\n/**\n * 환경변수 스키마 정의\n */\nexport interface EnvVarSchema<T = string>\n{\n /** 환경변수 키 */\n key: string;\n\n /** 설명 (목적, 사용처) */\n description: string;\n\n /** 타입 */\n type: 'string' | 'number' | 'boolean' | 'url' | 'enum' | 'json';\n\n /** 필수 여부 */\n required?: boolean;\n\n /** 기본값 */\n default?: T;\n\n /** 검증/변환 함수 */\n validator?: (value: string) => T;\n\n // === 검증 옵션 ===\n\n /** Fallback 환경변수 키들 (backward compatibility) */\n fallbackKeys?: string[];\n\n /** 최소 길이 (문자열 타입) */\n minLength?: number;\n\n // === 메타데이터 ===\n\n /** 민감정보 여부 (로깅 시 마스킹) */\n sensitive?: boolean;\n\n /** 예시 값들 (타입과 일치해야 함) */\n examples?: T[];\n}\n\n/**\n * 스키마 컬렉션 타입\n */\nexport type EnvSchemaCollection = Record<string, EnvVarSchema<any>>;\n\n/**\n * Helper type: Check if field has default value\n */\ntype HasDefault<T> = T extends { default: any } ? true : false;\n\n/**\n * Helper type: Check if field is explicitly required\n */\ntype IsRequired<T> = T extends { required: true } ? true : false;\n\n/**\n * Helper type: Check if field should be required (has default OR required: true)\n */\ntype ShouldBeRequired<T> = HasDefault<T> extends true ? true : IsRequired<T>;\n\n/**\n * 스키마로부터 타입 추출\n *\n * required: true 또는 default가 있는 필드 → 필수\n * required: false 또는 미지정 → optional (| undefined)\n */\nexport type InferEnvType<T extends EnvSchemaCollection> = {\n // Required fields (required: true OR has default)\n [K in keyof T as ShouldBeRequired<T[K]> extends true ? K : never]:\n T[K] extends EnvVarSchema<infer U> ? U : string;\n} & {\n // Optional fields (required: false OR not specified)\n [K in keyof T as ShouldBeRequired<T[K]> extends true ? never : K]?:\n T[K] extends EnvVarSchema<infer U> ? U | undefined : string | undefined;\n};\n\n/**\n * 스키마 정의 헬퍼 (타입 추론 지원)\n *\n * Automatically fills in the `key` property from object keys.\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n * // Automatically adds key: 'DATABASE_URL'\n * ```\n */\nexport function defineEnvSchema<T extends Record<string, any>>(\n schema: T\n): { [K in keyof T]: T[K] & { key: K } }\n{\n const result: any = {};\n\n for (const key in schema)\n {\n result[key] = {\n ...schema[key],\n key,\n };\n }\n\n return result;\n}\n\n/**\n * 문자열 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * API_KEY: {\n * ...envString({\n * description: 'API authentication key',\n * required: true,\n * sensitive: true,\n * }),\n * key: 'API_KEY',\n * }\n * };\n * ```\n */\nexport function envString<T extends Omit<EnvVarSchema, 'key' | 'type'>>(\n options: T\n): T & { type: 'string' }\n{\n return {\n ...options,\n type: 'string',\n };\n}\n\n/**\n * 숫자 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * PORT: {\n * ...envNumber({\n * description: 'Server port',\n * default: 3000,\n * validator: createNumberParser({ min: 1, max: 65535 }),\n * }),\n * key: 'PORT',\n * }\n * };\n * ```\n */\nexport function envNumber<T extends Omit<EnvVarSchema<number>, 'key' | 'type'>>(\n options: T\n): T & { type: 'number'; validator: (value: string) => number }\n{\n return {\n ...options,\n type: 'number',\n validator: options.validator || parseNumber,\n };\n}\n\n/**\n * Boolean 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * DEBUG: {\n * ...envBoolean({\n * description: 'Enable debug mode',\n * default: false,\n * }),\n * key: 'DEBUG',\n * }\n * };\n * ```\n */\nexport function envBoolean<T extends Omit<EnvVarSchema<boolean>, 'key' | 'type'>>(\n options: T\n): T & { type: 'boolean'; validator: (value: string) => boolean }\n{\n return {\n ...options,\n type: 'boolean',\n validator: options.validator || parseBoolean,\n };\n}\n\n/**\n * URL 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * DATABASE_URL: {\n * ...envUrl({\n * description: 'Database connection URL',\n * required: true,\n * validator: parsePostgresUrl,\n * }),\n * key: 'DATABASE_URL',\n * }\n * };\n * ```\n */\nexport function envUrl<T extends Omit<EnvVarSchema, 'key' | 'type'>>(\n options: T\n): T & { type: 'url' }\n{\n return {\n ...options,\n type: 'url',\n };\n}\n\n/**\n * Enum 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * LOG_LEVEL: {\n * ...envEnum(['debug', 'info', 'warn', 'error'] as const, {\n * description: 'Logging level',\n * default: 'info',\n * }),\n * key: 'LOG_LEVEL',\n * }\n * };\n * ```\n */\nexport function envEnum<\n T extends string,\n O extends Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'>\n>(\n allowed: readonly T[],\n options: O\n): O & { type: 'enum'; validator: (val: string) => T }\n{\n return {\n ...options,\n type: 'enum',\n validator: (val: string): T =>\n {\n if (!allowed.includes(val as T))\n {\n throw new Error(`Must be one of: ${allowed.join(', ')}, got: ${val}`);\n }\n\n return val as T;\n },\n };\n}\n\n/**\n * JSON 스키마 헬퍼\n *\n * @example\n * ```typescript\n * const schema = {\n * CONFIG_JSON: {\n * ...envJson<{ host: string; port: number }>({\n * description: 'JSON configuration object',\n * required: true,\n * }),\n * key: 'CONFIG_JSON',\n * }\n * };\n * ```\n */\nexport function envJson<\n T = any,\n O extends Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'> = Omit<EnvVarSchema<T>, 'key' | 'type' | 'validator'>\n>(\n options: O\n): O & { type: 'json'; validator: (val: string) => T }\n{\n return {\n ...options,\n type: 'json',\n validator: (val: string) => parseJson<T>(val),\n };\n}\n\n/**\n * 환경변수가 클라이언트에서 접근 가능한지 확인\n * (NEXT_PUBLIC_ 접두사로 판단)\n *\n * @param key - 환경변수 키\n * @returns 클라이언트에서 접근 가능하면 true\n *\n * @example\n * ```typescript\n * isClientAccessible('NEXT_PUBLIC_API_URL'); // true\n * isClientAccessible('DATABASE_URL'); // false\n * ```\n */\nexport function isClientAccessible(key: string): boolean\n{\n return key.startsWith('NEXT_PUBLIC_');\n}\n\n/**\n * 환경변수가 서버 전용인지 확인\n * (NEXT_PUBLIC_ 접두사가 없으면 서버 전용)\n *\n * @param key - 환경변수 키\n * @returns 서버 전용이면 true\n *\n * @example\n * ```typescript\n * isServerOnly('DATABASE_URL'); // true\n * isServerOnly('NEXT_PUBLIC_API_URL'); // false\n * ```\n */\nexport function isServerOnly(key: string): boolean\n{\n return !isClientAccessible(key);\n}","/**\n * Environment Variable Registry\n *\n * 환경변수 스키마를 등록하고 타입 안전하게 접근할 수 있는 레지스트리\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n *\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate(); // 검증 + env 반환\n * console.log(env.DATABASE_URL);\n * ```\n *\n * @module env/registry\n */\nimport type { EnvVarSchema, EnvSchemaCollection, InferEnvType } from './schema';\nimport { isClientAccessible } from './schema';\nimport { logger } from '@spfn/core/logger';\n\nconst envLogger = logger.child('@spfn/core:env-registry')\n\n\n/**\n * 환경변수 레지스트리\n *\n * 스키마 기반 환경변수 관리 및 검증\n */\nexport class EnvRegistry<T extends EnvSchemaCollection = EnvSchemaCollection>\n{\n private schemas = new Map<string, EnvVarSchema>();\n private hasValidated = false;\n private valueCache = new Map<string, any>();\n\n constructor(schemas?: T)\n {\n if (schemas)\n {\n this.registerMultiple(schemas);\n }\n }\n\n /**\n * 스키마 등록\n */\n register(schema: EnvVarSchema): void\n {\n this.schemas.set(schema.key, schema);\n }\n\n /**\n * 여러 스키마 등록\n */\n registerMultiple(schemas: EnvSchemaCollection): void\n {\n for (const [key, schema] of Object.entries(schemas))\n {\n this.register({ ...schema, key });\n }\n }\n\n /**\n * 캐시 및 검증 상태 리셋 (테스트용)\n */\n reset(): void\n {\n this.valueCache.clear();\n this.hasValidated = false;\n }\n\n /**\n * 환경변수 원시값 가져오기 (fallback 지원)\n */\n private getRawValue(key: string, fallbackKeys?: string[]): string | undefined\n {\n let value = process.env[key];\n\n if (!value && fallbackKeys)\n {\n for (const fallbackKey of fallbackKeys)\n {\n value = process.env[fallbackKey];\n if (value)\n {\n break;\n }\n }\n }\n\n return value;\n }\n\n /**\n * 값에 validator 적용\n */\n private applyValidator<U>(\n value: string,\n schema: EnvVarSchema<U>\n ): U\n {\n if (schema.validator)\n {\n return schema.validator(value) as U;\n }\n\n return value as U;\n }\n\n /**\n * 스키마 검증 수행 (값 읽기 없이)\n *\n * @internal\n */\n private validateSchemas(): void\n {\n // Skip if already validated\n if (this.hasValidated)\n {\n return;\n }\n\n const warnings: string[] = [];\n\n // 클라이언트 변수 중 민감정보 경고\n for (const [key, schema] of this.schemas)\n {\n if (isClientAccessible(key) && schema.sensitive)\n {\n warnings.push(\n `${key} is marked as sensitive but accessible from client (NEXT_PUBLIC_*). Remove NEXT_PUBLIC_ prefix or unmark as sensitive.`\n );\n }\n }\n\n // Log warnings\n if (warnings.length > 0)\n {\n envLogger.warn('Environment validation warnings:');\n warnings.forEach(w => envLogger.warn(` - ${w}`));\n }\n\n this.hasValidated = true;\n }\n\n /**\n * 실제 접근 시점에 환경변수 값 가져오기 및 검증\n *\n * @internal\n */\n private getAndValidate(key: string): any\n {\n // Check cache first\n if (this.valueCache.has(key))\n {\n return this.valueCache.get(key);\n }\n\n const schema = this.schemas.get(key);\n if (!schema)\n {\n return undefined;\n }\n\n // Get raw value using common helper\n const value = this.getRawValue(key, schema.fallbackKeys);\n\n // Check if required\n if (schema.required && !value)\n {\n const fallbackHint = schema.fallbackKeys\n ? ` (or ${schema.fallbackKeys.join(', ')})`\n : '';\n\n const errorMsg = `${key}${fallbackHint} is required but not set. ${schema.description || ''}`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n\n // If no value and not required, use default\n if (!value)\n {\n const result = schema.default;\n this.valueCache.set(key, result);\n return result;\n }\n\n // Check minLength\n if (schema.minLength !== undefined && value.length < schema.minLength)\n {\n const errorMsg = `${key} must be at least ${schema.minLength} characters long (current: ${value.length})`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n\n // Apply validator and cache result\n try\n {\n const result = this.applyValidator(value, schema);\n this.valueCache.set(key, result);\n return result;\n }\n catch (error)\n {\n const errorMsg = `${key} validation failed: ${error instanceof Error ? error.message : String(error)}`;\n envLogger.error(`Environment validation failed:\\n - ${errorMsg}`);\n throw new Error('Environment validation failed');\n }\n }\n\n /**\n * 환경변수 검증 및 타입 안전한 env 객체 반환\n *\n * Proxy 기반으로 구현되어 실제 환경변수 접근 시점에 값을 읽고 검증합니다.\n * 이를 통해 dotenv 로딩 타이밍과 무관하게 최신 환경변수 값을 가져올 수 있습니다.\n *\n * @returns 검증된 환경변수 객체 (Proxy)\n * @throws {Error} 필수 변수 누락 또는 검증 실패 시\n *\n * @example\n * ```typescript\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate(); // 스키마만 검증\n * // ... dotenv 로딩 ...\n * console.log(env.DATABASE_URL); // 이 시점에 실제 값 읽기\n * ```\n */\n validate(): InferEnvType<T>\n {\n // Perform schema-level validation (without reading values)\n this.validateSchemas();\n\n // Return Proxy that lazily reads and validates on access\n return new Proxy({} as InferEnvType<T>, {\n get: (_target, prop: string) =>\n {\n return this.getAndValidate(prop);\n },\n\n ownKeys: () =>\n {\n return Array.from(this.schemas.keys());\n },\n\n getOwnPropertyDescriptor: (_target, prop: string) =>\n {\n if (this.schemas.has(prop))\n {\n return {\n enumerable: true,\n configurable: true,\n get: () => this.getAndValidate(prop)\n };\n }\n\n return undefined;\n },\n\n has: (_target, prop: string) =>\n {\n return this.schemas.has(prop);\n }\n });\n }\n}\n\n/**\n * 레지스트리 생성 헬퍼\n *\n * @example\n * ```typescript\n * const schema = defineEnvSchema({\n * DATABASE_URL: envString({ description: 'Database URL', required: true })\n * });\n *\n * const registry = createEnvRegistry(schema);\n * const env = registry.validate();\n * ```\n */\nexport function createEnvRegistry<T extends EnvSchemaCollection>(\n schemas: T\n): EnvRegistry<T>\n{\n return new EnvRegistry(schemas);\n}"]}
|