@spfn/core 0.1.0-alpha.83 → 0.1.0-alpha.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen/index.d.ts +5 -0
- package/dist/codegen/index.js +15 -11
- package/dist/codegen/index.js.map +1 -1
- package/dist/events/index.d.ts +183 -0
- package/dist/events/index.js +77 -0
- package/dist/events/index.js.map +1 -0
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/server/index.js +14 -2
- package/dist/server/index.js.map +1 -1
- package/package.json +6 -1
package/dist/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/logger/index.ts","../src/route/function-routes.ts","../src/errors/database-errors.ts","../src/errors/http-errors.ts","../src/errors/error-utils.ts","../src/errors/index.ts","../src/env/config.ts","../src/env/loader.ts","../src/env/validator.ts","../src/env/index.ts","../src/db/postgres-errors.ts","../src/db/manager/connection.ts","../src/db/manager/config.ts","../src/db/manager/factory.ts","../src/db/manager/global-state.ts","../src/db/manager/health-check.ts","../src/db/manager/manager.ts","../src/db/manager/index.ts","../src/db/manager/config-generator.ts","../src/db/schema/helpers.ts","../src/db/schema/index.ts","../src/db/schema-helper.ts","../src/db/transaction/context.ts","../src/db/transaction/middleware.ts","../src/db/transaction/index.ts","../src/db/helpers.ts","../src/db/index.ts","../src/cache/cache-factory.ts","../src/cache/cache-manager.ts","../src/cache/index.ts","../src/route/auto-loader.ts","../src/route/bind.ts","../src/middleware/error-handler.ts","../src/middleware/request-logger.ts","../src/route/types.ts","../src/server/create-server.ts","../src/server/helpers.ts","../src/server/start-server.ts","../src/server/banner.ts","../src/server/validation.ts"],"names":["timestamp","newPath","existsSync","mkdirSync","join","unlinkSync","init_logger","init_config","dotenvConfig","dbLogger","init_factory","getDatabase","closeDatabase","init_manager","readdirSync","stat","statSync","dirname","readFileSync","packageSchemas","schema","txLogger","init_helpers","cacheLogger","routeLogger","count","discoverFunctionRoutes","maskSensitiveData","getRedis","Hono","serverLogger"],"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 const valueStr = typeof value === 'string' ? value : String(value);\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Slack 메시지 포맷\n */\nexport function formatSlack(metadata: LogMetadata): string\n{\n const emoji = {\n debug: ':bug:',\n info: ':information_source:',\n warn: ':warning:',\n error: ':x:',\n fatal: ':fire:',\n };\n\n const parts: string[] = [];\n\n parts.push(`${emoji[metadata.level]} *${metadata.level.toUpperCase()}*`);\n\n if (metadata.module)\n {\n parts.push(`\\`[${metadata.module}]\\``);\n }\n\n parts.push(metadata.message);\n\n let message = parts.join(' ');\n\n if (metadata.context)\n {\n message += '\\n```\\n' + JSON.stringify(metadata.context, null, 2) + '\\n```';\n }\n\n if (metadata.error)\n {\n message += '\\n```\\n' + formatError(metadata.error) + '\\n```';\n }\n\n return message;\n}\n\n/**\n * Email 제목 생성\n */\nexport function formatEmailSubject(metadata: LogMetadata): string\n{\n const prefix = `[${metadata.level.toUpperCase()}]`;\n const module = metadata.module ? `[${metadata.module}]` : '';\n\n return `${prefix}${module} ${metadata.message}`;\n}\n\n/**\n * Email 본문 생성 (HTML)\n */\nexport function formatEmailBody(metadata: LogMetadata): string\n{\n const parts: string[] = [];\n\n parts.push('<html>');\n parts.push('<body style=\"font-family: monospace; padding: 20px;\">');\n\n // 헤더\n parts.push(`<h2 style=\"color: ${getEmailColor(metadata.level)};\">`);\n parts.push(`${metadata.level.toUpperCase()}`);\n parts.push('</h2>');\n\n // 시간\n parts.push('<p>');\n parts.push(`<strong>Timestamp:</strong> ${formatTimestamp(metadata.timestamp)}`);\n parts.push('</p>');\n\n // 모듈\n if (metadata.module)\n {\n parts.push('<p>');\n parts.push(`<strong>Module:</strong> ${metadata.module}`);\n parts.push('</p>');\n }\n\n // 메시지\n parts.push('<p>');\n parts.push(`<strong>Message:</strong> ${metadata.message}`);\n parts.push('</p>');\n\n // Context\n if (metadata.context)\n {\n parts.push('<h3>Context</h3>');\n parts.push('<pre style=\"background: #f4f4f4; padding: 10px; border-radius: 4px;\">');\n parts.push(JSON.stringify(metadata.context, null, 2));\n parts.push('</pre>');\n }\n\n // 에러\n if (metadata.error)\n {\n parts.push('<h3>Error Stack Trace</h3>');\n parts.push('<pre style=\"background: #fff0f0; padding: 10px; border-radius: 4px;\">');\n parts.push(formatError(metadata.error));\n parts.push('</pre>');\n }\n\n parts.push('</body>');\n parts.push('</html>');\n\n return parts.join('\\n');\n}\n\n/**\n * Email 레벨별 컬러\n */\nfunction getEmailColor(level: LogLevel): string\n{\n const colors: Record<LogLevel, string> = {\n debug: '#00BCD4',\n info: '#4CAF50',\n warn: '#FF9800',\n error: '#F44336',\n fatal: '#9C27B0',\n };\n\n return colors[level];\n}","/**\n * Logger Class\n *\n * Central logging class with multiple transports, child loggers, and sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata, LoggerConfig, Transport } from './types';\nimport { LOG_LEVEL_PRIORITY } from './types';\nimport { maskSensitiveData } from './formatters';\n\n/**\n * Logger class\n */\nexport class Logger\n{\n private readonly config: LoggerConfig;\n private readonly module?: string;\n\n constructor(config: LoggerConfig)\n {\n this.config = config;\n this.module = config.module;\n }\n\n /**\n * Get current log level\n */\n get level(): LogLevel\n {\n return this.config.level;\n }\n\n /**\n * Create child logger (per module)\n */\n child(module: string): Logger\n {\n return new Logger({\n ...this.config,\n module,\n });\n }\n\n /**\n * Debug log\n */\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.log('debug', message, undefined, context);\n }\n\n /**\n * Info log\n */\n info(message: string, context?: Record<string, unknown>): void\n {\n this.log('info', message, undefined, context);\n }\n\n /**\n * Warn log\n */\n warn(message: string, context?: Record<string, unknown>): void;\n warn(message: string, error: Error, context?: Record<string, unknown>): void;\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('warn', message, errorOrContext, context);\n }\n else\n {\n this.log('warn', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Error log\n */\n error(message: string, context?: Record<string, unknown>): void;\n error(message: string, error: Error, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('error', message, errorOrContext, context);\n }\n else\n {\n this.log('error', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Fatal log\n */\n fatal(message: string, context?: Record<string, unknown>): void;\n fatal(message: string, error: Error, context?: Record<string, unknown>): void;\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('fatal', message, errorOrContext, context);\n }\n else\n {\n this.log('fatal', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Log processing (internal)\n */\n private log(level: LogLevel, message: string, error?: Error, context?: Record<string, unknown>): void\n {\n // Early return if log level is below configured level\n // This prevents unnecessary metadata creation and processing\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level])\n {\n return;\n }\n\n const metadata: LogMetadata = {\n timestamp: new Date(),\n level,\n message,\n module: this.module,\n error,\n // Mask sensitive information in context to prevent credential leaks\n context: context ? maskSensitiveData(context) as Record<string, unknown> : undefined,\n };\n\n // Pass to all enabled Transports\n this.processTransports(metadata);\n }\n\n /**\n * Process Transports\n */\n private processTransports(metadata: LogMetadata): void\n {\n const promises = this.config.transports\n .filter(transport => transport.enabled)\n .map(transport => this.safeTransportLog(transport, metadata));\n\n // Async processing to prevent Transport errors from blocking logs\n Promise.all(promises).catch(error =>\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport error: ${errorMessage}\\n`);\n });\n }\n\n /**\n * Transport log (error-safe)\n */\n private async safeTransportLog(transport: Transport, metadata: LogMetadata): Promise<void>\n {\n try\n {\n await transport.log(metadata);\n }\n catch (error)\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport \"${transport.name}\" failed: ${errorMessage}\\n`);\n }\n }\n\n /**\n * Close all Transports\n */\n async close(): Promise<void>\n {\n const closePromises = this.config.transports\n .filter(transport => transport.close)\n .map(transport => transport.close!());\n\n await Promise.all(closePromises);\n }\n}","/**\n * Console Transport\n *\n * 콘솔 출력 Transport\n *\n * ✅ 구현 완료:\n * - 콘솔 출력 (stdout/stderr)\n * - 컬러 출력 지원\n * - 로그 레벨별 스트림 분리 (warn/error/fatal → stderr)\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (Transport 인터페이스)\n * - src/logger/formatters.ts (포맷터)\n * - src/logger/config.ts (설정)\n */\n\nimport type { Transport, LogMetadata, LogLevel, ConsoleTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatConsole } from '../formatters';\n\n/**\n * Console Transport\n */\nexport class ConsoleTransport implements Transport\n{\n public readonly name = 'console';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private colorize: boolean;\n\n constructor(config: ConsoleTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.colorize = config.colorize ?? true;\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // 포맷팅\n const message = formatConsole(metadata, this.colorize);\n\n // warn/error/fatal은 stderr로, 나머지는 stdout으로\n if (metadata.level === 'warn' || metadata.level === 'error' || metadata.level === 'fatal')\n {\n console.error(message);\n }\n else\n {\n console.log(message);\n }\n }\n}","/**\n * File Transport\n *\n * File output transport with date and size-based rotation, automatic cleanup.\n */\n\nimport { createWriteStream, existsSync, mkdirSync, statSync, readdirSync, unlinkSync, renameSync } from 'fs';\nimport type { WriteStream } from 'fs';\nimport { join } from 'path';\nimport type { Transport, LogMetadata, LogLevel, FileTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatJSON } from '../formatters';\n\n/**\n * File Transport\n */\nexport class FileTransport implements Transport\n{\n public readonly name = 'file';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private readonly logDir: string;\n private readonly maxFileSize: number;\n private readonly maxFiles: number;\n private currentStream: WriteStream | null = null;\n private currentFilename: string | null = null;\n\n constructor(config: FileTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.logDir = config.logDir;\n this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024; // 10MB\n this.maxFiles = config.maxFiles ?? 10;\n\n // 로그 디렉토리가 없으면 생성\n if (!existsSync(this.logDir))\n {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // JSON 포맷으로 변환\n const message = formatJSON(metadata);\n\n // 파일명: YYYY-MM-DD.log\n const filename = this.getLogFilename(metadata.timestamp);\n\n // 날짜가 변경되면 스트림 교체\n if (this.currentFilename !== filename)\n {\n await this.rotateStream(filename);\n await this.cleanOldFiles(); // 오래된 파일 정리\n }\n // 파일 크기 체크 및 로테이션\n else if (this.currentFilename)\n {\n await this.checkAndRotateBySize();\n }\n\n // 스트림에 쓰기\n if (this.currentStream)\n {\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.write(message + '\\n', 'utf-8', (error: Error | null | undefined) =>\n {\n if (error)\n {\n // 파일 쓰기 실패 시 stderr로 출력 (fallback)\n process.stderr.write(`[FileTransport] Failed to write log: ${error.message}\\n`);\n reject(error);\n }\n else\n {\n resolve();\n }\n });\n });\n }\n }\n\n /**\n * 스트림 교체 (날짜 변경 시)\n */\n private async rotateStream(filename: string): Promise<void>\n {\n // 기존 스트림 닫기\n if (this.currentStream)\n {\n await this.closeStream();\n }\n\n // 새 스트림 생성\n const filepath = join(this.logDir, filename);\n\n this.currentStream = createWriteStream(filepath, {\n flags: 'a', // append mode\n encoding: 'utf-8',\n });\n\n this.currentFilename = filename;\n\n // 스트림 에러 핸들링\n this.currentStream.on('error', (error) =>\n {\n process.stderr.write(`[FileTransport] Stream error: ${error.message}\\n`);\n // 에러 발생 시 스트림 초기화\n this.currentStream = null;\n this.currentFilename = null;\n });\n }\n\n /**\n * 현재 스트림 닫기\n */\n private async closeStream(): Promise<void>\n {\n if (!this.currentStream)\n {\n return;\n }\n\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.end((error: Error | null | undefined) =>\n {\n if (error)\n {\n reject(error);\n }\n else\n {\n this.currentStream = null;\n this.currentFilename = null;\n resolve();\n }\n });\n });\n }\n\n /**\n * 파일 크기 체크 및 크기 기반 로테이션\n */\n private async checkAndRotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n const filepath = join(this.logDir, this.currentFilename);\n\n // 파일이 존재하지 않으면 스킵\n if (!existsSync(filepath))\n {\n return;\n }\n\n try\n {\n const stats = statSync(filepath);\n\n // 파일 크기가 maxFileSize를 초과하면 로테이션\n if (stats.size >= this.maxFileSize)\n {\n await this.rotateBySize();\n }\n }\n catch (error)\n {\n // 파일 stat 실패 시 무시\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 크기 기반 로테이션 수행\n * 예: 2025-01-01.log -> 2025-01-01.1.log, 2025-01-01.1.log -> 2025-01-01.2.log\n */\n private async rotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n // 기존 스트림 닫기\n await this.closeStream();\n\n const baseName = this.currentFilename.replace(/\\.log$/, '');\n const files = readdirSync(this.logDir);\n\n // 현재 날짜의 로그 파일들 찾기 (예: 2025-01-01.log, 2025-01-01.1.log, ...)\n const relatedFiles = files\n .filter(file => file.startsWith(baseName) && file.endsWith('.log'))\n .sort()\n .reverse(); // 역순 정렬로 높은 번호부터 처리\n\n // 기존 파일들을 번호 증가시켜 이동 (예: .1.log -> .2.log)\n for (const file of relatedFiles)\n {\n const match = file.match(/\\.(\\d+)\\.log$/);\n if (match)\n {\n const oldNum = parseInt(match[1], 10);\n const newNum = oldNum + 1;\n const oldPath = join(this.logDir, file);\n const newPath = join(this.logDir, `${baseName}.${newNum}.log`);\n\n try\n {\n renameSync(oldPath, newPath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}\\n`);\n }\n }\n }\n\n // 현재 파일을 .1.log로 이동\n const currentPath = join(this.logDir, this.currentFilename);\n const newPath = join(this.logDir, `${baseName}.1.log`);\n\n try\n {\n if (existsSync(currentPath))\n {\n renameSync(currentPath, newPath);\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}\\n`);\n }\n\n // 새 스트림 생성 (동일한 파일명으로)\n await this.rotateStream(this.currentFilename);\n }\n\n /**\n * 오래된 로그 파일 정리\n * maxFiles 개수를 초과하는 로그 파일 삭제\n */\n private async cleanOldFiles(): Promise<void>\n {\n try\n {\n // 디렉토리가 존재하지 않으면 스킵\n if (!existsSync(this.logDir))\n {\n return;\n }\n\n const files = readdirSync(this.logDir);\n\n // .log로 끝나는 파일만 필터링 후 수정 시간 기준 정렬\n const logFiles = files\n .filter(file => file.endsWith('.log'))\n .map(file =>\n {\n const filepath = join(this.logDir, file);\n const stats = statSync(filepath);\n return { file, mtime: stats.mtime };\n })\n .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); // 최신 파일이 앞으로\n\n // maxFiles를 초과하는 오래된 파일들 삭제\n if (logFiles.length > this.maxFiles)\n {\n const filesToDelete = logFiles.slice(this.maxFiles);\n\n for (const { file } of filesToDelete)\n {\n const filepath = join(this.logDir, file);\n try\n {\n unlinkSync(filepath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to delete old file \"${file}\": ${errorMessage}\\n`);\n }\n }\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 날짜별 로그 파일명 생성\n */\n private getLogFilename(date: Date): string\n {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}.log`;\n }\n\n async close(): Promise<void>\n {\n // 스트림 정리\n await this.closeStream();\n }\n}","/**\n * Logger Configuration\n *\n * Environment-based logger configuration with validation for console, file, Slack, and Email transports.\n */\n\nimport { existsSync, accessSync, constants, mkdirSync, writeFileSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type {\n LogLevel,\n ConsoleTransportConfig,\n FileTransportConfig,\n SlackTransportConfig,\n EmailTransportConfig,\n} from './types';\n\n/**\n * Check if file logging is enabled (for self-hosted)\n */\nexport function isFileLoggingEnabled(): boolean\n{\n return process.env.LOGGER_FILE_ENABLED === 'true';\n}\n\n/**\n * Get default log level by environment\n */\nexport function getDefaultLogLevel(): LogLevel\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment)\n {\n return 'debug';\n }\n\n if (isProduction)\n {\n return 'info';\n }\n\n // Test environment\n return 'warn';\n}\n\n/**\n * Console Transport configuration\n */\nexport function getConsoleConfig(): ConsoleTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'debug',\n enabled: true,\n colorize: !isProduction, // Dev: colored output, Production: plain text\n };\n}\n\n/**\n * File Transport configuration\n */\nexport function getFileConfig(): FileTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'info',\n enabled: isProduction, // File logging in production only\n logDir: process.env.LOG_DIR || './logs',\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n };\n}\n\n/**\n * Slack Transport configuration\n */\nexport function getSlackConfig(): SlackTransportConfig | null\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return null; // Disabled if not configured\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'error', // Send error and above to Slack\n enabled: isProduction, // Enabled in production only\n webhookUrl,\n channel: process.env.SLACK_CHANNEL,\n username: process.env.SLACK_USERNAME || 'Logger Bot',\n };\n}\n\n/**\n * Email Transport configuration\n */\nexport function getEmailConfig(): EmailTransportConfig | null\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // Disabled if required settings are missing\n if (!smtpHost || !smtpPort || !emailFrom || !emailTo)\n {\n return null;\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'fatal', // Send fatal level only via email\n enabled: isProduction, // Enabled in production only\n from: emailFrom,\n to: emailTo.split(',').map(email => email.trim()),\n smtpHost,\n smtpPort: parseInt(smtpPort, 10),\n smtpUser: process.env.SMTP_USER,\n smtpPassword: process.env.SMTP_PASSWORD,\n };\n}\n\n/**\n * Validate directory path and write permissions\n */\nfunction validateDirectoryWritable(dirPath: string): void\n{\n // Check if directory exists\n if (!existsSync(dirPath))\n {\n // Try to create directory\n try\n {\n mkdirSync(dirPath, { recursive: true });\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to create log directory \"${dirPath}\": ${errorMessage}`);\n }\n }\n\n // Check write permission\n try\n {\n accessSync(dirPath, constants.W_OK);\n }\n catch\n {\n throw new Error(`Log directory \"${dirPath}\" is not writable. Please check permissions.`);\n }\n\n // Try to write a test file\n const testFile = join(dirPath, '.logger-write-test');\n try\n {\n writeFileSync(testFile, 'test', 'utf-8');\n unlinkSync(testFile);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Cannot write to log directory \"${dirPath}\": ${errorMessage}`);\n }\n}\n\n/**\n * Validate file transport configuration\n */\nfunction validateFileConfig(): void\n{\n if (!isFileLoggingEnabled())\n {\n return; // File logging disabled, skip validation\n }\n\n const logDir = process.env.LOG_DIR;\n\n // Check if LOG_DIR is set\n if (!logDir)\n {\n throw new Error(\n 'LOG_DIR environment variable is required when LOGGER_FILE_ENABLED=true. ' +\n 'Example: LOG_DIR=/var/log/myapp'\n );\n }\n\n // Validate directory\n validateDirectoryWritable(logDir);\n}\n\n/**\n * Validate Slack transport configuration\n */\nfunction validateSlackConfig(): void\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return; // Slack disabled, skip validation\n }\n\n // Validate webhook URL format\n if (!webhookUrl.startsWith('https://hooks.slack.com/'))\n {\n throw new Error(\n `Invalid SLACK_WEBHOOK_URL: \"${webhookUrl}\". ` +\n 'Slack webhook URLs must start with \"https://hooks.slack.com/\"'\n );\n }\n}\n\n/**\n * Validate Email transport configuration\n */\nfunction validateEmailConfig(): void\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // If any email config is set, all required fields must be present\n const hasAnyEmailConfig = smtpHost || smtpPort || emailFrom || emailTo;\n if (!hasAnyEmailConfig)\n {\n return; // Email disabled, skip validation\n }\n\n // Validate all required fields\n const missingFields: string[] = [];\n if (!smtpHost) missingFields.push('SMTP_HOST');\n if (!smtpPort) missingFields.push('SMTP_PORT');\n if (!emailFrom) missingFields.push('EMAIL_FROM');\n if (!emailTo) missingFields.push('EMAIL_TO');\n\n if (missingFields.length > 0)\n {\n throw new Error(\n `Email transport configuration incomplete. Missing: ${missingFields.join(', ')}. ` +\n 'Either set all required fields or remove all email configuration.'\n );\n }\n\n // Validate SMTP port is a number\n const port = parseInt(smtpPort!, 10);\n if (isNaN(port) || port < 1 || port > 65535)\n {\n throw new Error(\n `Invalid SMTP_PORT: \"${smtpPort}\". Must be a number between 1 and 65535.`\n );\n }\n\n // Validate email format (basic check)\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(emailFrom!))\n {\n throw new Error(`Invalid EMAIL_FROM format: \"${emailFrom}\"`);\n }\n\n // Validate email recipients\n const recipients = emailTo!.split(',').map(e => e.trim());\n for (const email of recipients)\n {\n if (!emailRegex.test(email))\n {\n throw new Error(`Invalid email address in EMAIL_TO: \"${email}\"`);\n }\n }\n}\n\n/**\n * Validate environment variables\n */\nfunction validateEnvironment(): void\n{\n const nodeEnv = process.env.NODE_ENV;\n\n if (!nodeEnv)\n {\n process.stderr.write(\n '[Logger] Warning: NODE_ENV is not set. Defaulting to test environment.\\n'\n );\n }\n // Allow any NODE_ENV value (development, production, test, staging, local, etc.)\n // No validation needed - users can use custom environments\n}\n\n/**\n * Validate all logger configuration\n * Throws an error if configuration is invalid\n */\nexport function validateConfig(): void\n{\n try\n {\n validateEnvironment();\n validateFileConfig();\n validateSlackConfig();\n validateEmailConfig();\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n throw new Error(`[Logger] Configuration validation failed: ${error.message}`);\n }\n throw error;\n }\n}","/**\n * 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 * Logger Module Exports\n *\n * Entry point for logger module\n *\n * 💡 Usage examples:\n * ```typescript\n * import { logger } from '@spfn/core';\n *\n * // Basic usage\n * logger.info('Application started');\n * logger.error('Connection failed', error);\n *\n * // Create module-specific logger\n * const dbLogger = logger.child('database');\n * dbLogger.debug('Connecting to database...');\n *\n * // Add context\n * logger.warn('Retry attempt', { attempt: 3, delay: 1000 });\n * ```\n *\n * 💡 Transports:\n * - Console: Colored output for development, JSON for production\n * - File: Automatic file logging in production (LOG_FILE_ENABLED=true)\n * - Future: Slack, Email, and custom transports\n */\n\n// Logger Instance\nexport { logger } from './factory.js';\nexport { Logger } from './logger.js';\n\n// Types\nexport type { LogLevel, Transport } from './types.js';\n","/**\n * Function Route Discovery\n *\n * Automatically discovers and loads routes from SPFN functions\n *\n * NOTE: Contract-based routing - routes use absolute paths defined in contracts\n * No basePath needed - each contract defines its own absolute path (e.g., '/cms/labels')\n */\n\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { logger } from '../logger';\n\nconst routeLogger = logger.child('function-routes');\n\nexport type FunctionRouteInfo = {\n packageName: string;\n routesDir: string;\n packagePath: string;\n prefix?: string; // From package.json spfn.prefix\n};\n\n/**\n * Discover SPFN functions with route declarations\n *\n * Scans node_modules for packages that declare routes in package.json\n *\n * Example package.json:\n * ```json\n * {\n * \"name\": \"@spfn/cms\",\n * \"spfn\": {\n * \"routes\": {\n * \"dir\": \"./dist/routes\"\n * }\n * }\n * }\n * ```\n */\nexport function discoverFunctionRoutes(cwd: string = process.cwd()): FunctionRouteInfo[]\n{\n const functions: FunctionRouteInfo[] = [];\n const nodeModulesPath = join(cwd, 'node_modules');\n\n try\n {\n // Read package.json to get dependencies\n const projectPkgPath = join(cwd, 'package.json');\n const projectPkg = JSON.parse(readFileSync(projectPkgPath, 'utf-8'));\n\n const dependencies = {\n ...projectPkg.dependencies,\n ...projectPkg.devDependencies,\n };\n\n // Scan each dependency for spfn.routes\n for (const [packageName] of Object.entries(dependencies))\n {\n // Only scan @spfn/* and packages starting with spfn-\n if (!packageName.startsWith('@spfn/') && !packageName.startsWith('spfn-'))\n {\n continue;\n }\n\n try\n {\n const pkgPath = join(nodeModulesPath, ...packageName.split('/'), 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n\n if (pkg.spfn?.routes?.dir)\n {\n const { dir } = pkg.spfn.routes;\n const prefix = pkg.spfn.prefix; // Read prefix from package.json\n const packagePath = dirname(pkgPath);\n const routesDir = join(packagePath, dir);\n\n functions.push({\n packageName,\n routesDir,\n packagePath,\n prefix, // Include prefix in function info\n });\n\n routeLogger.debug('Discovered function routes', {\n package: packageName,\n dir,\n prefix: prefix || '(none)',\n });\n }\n }\n catch (error)\n {\n // Silently skip packages that don't exist or can't be read\n // This is normal for optional dependencies or workspace links\n }\n }\n }\n catch (error)\n {\n routeLogger.warn('Failed to discover function routes', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n\n return functions;\n}","/**\n * Database Error Classes\n *\n * Type-safe error handling with custom error class hierarchy\n * Mapped to HTTP status codes for API responses\n */\n\n/**\n * Base Database Error\n *\n * Base class for all database-related errors\n */\nexport class DatabaseError<TDetails extends Record<string, unknown> = Record<string, unknown>> extends Error\n{\n public readonly statusCode: number;\n public readonly details?: TDetails;\n public readonly timestamp: Date;\n\n constructor(\n message: string,\n statusCode: number = 500,\n details?: TDetails\n )\n {\n super(message);\n this.name = 'DatabaseError';\n this.statusCode = statusCode;\n this.details = details;\n this.timestamp = new Date();\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * Serialize error for API response\n */\n toJSON()\n {\n return {\n name: this.name,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n timestamp: this.timestamp.toISOString()\n };\n }\n}\n\n/**\n * Connection Error (503 Service Unavailable)\n *\n * Database connection failure, connection pool exhaustion, etc.\n */\nexport class ConnectionError extends DatabaseError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 503, details);\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Query Error (500 Internal Server Error)\n *\n * SQL query execution failure, syntax errors, etc.\n */\nexport class QueryError extends DatabaseError\n{\n constructor(message: string, statusCode: number = 500, details?: Record<string, any>)\n {\n super(message, statusCode, details);\n this.name = 'QueryError';\n }\n}\n\n/**\n * Entity Not Found Error (404 Not Found)\n *\n * Database entity does not exist\n */\nexport class EntityNotFoundError extends QueryError\n{\n constructor(resource: string, id: string | number)\n {\n super(`${resource} with id ${id} not found`, 404, { resource, id });\n this.name = 'EntityNotFoundError';\n }\n}\n\n/**\n * Constraint Violation Error (400 Bad Request)\n *\n * Database constraint violation (NOT NULL, CHECK, FOREIGN KEY, etc.)\n * This is different from HTTP ValidationError which validates request input\n */\nexport class ConstraintViolationError extends QueryError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'ConstraintViolationError';\n }\n}\n\n/**\n * Transaction Error (500 Internal Server Error)\n *\n * Transaction start/commit/rollback failure\n */\nexport class TransactionError extends DatabaseError\n{\n constructor(message: string, statusCode: number = 500, details?: Record<string, any>)\n {\n super(message, statusCode, details);\n this.name = 'TransactionError';\n }\n}\n\n/**\n * Deadlock Error (409 Conflict)\n *\n * Database deadlock detected\n */\nexport class DeadlockError extends TransactionError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 409, details);\n this.name = 'DeadlockError';\n }\n}\n\n/**\n * Duplicate Entry Error (409 Conflict)\n *\n * Unique constraint violation (e.g., duplicate email)\n */\nexport class DuplicateEntryError extends QueryError\n{\n constructor(field: string, value: string | number)\n {\n super(`${field} '${value}' already exists`, 409, { field, value });\n this.name = 'DuplicateEntryError';\n }\n}","/**\n * HTTP Error Classes\n *\n * Standard HTTP error classes for API responses\n * Covers common HTTP status codes beyond database errors\n */\n\n/**\n * Base HTTP Error\n *\n * Base class for all HTTP-related errors\n */\nexport class HttpError<TDetails extends Record<string, unknown> = Record<string, unknown>> extends Error\n{\n public readonly statusCode: number;\n public readonly details?: TDetails;\n public readonly timestamp: Date;\n\n constructor(\n message: string,\n statusCode: number,\n details?: TDetails\n )\n {\n super(message);\n this.name = 'HttpError';\n this.statusCode = statusCode;\n this.details = details;\n this.timestamp = new Date();\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * Serialize error for API response\n */\n toJSON()\n {\n return {\n name: this.name,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n timestamp: this.timestamp.toISOString()\n };\n }\n}\n\n/**\n * Bad Request Error (400)\n *\n * Generic bad request - malformed syntax, invalid parameters, etc.\n */\nexport class BadRequestError extends HttpError\n{\n constructor(message: string = 'Bad request', details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'BadRequestError';\n }\n}\n\n/**\n * Validation Error (400)\n *\n * Input validation failure (request params, query, body)\n * Used by contract-based routing for automatic validation\n */\nexport class ValidationError extends HttpError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Unauthorized Error (401)\n *\n * Authentication required or authentication failed\n */\nexport class UnauthorizedError extends HttpError\n{\n constructor(message: string = 'Authentication required', details?: Record<string, any>)\n {\n super(message, 401, details);\n this.name = 'UnauthorizedError';\n }\n}\n\n/**\n * Forbidden Error (403)\n *\n * Authenticated but lacks permission to access resource\n */\nexport class ForbiddenError extends HttpError\n{\n constructor(message: string = 'Access forbidden', details?: Record<string, any>)\n {\n super(message, 403, details);\n this.name = 'ForbiddenError';\n }\n}\n\n/**\n * Not Found Error (404)\n *\n * Requested resource does not exist\n * Generic HTTP 404 error (for database-specific NotFoundError, see database-errors.ts)\n */\nexport class NotFoundError extends HttpError\n{\n constructor(message: string = 'Resource not found', details?: Record<string, any>)\n {\n super(message, 404, details);\n this.name = 'NotFoundError';\n }\n}\n\n/**\n * Conflict Error (409)\n *\n * Generic conflict - resource state conflict, concurrent modification, etc.\n * More general than DuplicateEntryError\n */\nexport class ConflictError extends HttpError\n{\n constructor(message: string = 'Resource conflict', details?: Record<string, any>)\n {\n super(message, 409, details);\n this.name = 'ConflictError';\n }\n}\n\n/**\n * Too Many Requests Error (429)\n *\n * Rate limit exceeded\n */\nexport class TooManyRequestsError extends HttpError\n{\n constructor(\n message: string = 'Too many requests',\n retryAfter?: number,\n details?: Record<string, any>\n )\n {\n const fullDetails = retryAfter\n ? { ...details, retryAfter }\n : details;\n\n super(message, 429, fullDetails);\n this.name = 'TooManyRequestsError';\n }\n}\n\n/**\n * Internal Server Error (500)\n *\n * Generic server error when no specific error type applies\n */\nexport class InternalServerError extends HttpError\n{\n constructor(message: string = 'Internal server error', details?: Record<string, any>)\n {\n super(message, 500, details);\n this.name = 'InternalServerError';\n }\n}\n\n/**\n * Unprocessable Entity Error (422)\n *\n * Request is well-formed but contains semantic errors\n */\nexport class UnprocessableEntityError extends HttpError\n{\n constructor(message: string = 'Unprocessable entity', details?: Record<string, any>)\n {\n super(message, 422, details);\n this.name = 'UnprocessableEntityError';\n }\n}\n\n/**\n * Service Unavailable Error (503)\n *\n * Service temporarily unavailable (maintenance, overload, etc.)\n */\nexport class ServiceUnavailableError extends HttpError\n{\n constructor(\n message: string = 'Service unavailable',\n retryAfter?: number,\n details?: Record<string, any>\n )\n {\n const fullDetails = retryAfter\n ? { ...details, retryAfter }\n : details;\n\n super(message, 503, fullDetails);\n this.name = 'ServiceUnavailableError';\n }\n}","/**\n * Error Utility Functions\n *\n * Generic error type checking utilities\n */\n\nimport { DatabaseError } from './database-errors.js';\nimport { HttpError } from './http-errors.js';\n\n/**\n * Check if error is a DatabaseError\n */\nexport function isDatabaseError(error: unknown): error is DatabaseError\n{\n return error instanceof DatabaseError;\n}\n\n/**\n * Check if error is an HttpError\n */\nexport function isHttpError(error: unknown): error is HttpError\n{\n return error instanceof HttpError;\n}\n\n/**\n * Check if error has a statusCode property\n */\nexport function hasStatusCode(error: unknown): error is { statusCode: number }\n{\n return (\n typeof error === 'object' &&\n error !== null &&\n 'statusCode' in error &&\n typeof (error as any).statusCode === 'number'\n );\n}\n","/**\n * Error Module Exports\n *\n * Entry point for error handling module (Pure re-export only)\n */\n\n// Database Error Classes\nexport {\n DatabaseError,\n ConnectionError,\n QueryError,\n EntityNotFoundError,\n ConstraintViolationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n} from './database-errors.js';\n\n// HTTP Error Classes\nexport {\n HttpError,\n BadRequestError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n TooManyRequestsError,\n UnprocessableEntityError,\n InternalServerError,\n ServiceUnavailableError,\n} from './http-errors.js';\n\n// Error Utilities\nexport {\n isDatabaseError,\n isHttpError,\n hasStatusCode,\n} from './error-utils.js';\n","/**\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}","/**\n * Environment Variable Management\n *\n * Centralized environment variable loading with dotenv priority support\n *\n * @example\n * ```typescript\n * import { loadEnvironment, requireEnvVar } from '@spfn/core/env';\n *\n * // Load environment variables\n * loadEnvironment({\n * debug: true,\n * required: ['DATABASE_URL'],\n * });\n *\n * // Get required variables\n * const dbUrl = requireEnvVar('DATABASE_URL');\n * ```\n *\n * @module env\n */\n\n// Core loader functions\nexport {\n loadEnvironment,\n getEnvVar,\n requireEnvVar,\n hasEnvVar,\n getEnvVars,\n isEnvironmentLoaded,\n resetEnvironment,\n} from './loader.js';\n\n// Type definitions\nexport type {\n LoadEnvironmentOptions,\n LoadResult,\n GetEnvOptions,\n} from './config.js';\n\nexport {\n ENV_FILE_PRIORITY,\n TEST_ONLY_FILES,\n} from './config.js';\n\n// Validation utilities\nexport {\n validateUrl,\n createUrlValidator,\n validateNumber,\n createNumberValidator,\n validateBoolean,\n parseBoolean,\n validateEnum,\n createEnumValidator,\n validatePattern,\n createPatternValidator,\n validateNotEmpty,\n validateMinLength,\n createMinLengthValidator,\n combineValidators,\n validatePostgresUrl,\n validateRedisUrl,\n} from './validator.js';","/**\n * PostgreSQL Error Conversion Utilities\n *\n * Converts PostgreSQL-specific error codes to custom error types\n * @see https://www.postgresql.org/docs/current/errcodes-appendix.html\n */\n\nimport {\n DatabaseError,\n ConnectionError,\n DuplicateEntryError,\n DeadlockError,\n ConstraintViolationError,\n QueryError,\n TransactionError,\n} from '../errors';\n\n/**\n * Extract field and value from PostgreSQL unique violation message\n *\n * Handles various formats:\n * - Simple: Key (email)=(test@example.com)\n * - Complex: Key (user_id, tenant_id)=(123, 456)\n * - With quotes: Key (\"field\")=('value')\n */\nfunction parseUniqueViolation(message: string): { field: string; value: string } | null\n{\n // Try multiple patterns for robustness\n const patterns = [\n // Standard format: Key (field)=(value)\n /Key \\(([^)]+)\\)=\\(([^)]+)\\)/i,\n // With quotes: Key (\"field\")=('value')\n /Key \\([\"']?([^)\"']+)[\"']?\\)=\\([\"']?([^)\"']+)[\"']?\\)/i,\n // Alternative format\n /Key `([^`]+)`=`([^`]+)`/i,\n ];\n\n for (const pattern of patterns)\n {\n const match = message.match(pattern);\n if (match)\n {\n // Clean up extracted values\n const field = match[1].trim().replace(/[\"'`]/g, '');\n const value = match[2].trim().replace(/[\"'`]/g, '');\n return { field, value };\n }\n }\n\n return null;\n}\n\n/**\n * Convert PostgreSQL error to custom DatabaseError\n *\n * Maps PostgreSQL error codes to appropriate error classes with correct status codes\n *\n * @param error - PostgreSQL error object (from pg driver or Drizzle)\n * @returns Custom DatabaseError instance\n *\n * @example\n * ```typescript\n * import { fromPostgresError } from '@spfn/core/db';\n *\n * try {\n * await db.insert(users).values(data);\n * } catch (pgError) {\n * throw fromPostgresError(pgError);\n * }\n * ```\n */\nexport function fromPostgresError(error: any): DatabaseError\n{\n const code = error?.code;\n const message = error?.message || 'Database error occurred';\n\n switch (code)\n {\n // Class 08 — Connection Exception\n case '08000': // connection_exception\n case '08001': // sqlclient_unable_to_establish_sqlconnection\n case '08003': // connection_does_not_exist\n case '08004': // sqlserver_rejected_establishment_of_sqlconnection\n case '08006': // connection_failure\n case '08007': // transaction_resolution_unknown\n case '08P01': // protocol_violation\n return new ConnectionError(message, { code });\n\n // Class 23 — Integrity Constraint Violation\n case '23000': // integrity_constraint_violation\n case '23001': // restrict_violation\n return new ConstraintViolationError(message, { code, constraint: 'integrity' });\n\n case '23502': // not_null_violation\n return new ConstraintViolationError(message, { code, constraint: 'not_null' });\n\n case '23503': // foreign_key_violation\n return new ConstraintViolationError(message, { code, constraint: 'foreign_key' });\n\n case '23505': // unique_violation\n const parsed = parseUniqueViolation(message);\n if (parsed)\n {\n return new DuplicateEntryError(parsed.field, parsed.value);\n }\n return new DuplicateEntryError('field', 'value');\n\n case '23514': // check_violation\n return new ConstraintViolationError(message, { code, constraint: 'check' });\n\n // Class 40 — Transaction Rollback\n case '40000': // transaction_rollback\n case '40001': // serialization_failure\n case '40002': // transaction_integrity_constraint_violation\n case '40003': // statement_completion_unknown\n return new TransactionError(message, 500, { code });\n\n case '40P01': // deadlock_detected\n return new DeadlockError(message, { code });\n\n // Class 42 — Syntax Error or Access Rule Violation\n case '42000': // syntax_error_or_access_rule_violation\n case '42601': // syntax_error\n case '42501': // insufficient_privilege\n case '42602': // invalid_name\n case '42622': // name_too_long\n case '42701': // duplicate_column\n case '42702': // ambiguous_column\n case '42703': // undefined_column\n case '42704': // undefined_object\n case '42P01': // undefined_table\n case '42P02': // undefined_parameter\n return new QueryError(message, 400, { code });\n\n // Class 53 — Insufficient Resources\n case '53000': // insufficient_resources\n case '53100': // disk_full\n case '53200': // out_of_memory\n case '53300': // too_many_connections\n return new ConnectionError(message, { code });\n\n // Class 57 — Operator Intervention\n case '57000': // operator_intervention\n case '57014': // query_canceled\n case '57P01': // admin_shutdown\n case '57P02': // crash_shutdown\n case '57P03': // cannot_connect_now\n return new ConnectionError(message, { code });\n\n // Default: Unknown error\n default:\n return new QueryError(message, 500, { code });\n }\n}","import postgres from 'postgres';\nimport type { Sql } from 'postgres';\n\nimport { logger } from '../../logger';\nimport { ConnectionError } from '../../errors';\nimport { fromPostgresError } from '../postgres-errors';\nimport type { PoolConfig, RetryConfig } from './config';\n\nconst dbLogger = logger.child('database');\n\n/**\n * 지연 함수\n */\nfunction delay(ms: number): Promise<void>\n{\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Exponential Backoff로 DB 연결 생성\n *\n * @param connectionString - PostgreSQL 연결 문자열\n * @param poolConfig - Connection Pool 설정\n * @param retryConfig - 재시도 설정\n * @returns PostgreSQL 클라이언트\n */\nexport async function createDatabaseConnection(\n connectionString: string,\n poolConfig: PoolConfig,\n retryConfig: RetryConfig\n) {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++)\n {\n try\n {\n // PostgreSQL 클라이언트 생성\n const client = postgres(connectionString, {\n max: poolConfig.max,\n idle_timeout: poolConfig.idleTimeout,\n });\n\n // 연결 테스트 쿼리\n await client`SELECT 1 as test`;\n\n // 연결 성공\n if (attempt > 0)\n {\n dbLogger.info(`Database connected successfully after ${attempt} retries`);\n }\n else\n {\n dbLogger.info('Database connected successfully');\n }\n\n return client;\n }\n catch (error)\n {\n lastError = fromPostgresError(error);\n\n // 마지막 시도가 아니면 재시도\n if (attempt < retryConfig.maxRetries)\n {\n // Exponential Backoff 계산\n const delayMs = Math.min(\n retryConfig.initialDelay * Math.pow(retryConfig.factor, attempt),\n retryConfig.maxDelay\n );\n\n dbLogger.warn(\n `Connection failed (attempt ${attempt + 1}/${retryConfig.maxRetries + 1}), retrying in ${delayMs}ms...`,\n lastError,\n {\n attempt: attempt + 1,\n maxRetries: retryConfig.maxRetries + 1,\n delayMs,\n }\n );\n\n await delay(delayMs);\n }\n }\n }\n\n // 모든 재시도 실패\n const errorMessage =\n `Failed to connect to database after ${retryConfig.maxRetries + 1} attempts: ${lastError?.message || 'Unknown error'}`;\n\n throw new ConnectionError(errorMessage);\n}\n\n/**\n * DB 연결 상태 확인\n *\n * @param client - PostgreSQL 클라이언트\n * @returns 연결 가능 여부\n */\nexport async function checkConnection(client: Sql): Promise<boolean>\n{\n try\n {\n await client`SELECT 1 as health_check`;\n return true;\n }\n catch (error)\n {\n dbLogger.error('Database health check failed', error as Error);\n return false;\n }\n}","/**\n * Database Configuration\n *\n * DB 연결 및 Connection Pool 설정\n *\n * ✅ 구현 완료:\n * - 환경별 Connection Pool 설정\n * - 재시도 설정 (Exponential Backoff)\n * - 환경변수 기반 설정\n *\n * 🔗 관련 파일:\n * - src/server/core/db/connection.ts (연결 로직)\n * - src/server/core/db/index.ts (메인 export)\n */\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\";\nimport type { Sql } from \"postgres\";\n\nexport interface DatabaseClients\n{\n /** Primary database for writes (or both read/write if no replica) */\n write?: PostgresJsDatabase;\n /** Replica database for reads (optional, falls back to write) */\n read?: PostgresJsDatabase;\n /** Raw postgres client for write operations (for cleanup) */\n writeClient?: Sql;\n /** Raw postgres client for read operations (for cleanup) */\n readClient?: Sql;\n}\n\n/**\n * Health check configuration\n */\nexport interface HealthCheckConfig\n{\n enabled: boolean;\n interval: number;\n reconnect: boolean;\n maxRetries: number;\n retryInterval: number;\n}\n\n/**\n * Query performance monitoring configuration\n */\nexport interface MonitoringConfig\n{\n enabled: boolean;\n slowThreshold: number;\n logQueries: boolean;\n}\n\n/**\n * Database initialization options\n */\nexport interface DatabaseOptions\n{\n /**\n * Connection pool configuration\n * Overrides environment variables and defaults\n */\n pool?: Partial<PoolConfig>;\n\n /**\n * Health check configuration\n * Periodic checks to ensure database connection is alive\n */\n healthCheck?: Partial<HealthCheckConfig>;\n\n /**\n * Query performance monitoring configuration\n * Tracks slow queries and logs performance metrics\n */\n monitoring?: Partial<MonitoringConfig>;\n}\n\n/**\n * Connection Pool 설정\n */\nexport interface PoolConfig\n{\n max: number; // 최대 연결 수\n idleTimeout: number; // 유휴 연결 타임아웃 (초)\n}\n\n/**\n * 재시도 설정\n */\nexport interface RetryConfig\n{\n maxRetries: number; // 최대 재시도 횟수\n initialDelay: number; // 초기 대기 시간 (ms)\n maxDelay: number; // 최대 대기 시간 (ms)\n factor: number; // 지수 증가 배수\n}\n\n// ============================================================================\n// Environment Variable Parsing Utilities\n// ============================================================================\n\n/**\n * Parse environment variable as number with production/development defaults\n *\n * @param key - Environment variable name\n * @param prodDefault - Default value for production\n * @param devDefault - Default value for development\n * @returns Parsed number or default based on NODE_ENV\n *\n * @example\n * ```typescript\n * const max = parseEnvNumber('DB_POOL_MAX', 20, 10);\n * // Production: 20, Development: 10, or parsed value from env\n * ```\n */\nfunction parseEnvNumber(\n key: string,\n prodDefault: number,\n devDefault: number\n): number\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const envValue = parseInt(process.env[key] || '', 10);\n\n // If parsing fails (NaN), use environment-based default\n return isNaN(envValue)\n ? (isProduction ? prodDefault : devDefault)\n : envValue;\n}\n\n/**\n * Parse environment variable as boolean\n *\n * @param key - Environment variable name\n * @param defaultValue - Default value if not set\n * @returns Boolean value\n *\n * @example\n * ```typescript\n * const enabled = parseEnvBoolean('DB_HEALTH_CHECK_ENABLED', true);\n * // Returns true if env var is 'true', false if 'false', or default\n * ```\n */\nfunction parseEnvBoolean(key: string, defaultValue: boolean): boolean\n{\n const value = process.env[key];\n if (value === undefined) return defaultValue;\n return value.toLowerCase() === 'true';\n}\n\n// ============================================================================\n// Configuration Builders\n// ============================================================================\n\n/**\n * 환경별 Connection Pool 설정\n *\n * 우선순위:\n * 1. options 파라미터 (ServerConfig에서 전달)\n * 2. 환경변수 (DB_POOL_MAX, DB_POOL_IDLE_TIMEOUT)\n * 3. 기본값 (NODE_ENV에 따라)\n *\n * @param options - Optional pool configuration from ServerConfig\n * @returns Pool configuration\n *\n * @example\n * ```typescript\n * // 1. ServerConfig priority (highest)\n * const config = getPoolConfig({ max: 50, idleTimeout: 60 });\n *\n * // 2. Environment variable priority\n * // DB_POOL_MAX=30 DB_POOL_IDLE_TIMEOUT=45\n * const config = getPoolConfig();\n *\n * // 3. Default (lowest)\n * // Production: max=20, idleTimeout=30\n * // Development: max=10, idleTimeout=20\n * ```\n */\nexport function getPoolConfig(options?: Partial<PoolConfig>): PoolConfig\n{\n return {\n max: options?.max ?? parseEnvNumber('DB_POOL_MAX', 20, 10),\n idleTimeout: options?.idleTimeout ?? parseEnvNumber('DB_POOL_IDLE_TIMEOUT', 30, 20),\n };\n}\n\n/**\n * 환경별 재시도 설정\n *\n * 우선순위: 환경변수 > 기본값 (NODE_ENV에 따라)\n *\n * @returns Retry configuration\n *\n * @example\n * ```typescript\n * // Environment variables (highest priority)\n * // DB_RETRY_MAX=10\n * // DB_RETRY_INITIAL_DELAY=200\n * const config = getRetryConfig();\n *\n * // Defaults (lowest priority)\n * // Production: 5 retries, 100ms initial, 10s max, factor 2\n * // Development: 3 retries, 50ms initial, 5s max, factor 2\n * ```\n */\nexport function getRetryConfig(): RetryConfig\n{\n return {\n maxRetries: parseEnvNumber('DB_RETRY_MAX', 5, 3),\n initialDelay: parseEnvNumber('DB_RETRY_INITIAL_DELAY', 100, 50),\n maxDelay: parseEnvNumber('DB_RETRY_MAX_DELAY', 10000, 5000),\n factor: parseEnvNumber('DB_RETRY_FACTOR', 2, 2),\n };\n}\n\n/**\n * Build health check configuration with priority resolution\n *\n * 우선순위: options > env > defaults\n *\n * @param options - Optional health check configuration\n * @returns Health check configuration\n *\n * @example\n * ```typescript\n * // Custom options (highest priority)\n * const config = buildHealthCheckConfig({ enabled: false });\n *\n * // Environment variables\n * // DB_HEALTH_CHECK_ENABLED=true\n * // DB_HEALTH_CHECK_INTERVAL=30000\n * const config = buildHealthCheckConfig();\n *\n * // Defaults (lowest priority)\n * // enabled: true, interval: 60000ms, reconnect: true\n * ```\n */\nexport function buildHealthCheckConfig(options?: Partial<HealthCheckConfig>): HealthCheckConfig\n{\n return {\n enabled: options?.enabled\n ?? parseEnvBoolean('DB_HEALTH_CHECK_ENABLED', true),\n interval: options?.interval\n ?? parseEnvNumber('DB_HEALTH_CHECK_INTERVAL', 60000, 60000),\n reconnect: options?.reconnect\n ?? parseEnvBoolean('DB_HEALTH_CHECK_RECONNECT', true),\n maxRetries: options?.maxRetries\n ?? parseEnvNumber('DB_HEALTH_CHECK_MAX_RETRIES', 3, 3),\n retryInterval: options?.retryInterval\n ?? parseEnvNumber('DB_HEALTH_CHECK_RETRY_INTERVAL', 5000, 5000),\n };\n}\n\n/**\n * Build monitoring configuration with priority resolution\n *\n * 우선순위: options > env > defaults\n *\n * @param options - Optional monitoring configuration\n * @returns Monitoring configuration\n *\n * @example\n * ```typescript\n * // Custom options (highest priority)\n * const config = buildMonitoringConfig({ slowThreshold: 2000 });\n *\n * // Environment variables\n * // DB_MONITORING_ENABLED=true\n * // DB_MONITORING_SLOW_THRESHOLD=500\n * const config = buildMonitoringConfig();\n *\n * // Defaults (lowest priority)\n * // Development: enabled=true, slowThreshold=1000ms, logQueries=false\n * // Production: enabled=false, slowThreshold=1000ms, logQueries=false\n * ```\n */\nexport function buildMonitoringConfig(options?: Partial<MonitoringConfig>): MonitoringConfig\n{\n const isDevelopment = process.env.NODE_ENV !== 'production';\n\n return {\n enabled: options?.enabled\n ?? parseEnvBoolean('DB_MONITORING_ENABLED', isDevelopment),\n slowThreshold: options?.slowThreshold\n ?? parseEnvNumber('DB_MONITORING_SLOW_THRESHOLD', 1000, 1000),\n logQueries: options?.logQueries\n ?? parseEnvBoolean('DB_MONITORING_LOG_QUERIES', false),\n };\n}","/**\n * Database factory with automatic environment variable detection\n * Supports: Single primary, Primary + Replica\n */\n\nimport { drizzle } from 'drizzle-orm/postgres-js';\n\nimport { logger } from '../../logger';\nimport { loadEnvironment } from '../../env';\nimport { createDatabaseConnection } from './connection.js';\nimport { getPoolConfig, getRetryConfig, type DatabaseOptions, type DatabaseClients, type PoolConfig, type RetryConfig } from './config.js';\n\nconst dbLogger = logger.child('database');\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Database configuration pattern types\n *\n * Represents different ways to configure database connections via environment variables.\n */\ntype DatabasePattern =\n | { type: 'write-read'; write: string; read: string } // Explicit write/read separation\n | { type: 'legacy'; primary: string; replica: string } // Legacy replica pattern\n | { type: 'single'; url: string } // Single database\n | { type: 'none' }; // No configuration\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if any database configuration exists in environment\n */\nfunction hasDatabaseConfig(): boolean\n{\n return !!(\n process.env.DATABASE_URL ||\n process.env.DATABASE_WRITE_URL ||\n process.env.DATABASE_READ_URL\n );\n}\n\n/**\n * Detect database configuration pattern from environment variables\n *\n * Priority order (highest to lowest):\n * 1. write-read: DATABASE_WRITE_URL + DATABASE_READ_URL (explicit separation)\n * 2. legacy: DATABASE_URL + DATABASE_REPLICA_URL (backward compatibility)\n * 3. single: DATABASE_URL (most common)\n * 4. single: DATABASE_WRITE_URL (write-only, no replica)\n * 5. none: No configuration found\n *\n * @returns Detected database configuration pattern\n *\n * @example\n * ```typescript\n * const pattern = detectDatabasePattern();\n *\n * if (pattern.type === 'write-read') {\n * console.log(`Write: ${pattern.write}, Read: ${pattern.read}`);\n * }\n * ```\n */\nfunction detectDatabasePattern(): DatabasePattern\n{\n // Priority 1: Explicit write/read separation (recommended)\n if (process.env.DATABASE_WRITE_URL && process.env.DATABASE_READ_URL)\n {\n return {\n type: 'write-read',\n write: process.env.DATABASE_WRITE_URL,\n read: process.env.DATABASE_READ_URL,\n };\n }\n\n // Priority 2: Legacy replica pattern (backward compatibility)\n if (process.env.DATABASE_URL && process.env.DATABASE_REPLICA_URL)\n {\n return {\n type: 'legacy',\n primary: process.env.DATABASE_URL,\n replica: process.env.DATABASE_REPLICA_URL,\n };\n }\n\n // Priority 3: Single primary (most common)\n if (process.env.DATABASE_URL)\n {\n return {\n type: 'single',\n url: process.env.DATABASE_URL,\n };\n }\n\n // Priority 4: Write-only (no replica)\n if (process.env.DATABASE_WRITE_URL)\n {\n return {\n type: 'single',\n url: process.env.DATABASE_WRITE_URL,\n };\n }\n\n // No configuration found\n return { type: 'none' };\n}\n\n/**\n * Create write and read database clients\n *\n * @param writeUrl - Write database connection string\n * @param readUrl - Read database connection string\n * @param poolConfig - Connection pool configuration\n * @param retryConfig - Retry configuration\n * @returns Database clients\n */\nasync function createWriteReadClients(\n writeUrl: string,\n readUrl: string,\n poolConfig: PoolConfig,\n retryConfig: RetryConfig\n): Promise<DatabaseClients>\n{\n const writeClient = await createDatabaseConnection(writeUrl, poolConfig, retryConfig);\n const readClient = await createDatabaseConnection(readUrl, poolConfig, retryConfig);\n\n return {\n write: drizzle(writeClient),\n read: drizzle(readClient),\n writeClient,\n readClient,\n };\n}\n\n/**\n * Create single database client (used for both read and write)\n *\n * @param url - Database connection string\n * @param poolConfig - Connection pool configuration\n * @param retryConfig - Retry configuration\n * @returns Database clients\n */\nasync function createSingleClient(\n url: string,\n poolConfig: PoolConfig,\n retryConfig: RetryConfig\n): Promise<DatabaseClients>\n{\n const client = await createDatabaseConnection(url, poolConfig, retryConfig);\n const db = drizzle(client);\n\n return {\n write: db,\n read: db,\n writeClient: client,\n readClient: client,\n };\n}\n\n/**\n * Create database client(s) from environment variables\n *\n * Supported patterns (priority order):\n * 1. Single primary: DATABASE_URL\n * 2. Primary + Replica: DATABASE_WRITE_URL + DATABASE_READ_URL\n * 3. Legacy replica: DATABASE_URL + DATABASE_REPLICA_URL\n *\n * @param options - Optional database configuration (pool settings, etc.)\n * @returns Database client(s) or undefined if no configuration found\n *\n * @example\n * ```bash\n * # Single primary (most common)\n * DATABASE_URL=postgresql://localhost:5432/mydb\n *\n * # Primary + Replica\n * DATABASE_WRITE_URL=postgresql://primary:5432/mydb\n * DATABASE_READ_URL=postgresql://replica:5432/mydb\n *\n * # Legacy (backward compatibility)\n * DATABASE_URL=postgresql://primary:5432/mydb\n * DATABASE_REPLICA_URL=postgresql://replica:5432/mydb\n * ```\n *\n * @example\n * ```typescript\n * // Custom pool configuration\n * const db = await createDatabaseFromEnv({\n * pool: { max: 50, idleTimeout: 60 }\n * });\n * ```\n */\nexport async function createDatabaseFromEnv(options?: DatabaseOptions): Promise<DatabaseClients>\n{\n // Load environment variables using centralized loader\n if (!hasDatabaseConfig())\n {\n dbLogger.debug('No DATABASE_URL found, loading environment variables');\n\n const result = loadEnvironment({\n debug: true,\n });\n\n dbLogger.debug('Environment variables loaded', {\n success: result.success,\n loaded: result.loaded.length,\n hasDatabaseUrl: !!process.env.DATABASE_URL,\n hasWriteUrl: !!process.env.DATABASE_WRITE_URL,\n hasReadUrl: !!process.env.DATABASE_READ_URL,\n });\n }\n\n // Quick exit if no database config\n if (!hasDatabaseConfig())\n {\n dbLogger.warn('No database configuration found', {\n cwd: process.cwd(),\n nodeEnv: process.env.NODE_ENV,\n checkedVars: ['DATABASE_URL', 'DATABASE_WRITE_URL', 'DATABASE_READ_URL'],\n });\n return { write: undefined, read: undefined };\n }\n\n try\n {\n const poolConfig = getPoolConfig(options?.pool);\n const retryConfig = getRetryConfig();\n const pattern = detectDatabasePattern();\n\n // Create database clients based on detected pattern\n switch (pattern.type)\n {\n case 'write-read':\n dbLogger.debug('Using write-read pattern', {\n write: pattern.write.replace(/:[^:@]+@/, ':***@'),\n read: pattern.read.replace(/:[^:@]+@/, ':***@'),\n });\n return await createWriteReadClients(\n pattern.write,\n pattern.read,\n poolConfig,\n retryConfig\n );\n\n case 'legacy':\n dbLogger.debug('Using legacy replica pattern', {\n primary: pattern.primary.replace(/:[^:@]+@/, ':***@'),\n replica: pattern.replica.replace(/:[^:@]+@/, ':***@'),\n });\n return await createWriteReadClients(\n pattern.primary,\n pattern.replica,\n poolConfig,\n retryConfig\n );\n\n case 'single':\n dbLogger.debug('Using single database pattern', {\n url: pattern.url.replace(/:[^:@]+@/, ':***@'),\n });\n return await createSingleClient(pattern.url, poolConfig, retryConfig);\n\n case 'none':\n dbLogger.warn('No database pattern detected');\n return { write: undefined, read: undefined };\n }\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n dbLogger.error('Failed to create database connection', {\n error: message,\n stage: 'initialization',\n hasWriteUrl: !!process.env.DATABASE_WRITE_URL,\n hasReadUrl: !!process.env.DATABASE_READ_URL,\n hasUrl: !!process.env.DATABASE_URL,\n hasReplicaUrl: !!process.env.DATABASE_REPLICA_URL,\n });\n\n // If DATABASE_URL is configured, connection failure should be fatal\n // This prevents the server from starting without a database connection\n throw new Error(`Database connection failed: ${message}`, { cause: error });\n }\n}","/**\n * Global Database State Management\n *\n * Manages global database instances using globalThis for persistence across module reloads.\n * This is particularly useful in development with hot module replacement (HMR).\n *\n * The singleton pattern ensures database connections persist even when modules are reloaded\n * during development (e.g., with tsx watch mode).\n */\n\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport type { Sql } from 'postgres';\nimport type { MonitoringConfig } from './config.js';\n\n// ============================================================================\n// Global Type Declarations\n// ============================================================================\n\n/**\n * Extend globalThis with database-specific properties\n *\n * Using globalThis allows database instances to persist across module reloads,\n * which is essential for development environments with hot module replacement.\n */\ndeclare global\n{\n var __SPFN_DB_WRITE__: PostgresJsDatabase<Record<string, unknown>> | undefined;\n var __SPFN_DB_READ__: PostgresJsDatabase<Record<string, unknown>> | undefined;\n var __SPFN_DB_WRITE_CLIENT__: Sql | undefined;\n var __SPFN_DB_READ_CLIENT__: Sql | undefined;\n var __SPFN_DB_HEALTH_CHECK__: NodeJS.Timeout | undefined;\n var __SPFN_DB_MONITORING__: MonitoringConfig | undefined;\n}\n\n// ============================================================================\n// Database Instance Accessors\n// ============================================================================\n\n/**\n * Get write database instance from global state\n */\nexport const getWriteInstance = (): PostgresJsDatabase<Record<string, unknown>> | undefined =>\n globalThis.__SPFN_DB_WRITE__;\n\n/**\n * Set write database instance in global state\n */\nexport const setWriteInstance = (instance: PostgresJsDatabase<Record<string, unknown>> | undefined): void => {\n globalThis.__SPFN_DB_WRITE__ = instance;\n};\n\n/**\n * Get read database instance from global state\n */\nexport const getReadInstance = (): PostgresJsDatabase<Record<string, unknown>> | undefined =>\n globalThis.__SPFN_DB_READ__;\n\n/**\n * Set read database instance in global state\n */\nexport const setReadInstance = (instance: PostgresJsDatabase<Record<string, unknown>> | undefined): void => {\n globalThis.__SPFN_DB_READ__ = instance;\n};\n\n// ============================================================================\n// Raw Client Accessors\n// ============================================================================\n\n/**\n * Get write client from global state (for cleanup)\n */\nexport const getWriteClient = (): Sql | undefined =>\n globalThis.__SPFN_DB_WRITE_CLIENT__;\n\n/**\n * Set write client in global state\n */\nexport const setWriteClient = (client: Sql | undefined): void => {\n globalThis.__SPFN_DB_WRITE_CLIENT__ = client;\n};\n\n/**\n * Get read client from global state (for cleanup)\n */\nexport const getReadClient = (): Sql | undefined =>\n globalThis.__SPFN_DB_READ_CLIENT__;\n\n/**\n * Set read client in global state\n */\nexport const setReadClient = (client: Sql | undefined): void => {\n globalThis.__SPFN_DB_READ_CLIENT__ = client;\n};\n\n// ============================================================================\n// Health Check Accessors\n// ============================================================================\n\n/**\n * Get health check interval from global state\n */\nexport const getHealthCheckInterval = (): NodeJS.Timeout | undefined =>\n globalThis.__SPFN_DB_HEALTH_CHECK__;\n\n/**\n * Set health check interval in global state\n */\nexport const setHealthCheckInterval = (interval: NodeJS.Timeout | undefined): void => {\n globalThis.__SPFN_DB_HEALTH_CHECK__ = interval;\n};\n\n// ============================================================================\n// Monitoring Config Accessors\n// ============================================================================\n\n/**\n * Get monitoring configuration from global state\n */\nexport const getMonitoringConfig = (): MonitoringConfig | undefined =>\n globalThis.__SPFN_DB_MONITORING__;\n\n/**\n * Set monitoring configuration in global state\n */\nexport const setMonitoringConfig = (config: MonitoringConfig | undefined): void => {\n globalThis.__SPFN_DB_MONITORING__ = config;\n};","/**\n * Database Health Check\n *\n * Periodic health checks for database connections with automatic reconnection.\n * Monitors both write and read database instances and attempts recovery on failure.\n */\n\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nimport { logger } from '../../logger';\nimport { createDatabaseFromEnv } from './factory.js';\nimport type { DatabaseOptions, HealthCheckConfig } from './config.js';\nimport {\n getHealthCheckInterval,\n setHealthCheckInterval,\n setWriteInstance,\n setReadInstance,\n setWriteClient,\n setReadClient,\n} from './global-state.js';\n\nconst dbLogger = logger.child('database');\n\n/**\n * Start database health check\n *\n * Periodically checks database connection health and attempts reconnection if enabled.\n * Automatically started by initDatabase() when health check is enabled.\n *\n * @param config - Health check configuration\n * @param options - Optional database configuration (pool settings, etc.)\n * @param getDatabase - Function to get database instance (to avoid circular dependency)\n * @param closeDatabase - Function to close database (for reconnection)\n *\n * @example\n * ```typescript\n * import { startHealthCheck } from '@spfn/core/db/manager/health-check';\n *\n * startHealthCheck(\n * {\n * enabled: true,\n * interval: 30000, // 30 seconds\n * reconnect: true,\n * maxRetries: 5,\n * retryInterval: 10000, // 10 seconds\n * },\n * undefined,\n * getDatabase,\n * closeDatabase\n * );\n * ```\n */\nimport type { GetDatabaseFn } from './manager';\n\nexport function startHealthCheck(\n config: HealthCheckConfig,\n options: DatabaseOptions | undefined,\n getDatabase: GetDatabaseFn,\n closeDatabase: () => Promise<void>\n): void\n{\n const healthCheck = getHealthCheckInterval();\n if (healthCheck)\n {\n dbLogger.debug('Health check already running');\n return;\n }\n\n dbLogger.info('Starting database health check', {\n interval: `${config.interval}ms`,\n reconnect: config.reconnect,\n });\n\n const interval = setInterval(async () =>\n {\n try\n {\n const write = getDatabase('write');\n const read = getDatabase('read');\n\n // Check write connection\n if (write)\n {\n await write.execute('SELECT 1');\n }\n\n // Check read connection (if different)\n if (read && read !== write)\n {\n await read.execute('SELECT 1');\n }\n\n // Health check passed - no need to log (only log failures)\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n dbLogger.error('Database health check failed', { error: message });\n\n // Attempt reconnection if enabled\n if (config.reconnect)\n {\n await attemptReconnection(config, options, closeDatabase);\n }\n }\n }, config.interval);\n\n setHealthCheckInterval(interval);\n}\n\n/**\n * Attempt database reconnection with retry logic\n *\n * Closes existing connections and attempts to reinitialize the database.\n * Retries multiple times with configurable delay between attempts.\n *\n * @param config - Health check configuration\n * @param options - Optional database configuration (pool settings, etc.)\n * @param closeDatabase - Function to close existing database connections\n */\nasync function attemptReconnection(\n config: HealthCheckConfig,\n options: DatabaseOptions | undefined,\n closeDatabase: () => Promise<void>\n): Promise<void>\n{\n dbLogger.warn('Attempting database reconnection', {\n maxRetries: config.maxRetries,\n retryInterval: `${config.retryInterval}ms`,\n });\n\n for (let attempt = 1; attempt <= config.maxRetries; attempt++)\n {\n try\n {\n dbLogger.debug(`Reconnection attempt ${attempt}/${config.maxRetries}`);\n\n // Close existing connections\n await closeDatabase();\n\n // Wait before retry\n await new Promise(resolve => setTimeout(resolve, config.retryInterval));\n\n // Reinitialize database\n const result = await createDatabaseFromEnv(options);\n\n if (result.write)\n {\n // Test connection\n await result.write.execute('SELECT 1');\n\n // Store instances\n setWriteInstance(result.write);\n setReadInstance(result.read);\n setWriteClient(result.writeClient);\n setReadClient(result.readClient);\n\n dbLogger.info('Database reconnection successful', { attempt });\n return;\n }\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n dbLogger.error(`Reconnection attempt ${attempt} failed`, {\n error: message,\n attempt,\n maxRetries: config.maxRetries,\n });\n\n if (attempt === config.maxRetries)\n {\n dbLogger.error('Max reconnection attempts reached, giving up');\n }\n }\n }\n}\n\n/**\n * Stop database health check\n *\n * Automatically called by closeDatabase().\n * Can also be called manually to stop health checks.\n *\n * @example\n * ```typescript\n * import { stopHealthCheck } from '@spfn/core/db/manager/health-check';\n *\n * stopHealthCheck();\n * ```\n */\nexport function stopHealthCheck(): void\n{\n const healthCheck = getHealthCheckInterval();\n if (healthCheck)\n {\n clearInterval(healthCheck);\n setHealthCheckInterval(undefined);\n dbLogger.info('Database health check stopped');\n }\n}","/**\n * Global Database instance manager\n * Provides singleton access to database across all modules\n * Supports Primary + Replica pattern with separate read/write instances\n */\n\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nimport { logger } from '../../logger';\nimport { createDatabaseFromEnv } from './factory.js';\nimport type { DatabaseOptions, MonitoringConfig } from \"./config.js\";\nimport { buildHealthCheckConfig, buildMonitoringConfig } from \"./config.js\";\nimport {\n getWriteInstance,\n setWriteInstance,\n getReadInstance,\n setReadInstance,\n getWriteClient,\n setWriteClient,\n getReadClient,\n setReadClient,\n getMonitoringConfig,\n setMonitoringConfig,\n} from './global-state.js';\nimport { startHealthCheck, stopHealthCheck } from './health-check.js';\n\nconst dbLogger = logger.child('database');\n\n/**\n * DB connection type\n */\nexport type DbConnectionType = 'read' | 'write';\n\n/**\n * GetDatabase function type\n */\nexport type GetDatabaseFn = (type?: DbConnectionType) => PostgresJsDatabase<Record<string, unknown>> | undefined;\n\n/**\n * Get caller information from stack trace\n */\nfunction getCallerInfo(): string | undefined\n{\n try\n {\n const stack = new Error().stack;\n if (!stack) return undefined;\n\n const lines = stack.split('\\n');\n // Skip first 3 lines: Error, getCallerInfo, getDatabase\n for (let i = 3; i < lines.length; i++)\n {\n const line = lines[i];\n // Find first meaningful caller (not node_modules/@spfn/core/db)\n if (!line.includes('node_modules') && !line.includes('/db/manager/'))\n {\n // Extract file:line from stack line\n const match = line.match(/\\((.+):(\\d+):(\\d+)\\)/) || line.match(/at (.+):(\\d+):(\\d+)/);\n if (match)\n {\n const fullPath = match[1];\n // Get relative path from project root\n const parts = fullPath.split('/');\n const srcIndex = parts.lastIndexOf('src');\n if (srcIndex !== -1)\n {\n const relativePath = parts.slice(srcIndex).join('/');\n return `${relativePath}:${match[2]}`;\n }\n return `${fullPath}:${match[2]}`;\n }\n break;\n }\n }\n }\n catch\n {\n // Ignore errors in stack trace parsing\n }\n return undefined;\n}\n\n/**\n * Get global database write instance\n *\n * @returns Database write instance or undefined if not initialized\n *\n * @example\n * ```typescript\n * import { getDatabase } from '@spfn/core/db';\n *\n * const db = getDatabase();\n * if (db) {\n * const users = await db.select().from(usersTable);\n * }\n * ```\n */\nexport function getDatabase(type?: DbConnectionType): PostgresJsDatabase<Record<string, unknown>> | undefined\n{\n const writeInst = getWriteInstance();\n const readInst = getReadInstance();\n\n // Detailed debug logging with caller info (only if DB_DEBUG_TRACE is enabled)\n if (process.env.DB_DEBUG_TRACE === 'true')\n {\n const caller = getCallerInfo();\n dbLogger.debug('getDatabase() called', {\n type: type || 'write',\n hasWrite: !!writeInst,\n hasRead: !!readInst,\n caller,\n });\n }\n\n if (type === 'read')\n {\n return readInst ?? writeInst;\n }\n\n return writeInst;\n}\n\n/**\n * Set global database instances (for testing or manual configuration)\n *\n * @param write - Database write instance\n * @param read - Database read instance (optional, defaults to write)\n *\n * @example\n * ```typescript\n * import { setDatabase } from '@spfn/core/db';\n * import { drizzle } from 'drizzle-orm/postgres-js';\n * import postgres from 'postgres';\n *\n * const writeClient = postgres('postgresql://primary:5432/mydb');\n * const readClient = postgres('postgresql://replica:5432/mydb');\n * setDatabase(drizzle(writeClient), drizzle(readClient));\n * ```\n */\nexport function setDatabase(\n write: PostgresJsDatabase<Record<string, unknown>> | undefined,\n read?: PostgresJsDatabase<Record<string, unknown>> | undefined\n): void\n{\n setWriteInstance(write);\n setReadInstance(read ?? write);\n}\n\n/**\n * Initialize database from environment variables\n * Automatically called by server startup\n *\n * Supported environment variables:\n * - DATABASE_URL (single primary)\n * - DATABASE_WRITE_URL + DATABASE_READ_URL (primary + replica)\n * - DATABASE_URL + DATABASE_REPLICA_URL (legacy replica)\n * - DB_POOL_MAX (connection pool max size)\n * - DB_POOL_IDLE_TIMEOUT (connection idle timeout in seconds)\n * - DB_HEALTH_CHECK_ENABLED (enable health checks, default: true)\n * - DB_HEALTH_CHECK_INTERVAL (health check interval in ms, default: 60000)\n * - DB_HEALTH_CHECK_RECONNECT (enable auto-reconnect, default: true)\n * - DB_HEALTH_CHECK_MAX_RETRIES (max reconnection attempts, default: 3)\n * - DB_HEALTH_CHECK_RETRY_INTERVAL (retry interval in ms, default: 5000)\n * - DB_MONITORING_ENABLED (enable query monitoring, default: true in dev, false in prod)\n * - DB_MONITORING_SLOW_THRESHOLD (slow query threshold in ms, default: 1000)\n * - DB_MONITORING_LOG_QUERIES (log actual SQL queries, default: false)\n * - DB_DEBUG_TRACE (enable detailed getDatabase() call tracing with caller info, default: false)\n *\n * Configuration priority:\n * 1. options parameter (ServerConfig)\n * 2. Environment variables\n * 3. Defaults (based on NODE_ENV)\n *\n * @param options - Optional database configuration (pool settings, etc.)\n * @returns Object with write and read instances\n *\n * @example\n * ```typescript\n * import { initDatabase } from '@spfn/core/db';\n *\n * // Manual initialization (not needed if using server startup)\n * const { write, read } = await initDatabase();\n * if (write) {\n * console.log('Database connected');\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Custom pool configuration\n * const { write, read } = await initDatabase({\n * pool: { max: 50, idleTimeout: 60 }\n * });\n * ```\n */\nexport async function initDatabase(options?: DatabaseOptions): Promise<{\n write?: PostgresJsDatabase<Record<string, unknown>>;\n read?: PostgresJsDatabase<Record<string, unknown>>;\n}>\n{\n // Already initialized\n const writeInst = getWriteInstance();\n if (writeInst)\n {\n dbLogger.debug('Database already initialized');\n return { write: writeInst, read: getReadInstance() };\n }\n\n // Auto-detect from environment\n const result = await createDatabaseFromEnv(options);\n\n if (result.write)\n {\n try\n {\n // Test connection with a simple query\n await result.write.execute('SELECT 1');\n\n // Test read instance if different\n if (result.read && result.read !== result.write)\n {\n await result.read.execute('SELECT 1');\n }\n\n // Store instances in globalThis\n setWriteInstance(result.write);\n setReadInstance(result.read);\n setWriteClient(result.writeClient);\n setReadClient(result.readClient);\n\n const hasReplica = result.read && result.read !== result.write;\n dbLogger.info(\n hasReplica\n ? 'Database connected (Primary + Replica)'\n : 'Database connected'\n );\n\n // Start health check (automatic)\n const healthCheckConfig = buildHealthCheckConfig(options?.healthCheck);\n if (healthCheckConfig.enabled)\n {\n startHealthCheck(healthCheckConfig, options, getDatabase, closeDatabase);\n }\n\n // Initialize monitoring configuration\n const monConfig = buildMonitoringConfig(options?.monitoring);\n setMonitoringConfig(monConfig);\n if (monConfig.enabled)\n {\n dbLogger.info('Database query monitoring enabled', {\n slowThreshold: `${monConfig.slowThreshold}ms`,\n logQueries: monConfig.logQueries,\n });\n }\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n dbLogger.error('Database connection failed', { error: message });\n\n // Cleanup on failure\n await closeDatabase();\n\n // If DATABASE_URL is configured, connection failure should be fatal\n throw new Error(`Database connection test failed: ${message}`, { cause: error });\n }\n }\n else\n {\n dbLogger.warn('No database configuration found');\n dbLogger.warn('Set DATABASE_URL environment variable to enable database');\n }\n\n return { write: getWriteInstance(), read: getReadInstance() };\n}\n\n/**\n * Close all database connections and cleanup\n *\n * Properly closes postgres connection pools with timeout.\n * Should be called during graceful shutdown or after tests.\n *\n * @example\n * ```typescript\n * import { closeDatabase } from '@spfn/core/db';\n *\n * // During graceful shutdown\n * process.on('SIGTERM', async () => {\n * await closeDatabase();\n * process.exit(0);\n * });\n *\n * // In tests\n * afterAll(async () => {\n * await closeDatabase();\n * });\n * ```\n */\nexport async function closeDatabase(): Promise<void>\n{\n const writeInst = getWriteInstance();\n const readInst = getReadInstance();\n if (!writeInst && !readInst)\n {\n dbLogger.debug('No database connections to close');\n return;\n }\n\n // Stop health check\n stopHealthCheck();\n\n try\n {\n const closePromises: Promise<void>[] = [];\n\n // Close write client\n const writeC = getWriteClient();\n if (writeC)\n {\n dbLogger.debug('Closing write connection...');\n closePromises.push(\n writeC.end({ timeout: 5 })\n .then(() => dbLogger.debug('Write connection closed'))\n .catch(err => dbLogger.error('Error closing write connection', err))\n );\n }\n\n // Close read client (if different from write)\n const readC = getReadClient();\n if (readC && readC !== writeC)\n {\n dbLogger.debug('Closing read connection...');\n closePromises.push(\n readC.end({ timeout: 5 })\n .then(() => dbLogger.debug('Read connection closed'))\n .catch(err => dbLogger.error('Error closing read connection', err))\n );\n }\n\n // Wait for all connections to close\n await Promise.all(closePromises);\n\n dbLogger.info('All database connections closed');\n }\n catch (error)\n {\n dbLogger.error('Error during database cleanup', error as Error);\n throw error;\n }\n finally\n {\n // Always clear instances\n setWriteInstance(undefined);\n setReadInstance(undefined);\n setWriteClient(undefined);\n setReadClient(undefined);\n setMonitoringConfig(undefined);\n }\n}\n\n/**\n * Get database connection info (for debugging)\n */\nexport function getDatabaseInfo(): {\n hasWrite: boolean;\n hasRead: boolean;\n isReplica: boolean;\n}\n{\n const writeInst = getWriteInstance();\n const readInst = getReadInstance();\n\n return {\n hasWrite: !!writeInst,\n hasRead: !!readInst,\n isReplica: !!(readInst && readInst !== writeInst),\n };\n}\n\n/**\n * Get current monitoring configuration\n *\n * Returns the monitoring configuration that was set during database initialization.\n * Used by Repository to determine if and how to monitor query performance.\n *\n * @returns Current monitoring configuration or undefined if database not initialized\n *\n * @example\n * ```typescript\n * import { getDatabaseMonitoringConfig } from '@spfn/core/db';\n *\n * const config = getDatabaseMonitoringConfig();\n * if (config?.enabled) {\n * console.log(`Slow query threshold: ${config.slowThreshold}ms`);\n * }\n * ```\n */\nexport function getDatabaseMonitoringConfig(): MonitoringConfig | undefined\n{\n return getMonitoringConfig();\n}","/**\n * Database Manager Module Exports\n */\n\n// Database Factory (Environment Detection)\nexport { createDatabaseFromEnv } from './factory.js';\nexport type { DatabaseClients } from './config.js';\n\n// Database Manager (Singleton Pattern)\nexport {\n initDatabase,\n getDatabase,\n setDatabase,\n closeDatabase,\n getDatabaseInfo,\n getDatabaseMonitoringConfig,\n} from './manager.js';\n\n// Connection Functions\nexport { createDatabaseConnection, checkConnection } from './connection.js';\n\n// Configuration Types\nexport type { PoolConfig, RetryConfig } from './config.js';","/**\n * Drizzle Kit configuration generator\n * Automatically generates drizzle.config.ts from environment variables\n */\n\nimport { existsSync, readdirSync, readFileSync, statSync } from 'fs';\nimport { join, dirname, basename } from 'path';\n\nexport interface DrizzleConfigOptions\n{\n /** Database connection URL (defaults to process.env.DATABASE_URL) */\n databaseUrl?: string;\n\n /** Schema files glob pattern or array of patterns (defaults to './src/server/entities/\\*\\*\\/*.ts') */\n schema?: string | string[];\n\n /** Migration output directory (defaults to './src/server/drizzle') */\n out?: string;\n\n /** Database dialect (auto-detected from URL if not provided) */\n dialect?: 'postgresql' | 'mysql' | 'sqlite';\n\n /** Current working directory for discovering package schemas */\n cwd?: string;\n\n /** Disable automatic package schema discovery */\n disablePackageDiscovery?: boolean;\n\n /** Only include schemas from specific package (e.g., '@spfn/cms') */\n packageFilter?: string;\n}\n\n/**\n * Expand glob patterns to actual file paths\n * Handles patterns like:\n * - ./dist/entities/*.js → [./dist/entities/foo.js, ./dist/entities/bar.js]\n * - ./dist/entities/**\\/*.js → recursively finds all .js files\n *\n * @param pattern - Glob pattern or file path\n * @returns Array of expanded file paths\n */\nfunction expandGlobPattern(pattern: string): string[]\n{\n // If pattern doesn't contain wildcards, return as-is\n if (!pattern.includes('*'))\n {\n return existsSync(pattern) ? [pattern] : [];\n }\n\n const files: string[] = [];\n\n // Handle /**/* pattern (recursive)\n if (pattern.includes('**'))\n {\n const [baseDir, ...rest] = pattern.split('**');\n const extension = rest.join('').replace(/[\\/\\\\]\\*\\./g, '').trim();\n\n const scanRecursive = (dir: string) =>\n {\n if (!existsSync(dir)) return;\n\n try\n {\n const entries = readdirSync(dir);\n\n for (const entry of entries)\n {\n const fullPath = join(dir, entry);\n\n try\n {\n const stat = statSync(fullPath);\n\n if (stat.isDirectory())\n {\n scanRecursive(fullPath);\n }\n else if (stat.isFile())\n {\n // Check if file matches extension\n if (!extension || fullPath.endsWith(extension))\n {\n files.push(fullPath);\n }\n }\n }\n catch\n {\n // Skip files we can't stat\n }\n }\n }\n catch\n {\n // Skip directories we can't read\n }\n };\n\n scanRecursive(baseDir.trim() || '.');\n }\n // Handle /* pattern (single level)\n else if (pattern.includes('*'))\n {\n const dir = dirname(pattern);\n const filePattern = basename(pattern);\n\n if (!existsSync(dir)) return [];\n\n try\n {\n const entries = readdirSync(dir);\n\n for (const entry of entries)\n {\n const fullPath = join(dir, entry);\n\n try\n {\n const stat = statSync(fullPath);\n\n if (stat.isFile())\n {\n // Simple pattern matching (*.js matches foo.js)\n if (filePattern === '*' ||\n (filePattern.startsWith('*.') && entry.endsWith(filePattern.slice(1))))\n {\n files.push(fullPath);\n }\n }\n }\n catch\n {\n // Skip files we can't stat\n }\n }\n }\n catch\n {\n // Skip directories we can't read\n }\n }\n\n return files;\n}\n\n/**\n * Discover schema paths from installed packages\n * Only scans packages that:\n * 1. Are in @spfn scope\n * 2. Are direct dependencies with \"spfn\" keyword or \"spfn\" field in package.json\n */\nfunction discoverPackageSchemas(cwd: string): string[]\n{\n const schemas: string[] = [];\n const nodeModulesPath = join(cwd, 'node_modules');\n\n if (!existsSync(nodeModulesPath))\n {\n return schemas;\n }\n\n // Get direct dependencies from project's package.json\n const projectPkgPath = join(cwd, 'package.json');\n let directDeps: Set<string> = new Set();\n\n if (existsSync(projectPkgPath))\n {\n try\n {\n const projectPkg = JSON.parse(readFileSync(projectPkgPath, 'utf-8'));\n directDeps = new Set([\n ...Object.keys(projectPkg.dependencies || {}),\n ...Object.keys(projectPkg.devDependencies || {})\n ]);\n }\n catch (error)\n {\n // If we can't read project package.json, just scan @spfn packages\n }\n }\n\n const checkPackage = (_pkgName: string, pkgPath: string) =>\n {\n const pkgJsonPath = join(pkgPath, 'package.json');\n\n if (!existsSync(pkgJsonPath)) return;\n\n try\n {\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));\n\n // Check if package has schema declarations\n if (pkgJson.spfn?.schemas)\n {\n const packageSchemas = Array.isArray(pkgJson.spfn.schemas)\n ? pkgJson.spfn.schemas\n : [pkgJson.spfn.schemas];\n\n // Convert to absolute paths from package root and expand globs\n for (const schema of packageSchemas)\n {\n const absolutePath = join(pkgPath, schema);\n\n // Expand glob patterns to actual file lists\n // This prevents drizzle-kit from hanging on glob patterns\n const expandedFiles = expandGlobPattern(absolutePath);\n\n // Filter out index files (they are re-exports, not schema definitions)\n const schemaFiles = expandedFiles.filter(file =>\n !file.endsWith('/index.js') &&\n !file.endsWith('/index.ts') &&\n !file.endsWith('/index.mjs') &&\n !file.endsWith('\\\\index.js') &&\n !file.endsWith('\\\\index.ts') &&\n !file.endsWith('\\\\index.mjs')\n );\n\n schemas.push(...schemaFiles);\n }\n }\n }\n catch (error)\n {\n // Skip packages with invalid package.json\n }\n };\n\n // 1. Always scan @spfn/* packages\n const spfnDir = join(nodeModulesPath, '@spfn');\n if (existsSync(spfnDir))\n {\n try\n {\n const spfnPackages = readdirSync(spfnDir);\n for (const pkg of spfnPackages)\n {\n checkPackage(`@spfn/${pkg}`, join(spfnDir, pkg));\n }\n }\n catch (error)\n {\n // Skip if can't read @spfn directory\n }\n }\n\n // 2. Check direct dependencies for SPFN integration\n for (const depName of directDeps)\n {\n // Skip if already checked (@spfn/* packages)\n if (depName.startsWith('@spfn/')) continue;\n\n // Resolve package path (handle scoped packages)\n const pkgPath = depName.startsWith('@')\n ? join(nodeModulesPath, ...depName.split('/'))\n : join(nodeModulesPath, depName);\n\n checkPackage(depName, pkgPath);\n }\n\n return schemas;\n}\n\n/**\n * Detect database dialect from connection URL\n */\nexport function detectDialect(url: string): 'postgresql' | 'mysql' | 'sqlite'\n{\n if (url.startsWith('postgres://') || url.startsWith('postgresql://'))\n {\n return 'postgresql';\n }\n\n if (url.startsWith('mysql://'))\n {\n return 'mysql';\n }\n\n if (url.startsWith('sqlite://') || url.includes('.db') || url.includes('.sqlite'))\n {\n return 'sqlite';\n }\n\n throw new Error(\n `Unsupported database URL format: ${url}. Supported: postgresql://, mysql://, sqlite://`\n );\n}\n\n/**\n * Generate Drizzle Kit configuration\n *\n * @param options - Configuration options\n * @returns Drizzle Kit configuration object\n *\n * @example\n * ```ts\n * // Zero-config (reads from process.env.DATABASE_URL)\n * const config = getDrizzleConfig();\n *\n * // Custom config\n * const config = getDrizzleConfig({\n * databaseUrl: 'postgresql://localhost/mydb',\n * schema: './src/db/schema/*.ts',\n * out: './migrations',\n * });\n * ```\n */\nexport function getDrizzleConfig(options: DrizzleConfigOptions = {})\n{\n const databaseUrl = options.databaseUrl ?? process.env.DATABASE_URL;\n\n if (!databaseUrl)\n {\n throw new Error(\n 'DATABASE_URL is required. Set it in .env or pass it to getDrizzleConfig()'\n );\n }\n\n const dialect = options.dialect ?? detectDialect(databaseUrl);\n const out = options.out ?? './src/server/drizzle';\n\n // If packageFilter is specified, only include that package's schemas\n if (options.packageFilter)\n {\n const packageSchemas = options.disablePackageDiscovery\n ? []\n : discoverPackageSchemas(options.cwd ?? process.cwd());\n\n // Filter to only the specified package\n const filteredSchemas = packageSchemas.filter(schemaPath =>\n schemaPath.includes(`node_modules/${options.packageFilter}/`)\n );\n\n if (filteredSchemas.length === 0)\n {\n throw new Error(\n `No schemas found for package ${options.packageFilter}. ` +\n `Make sure the package is installed and has \"spfn.schemas\" in package.json.`\n );\n }\n\n const schema = filteredSchemas.length === 1 ? filteredSchemas[0] : filteredSchemas;\n\n return {\n schema,\n out,\n dialect,\n dbCredentials: getDbCredentials(dialect, databaseUrl),\n };\n }\n\n // Default: merge user schemas and all package schemas\n const userSchema = options.schema ?? './src/server/entities/**/*.ts'; // Support nested folders\n const userSchemas = Array.isArray(userSchema) ? userSchema : [userSchema];\n\n // Discover package schemas unless disabled\n const packageSchemas = options.disablePackageDiscovery\n ? []\n : discoverPackageSchemas(options.cwd ?? process.cwd());\n\n // Merge user schemas and package schemas\n const allSchemas = [...userSchemas, ...packageSchemas];\n const schema = allSchemas.length === 1 ? allSchemas[0] : allSchemas;\n\n return {\n schema,\n out,\n dialect,\n dbCredentials: getDbCredentials(dialect, databaseUrl),\n };\n}\n\n/**\n * Get database credentials based on dialect\n */\nfunction getDbCredentials(dialect: string, url: string)\n{\n switch (dialect)\n {\n case 'postgresql':\n case 'mysql':\n return { url };\n\n case 'sqlite':\n // Extract file path from sqlite:// URL\n const dbPath = url.replace('sqlite://', '').replace('sqlite:', '');\n return { url: dbPath };\n\n default:\n throw new Error(`Unsupported dialect: ${dialect}`);\n }\n}\n\n/**\n * Generate drizzle.config.ts file content\n *\n * @param options - Configuration options\n * @returns File content as string\n */\nexport function generateDrizzleConfigFile(options: DrizzleConfigOptions = {}): string\n{\n const config = getDrizzleConfig(options);\n\n // Format schema value (handle both string and array)\n const schemaValue = Array.isArray(config.schema)\n ? `[\\n ${config.schema.map(s => `'${s}'`).join(',\\n ')}\\n ]`\n : `'${config.schema}'`;\n\n return `import { defineConfig } from 'drizzle-kit';\n\nexport default defineConfig({\n schema: ${schemaValue},\n out: '${config.out}',\n dialect: '${config.dialect}',\n dbCredentials: ${JSON.stringify(config.dbCredentials, null, 4)},\n});\n`;\n}","/**\n * Schema Helper Functions\n *\n * Common field patterns for Drizzle ORM entities to reduce boilerplate.\n *\n * @example\n * ```typescript\n * import { pgTable, text } from 'drizzle-orm/pg-core';\n * import { id, timestamps } from '@spfn/core';\n *\n * export const users = pgTable('users', {\n * id: id(),\n * email: text('email').unique(),\n * ...timestamps(),\n * });\n * ```\n */\n\nimport type { PgColumn } from 'drizzle-orm/pg-core';\nimport { bigserial, timestamp, text, uuid as pgUuid } from 'drizzle-orm/pg-core';\n\n/**\n * Standard auto-incrementing primary key\n *\n * @returns bigserial primary key column\n *\n * @example\n * ```typescript\n * export const users = pgTable('users', {\n * id: id(),\n * // ...\n * });\n * ```\n */\nexport function id()\n{\n return bigserial('id', { mode: 'number' }).primaryKey();\n}\n\n/**\n * Standard timestamp fields (createdAt, updatedAt)\n *\n * Both fields are timezone-aware, auto-set to current time on creation.\n * When autoUpdate is enabled, updatedAt will be automatically updated on record updates.\n *\n * @param options - Optional configuration\n * @param options.autoUpdate - Automatically update updatedAt on record updates (default: false)\n * @returns Object with createdAt and updatedAt columns\n *\n * @example\n * ```typescript\n * // Without auto-update\n * export const users = pgTable('users', {\n * id: id(),\n * email: text('email'),\n * ...timestamps(),\n * });\n *\n * // With auto-update\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * ...timestamps({ autoUpdate: true }),\n * });\n * ```\n */\nexport function timestamps(options?: { autoUpdate?: boolean })\n{\n const updatedAtColumn = timestamp('updated_at', { withTimezone: true, mode: 'date' })\n .defaultNow()\n .notNull();\n\n // Mark column for auto-update if enabled\n if (options?.autoUpdate)\n {\n (updatedAtColumn as any).__autoUpdate = true;\n }\n\n return {\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' })\n .defaultNow()\n .notNull(),\n updatedAt: updatedAtColumn,\n };\n}\n\n/**\n * Auto-updating timestamp field (for custom timestamp fields)\n *\n * Creates a timestamp field that automatically updates on record updates.\n * Useful when you need a custom name like 'modifiedAt', 'lastUpdated', etc.\n *\n * @param fieldName - Field name in camelCase (default: 'updatedAt')\n * @returns Object with the timestamp column (converts camelCase to snake_case)\n *\n * @example\n * ```typescript\n * // Custom field name\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * ...autoUpdateTimestamp('modifiedAt'), // Creates 'modified_at' column\n * });\n *\n * // Default field name\n * export const articles = pgTable('articles', {\n * id: id(),\n * ...autoUpdateTimestamp(), // Creates 'updatedAt' -> 'updated_at'\n * });\n * ```\n */\nexport function autoUpdateTimestamp(fieldName: string = 'updatedAt')\n{\n // Convert camelCase to snake_case for column name\n const columnName = fieldName.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');\n\n const column = timestamp(columnName, { withTimezone: true, mode: 'date' })\n .defaultNow()\n .notNull();\n\n // Mark column for auto-update\n (column as any).__autoUpdate = true;\n\n return {\n [fieldName]: column,\n };\n}\n\n/**\n * Foreign key reference to another table\n *\n * Creates a bigserial column with cascade delete.\n * Type-safe: ensures the reference points to a valid PostgreSQL column.\n *\n * @param name - Column name (e.g., 'author' creates 'author_id')\n * @param reference - Reference to parent table column\n * @param options - Optional foreign key options\n *\n * @example\n * ```typescript\n * import { users } from './users';\n *\n * export const posts = pgTable('posts', {\n * id: id(),\n * authorId: foreignKey('author', () => users.id),\n * ...timestamps(),\n * });\n * ```\n */\nexport function foreignKey<T extends PgColumn>(\n name: string,\n reference: () => T,\n options?: { onDelete?: 'cascade' | 'set null' | 'restrict' | 'no action' }\n)\n{\n return bigserial(`${name}_id`, { mode: 'number' })\n .notNull()\n .references(reference, { onDelete: options?.onDelete ?? 'cascade' });\n}\n\n/**\n * Optional foreign key reference (nullable)\n *\n * Type-safe: ensures the reference points to a valid PostgreSQL column.\n *\n * @param name - Column name (e.g., 'author' creates 'author_id')\n * @param reference - Reference to parent table column\n * @param options - Optional foreign key options\n *\n * @example\n * ```typescript\n * export const posts = pgTable('posts', {\n * id: id(),\n * authorId: optionalForeignKey('author', () => users.id),\n * });\n * ```\n */\nexport function optionalForeignKey<T extends PgColumn>(\n name: string,\n reference: () => T,\n options?: { onDelete?: 'cascade' | 'set null' | 'restrict' | 'no action' }\n)\n{\n return bigserial(`${name}_id`, { mode: 'number' })\n .references(reference, { onDelete: options?.onDelete ?? 'set null' });\n}\n\n/**\n * UUID primary key\n *\n * Creates a UUID column as primary key with automatic default value generation.\n * Useful for distributed systems or when you need globally unique identifiers.\n *\n * @returns uuid primary key column with gen_random_uuid() default\n *\n * @example\n * ```typescript\n * export const sessions = pgTable('sessions', {\n * id: uuid(),\n * userId: foreignKey('user', () => users.id),\n * ...timestamps(),\n * });\n * ```\n */\nexport function uuid()\n{\n return pgUuid('id').defaultRandom().primaryKey();\n}\n\n/**\n * Audit fields for tracking record creators and updaters\n *\n * Adds createdBy and updatedBy fields for user tracking.\n * Typically stores user IDs, emails, or usernames.\n *\n * @returns Object with createdBy and updatedBy columns\n *\n * @example\n * ```typescript\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * ...timestamps(),\n * ...auditFields(),\n * });\n *\n * // Usage in route\n * await db.insert(posts).values({\n * title: 'New Post',\n * createdBy: currentUser.email,\n * });\n * ```\n */\nexport function auditFields()\n{\n return {\n createdBy: text('created_by'),\n updatedBy: text('updated_by'),\n };\n}\n\n/**\n * Publishing fields for content management\n *\n * Tracks when and by whom content was published.\n * Useful for CMS, blog posts, articles, etc.\n *\n * @returns Object with publishedAt and publishedBy columns\n *\n * @example\n * ```typescript\n * export const articles = pgTable('articles', {\n * id: id(),\n * title: text('title'),\n * status: text('status'), // draft/published/archived\n * ...publishingFields(),\n * ...timestamps(),\n * });\n *\n * // Publishing an article\n * await db.update(articles)\n * .set({\n * status: 'published',\n * publishedAt: new Date(),\n * publishedBy: currentUser.email,\n * })\n * .where(eq(articles.id, articleId));\n * ```\n */\nexport function publishingFields()\n{\n return {\n publishedAt: timestamp('published_at', { withTimezone: true, mode: 'date' }),\n publishedBy: text('published_by'),\n };\n}\n\n/**\n * Custom verification timestamp field\n *\n * Creates a nullable timestamp field for tracking verification status.\n * Useful for email verification, phone verification, etc.\n *\n * @param fieldName - Field name in camelCase (e.g., 'emailVerified', 'phoneVerified')\n * @returns Object with verification timestamp column (converts to snake_case + '_at')\n *\n * @example\n * ```typescript\n * export const users = pgTable('users', {\n * id: id(),\n * email: text('email'),\n * phone: text('phone'),\n * ...verificationTimestamp('emailVerified'), // emailVerifiedAt -> email_verified_at\n * ...verificationTimestamp('phoneVerified'), // phoneVerifiedAt -> phone_verified_at\n * ...timestamps(),\n * });\n *\n * // Verify email\n * await db.update(users)\n * .set({ emailVerifiedAt: new Date() })\n * .where(eq(users.email, userEmail));\n * ```\n */\nexport function verificationTimestamp(fieldName: string)\n{\n // Convert camelCase to snake_case and add '_at' suffix\n const columnName = fieldName\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '') + '_at';\n\n return {\n [fieldName + 'At']: timestamp(columnName, { withTimezone: true, mode: 'date' }),\n };\n}\n\n/**\n * Soft delete fields\n *\n * Adds deletedAt and deletedBy for logical deletion.\n * Records are marked as deleted instead of being physically removed.\n *\n * @returns Object with deletedAt and deletedBy columns\n *\n * @example\n * ```typescript\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * ...timestamps(),\n * ...softDelete(),\n * });\n *\n * // Soft delete\n * await db.update(posts)\n * .set({\n * deletedAt: new Date(),\n * deletedBy: currentUser.email,\n * })\n * .where(eq(posts.id, postId));\n *\n * // Query only non-deleted records\n * const activePosts = await db.select()\n * .from(posts)\n * .where(isNull(posts.deletedAt));\n * ```\n */\nexport function softDelete()\n{\n return {\n deletedAt: timestamp('deleted_at', { withTimezone: true, mode: 'date' }),\n deletedBy: text('deleted_by'),\n };\n}\n\n/**\n * Type-safe status enum field\n *\n * Creates a status text column with enum constraint and default value.\n * Provides compile-time type safety for status values.\n *\n * @param statuses - Array of status values (at least 2 required)\n * @param defaultStatus - Default status value (defaults to first status)\n * @returns Status column with enum constraint\n *\n * @example\n * ```typescript\n * // Basic usage\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * status: statusEnum(['draft', 'published', 'archived'] as const),\n * ...timestamps(),\n * });\n *\n * // With custom default\n * export const users = pgTable('users', {\n * id: id(),\n * email: text('email'),\n * status: statusEnum(['active', 'inactive', 'suspended'] as const, 'active'),\n * ...timestamps(),\n * });\n *\n * // TypeScript infers the type\n * type PostStatus = 'draft' | 'published' | 'archived';\n * ```\n */\nexport function statusEnum<T extends readonly [string, ...string[]]>(\n statuses: T,\n defaultStatus?: T[number]\n)\n{\n return text('status', { enum: statuses as any })\n .notNull()\n .default((defaultStatus ?? statuses[0]) as any);\n}","/**\n * Schema Module Exports\n */\n\n// Schema Helpers\nexport {\n id,\n uuid,\n timestamps,\n autoUpdateTimestamp,\n foreignKey,\n optionalForeignKey,\n auditFields,\n publishingFields,\n verificationTimestamp,\n softDelete,\n statusEnum,\n} from './helpers.js';","/**\n * Database Schema Helper\n *\n * Provides utilities for creating isolated PostgreSQL schemas for SPFN functions\n */\n\nimport { pgSchema } from 'drizzle-orm/pg-core';\n\n/**\n * Create a namespaced PostgreSQL schema for a function\n *\n * @param packageName - NPM package name (e.g., '@spfn/cms', 'spfn-auth')\n * @returns PostgreSQL schema object for creating tables\n *\n * @example\n * ```typescript\n * // @spfn/cms → spfn_cms schema\n * import { createFunctionSchema } from '@spfn/core/db';\n *\n * const schema = createFunctionSchema('@spfn/cms');\n *\n * export const labels = schema.table('labels', {\n * id: id(),\n * name: text('name').notNull(),\n * });\n * // Creates table: spfn_cms.labels\n * ```\n */\nexport function createFunctionSchema(packageName: string)\n{\n const schemaName = packageNameToSchema(packageName);\n return pgSchema(schemaName);\n}\n\n/**\n * Convert package name to PostgreSQL schema name\n *\n * @param packageName - NPM package name\n * @returns Schema name in PostgreSQL format\n *\n * @example\n * ```typescript\n * packageNameToSchema('@spfn/cms') // 'spfn_cms'\n * packageNameToSchema('@company/spfn-auth') // 'company_spfn_auth'\n * packageNameToSchema('spfn-storage') // 'spfn_storage'\n * ```\n */\nexport function packageNameToSchema(packageName: string): string\n{\n // Remove @ and replace / and - with _\n return packageName\n .replace('@', '')\n .replace('/', '_')\n .replace(/-/g, '_');\n}\n\n/**\n * Get recommended schema name for a package\n *\n * @param packageName - NPM package name\n * @returns Object with schema name and whether it's scoped\n *\n * @example\n * ```typescript\n * getSchemaInfo('@spfn/cms')\n * // { schemaName: 'spfn_cms', isScoped: true, scope: 'spfn' }\n *\n * getSchemaInfo('spfn-auth')\n * // { schemaName: 'spfn_auth', isScoped: false, scope: null }\n * ```\n */\nexport function getSchemaInfo(packageName: string)\n{\n const isScoped = packageName.startsWith('@');\n const scope = isScoped ? packageName.split('/')[0].substring(1) : null;\n const schemaName = packageNameToSchema(packageName);\n\n return {\n schemaName,\n isScoped,\n scope,\n };\n}","/**\n * AsyncLocalStorage-based Transaction Context\n *\n * Uses Node.js AsyncLocalStorage to propagate transactions throughout the async call chain.\n *\n * Features:\n * - AsyncLocalStorage-based context management\n * - Type-safe transaction propagation across async chains\n * - Transaction ID tracking for debugging and tracing\n * - Nested transaction detection and logging\n * - Transaction nesting level tracking\n */\nimport { AsyncLocalStorage } from 'async_hooks';\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { logger } from '../../logger'; // Assuming logger is accessible\n\n/**\n * Transaction database type\n * Uses Record<string, unknown> to accept any schema shape\n */\nexport type TransactionDB = PostgresJsDatabase<Record<string, unknown>>;\n\nconst txLogger = logger.child('transaction');\n\n/**\n * Transaction context stored in AsyncLocalStorage\n */\nexport type TransactionContext = {\n /** The actual Drizzle transaction object */\n tx: TransactionDB;\n /** Unique transaction ID for logging and tracing */\n txId: string; // Add txId to the context\n level: number;\n};\n\n/**\n * Global AsyncLocalStorage instance for transaction context\n */\nexport const asyncContext = new AsyncLocalStorage<TransactionContext>();\n\n/**\n * Get current transaction object and metadata from AsyncLocalStorage\n *\n * @returns TransactionContext if available, null otherwise\n */\nexport function getTransactionContext(): TransactionContext | null\n{\n return asyncContext.getStore() ?? null;\n}\n\n/**\n * Get current transaction from AsyncLocalStorage\n *\n * @returns Transaction if available, null otherwise\n */\nexport function getTransaction(): TransactionDB | null\n{\n const context = getTransactionContext();\n return context?.tx ?? null;\n}\n\n/**\n * Get current transaction ID from AsyncLocalStorage\n *\n * @returns Transaction ID if available, null otherwise\n */\nexport function getTransactionId(): string | null\n{\n const context = getTransactionContext();\n return context?.txId ?? null;\n}\n\n/**\n * Run a function within a transaction context\n *\n * The transaction will be available to all async operations within the callback\n * via getTransaction().\n *\n * @param tx - Drizzle transaction object\n * @param txId - Unique ID for the transaction\n * @param callback - Function to run within transaction context\n * @returns Result of the callback\n */\nexport function runWithTransaction<T>(\n tx: TransactionDB,\n txId: string, // Add txId parameter\n callback: () => Promise<T>\n): Promise<T>\n{\n const existingContext = getTransactionContext();\n\n // Determine the current transaction nesting level\n const newLevel = existingContext ? existingContext.level + 1 : 1;\n\n if (existingContext)\n {\n // Nested transaction detected. This means Drizzle will use a SAVEPOINT.\n txLogger.info('Nested transaction started (SAVEPOINT)', {\n outerTxId: existingContext.txId,\n innerTxId: txId,\n level: newLevel,\n });\n }\n else\n {\n // Root transaction\n txLogger.debug('Root transaction context set', { txId, level: newLevel });\n }\n\n // Store transaction, new ID, and the current nesting level\n return asyncContext.run({ tx, txId, level: newLevel }, callback);\n}","/**\n * Transactional Middleware\n *\n * Wraps route handlers in a database transaction.\n * Auto-commits on success, auto-rolls back on error.\n *\n * Features:\n * - Automatic transaction management (start/commit/rollback)\n * - Transaction propagation via AsyncLocalStorage\n * - Nested transaction detection and logging\n * - Hono Context error detection\n * - Transaction timeout with configurable threshold\n * - Execution time tracking and slow transaction warnings\n * - UUID-based transaction IDs for debugging\n * - PostgreSQL error conversion to custom errors\n */\nimport { randomUUID } from 'crypto';\nimport { logger } from '../../logger';\nimport { createMiddleware } from 'hono/factory';\nimport { getDatabase } from \"../manager\";\nimport { runWithTransaction, type TransactionDB } from './context.js';\nimport { TransactionError } from '../../errors';\nimport { fromPostgresError } from '../postgres-errors.js';\n\n/**\n * Transaction middleware options\n */\nexport interface TransactionalOptions\n{\n /**\n * Slow transaction warning threshold in milliseconds\n * @default 1000 (1 second)\n */\n slowThreshold?: number;\n\n /**\n * Enable transaction logging\n * @default true\n */\n enableLogging?: boolean;\n\n /**\n * Transaction timeout in milliseconds\n *\n * If transaction exceeds this duration, it will be aborted with TransactionError.\n *\n * @default 30000 (30 seconds) or TRANSACTION_TIMEOUT environment variable\n *\n * @example\n * ```typescript\n * // Default timeout (30s or TRANSACTION_TIMEOUT env var)\n * Transactional()\n *\n * // Custom timeout for specific route (60s)\n * Transactional({ timeout: 60000 })\n *\n * // Disable timeout\n * Transactional({ timeout: 0 })\n * ```\n */\n timeout?: number;\n}\n\n/**\n * Transaction middleware for Hono routes\n *\n * Automatically wraps route handlers in a database transaction.\n * Commits on success, rolls back on error.\n *\n * @example\n * ```typescript\n * // In your route file\n * export const middlewares = [Transactional()];\n *\n * export async function POST(c: RouteContext) {\n * // All DB operations run in a transaction\n * const [user] = await db.insert(users).values(body).returning();\n * await db.insert(profiles).values({ userId: user.id });\n * // Auto-commits on success\n * return c.json(user, 201);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With custom options\n * export const middlewares = [\n * Transactional({\n * slowThreshold: 2000, // Warn if transaction takes > 2s\n * enableLogging: false, // Disable logging\n * timeout: 60000, // 60 second timeout for long operations\n * })\n * ];\n * ```\n *\n * 🔄 Transaction behavior:\n * - Success: Auto-commit\n * - Error: Auto-rollback\n * - Detects context.error to trigger rollback\n *\n * 📊 Transaction logging:\n * - Auto-logs transaction start/commit/rollback\n * - Measures and records execution time\n * - Warns about slow transactions (default: > 1s)\n */\nexport function Transactional(options: TransactionalOptions = {})\n{\n // Get default timeout from environment variable (default: 30 seconds)\n const defaultTimeout = parseInt(process.env.TRANSACTION_TIMEOUT || '30000', 10);\n\n const {\n slowThreshold = 1000,\n enableLogging = true,\n timeout = defaultTimeout,\n } = options;\n\n const txLogger = logger.child('transaction');\n\n return createMiddleware(async (c, next) =>\n {\n // Generate transaction ID for debugging (using crypto.randomUUID for better uniqueness)\n const txId = `tx_${randomUUID()}`;\n const startTime = Date.now();\n const route = `${c.req.method} ${c.req.path}`;\n\n if (enableLogging)\n {\n txLogger.debug('Transaction started', { txId, route });\n }\n\n try\n {\n // Get write database instance\n const writeDb = getDatabase('write');\n if (!writeDb)\n {\n throw new TransactionError(\n 'Database not initialized. Cannot start transaction.',\n 500,\n { txId, route }\n );\n }\n\n // Create transaction promise\n const transactionPromise = writeDb.transaction(async (tx: TransactionDB) =>\n {\n // Store transaction in AsyncLocalStorage\n await runWithTransaction(tx, txId, async () =>\n {\n // Execute handler\n await next();\n\n // Detect if Hono caught an error and stored it in context.error\n // Context type doesn't officially define error property, so we extend it\n type ContextWithError = typeof c & { error?: Error };\n const contextWithError = c as ContextWithError;\n if (contextWithError.error)\n {\n // Throw to rollback transaction\n throw contextWithError.error;\n }\n\n // Auto-commit on success (handled by Drizzle)\n });\n });\n\n // Apply timeout if enabled (timeout > 0)\n if (timeout > 0)\n {\n const timeoutPromise = new Promise<never>((_, reject) =>\n {\n setTimeout(() =>\n {\n reject(\n new TransactionError(\n `Transaction timeout after ${timeout}ms`,\n 500,\n {\n txId,\n route,\n timeout: `${timeout}ms`,\n }\n )\n );\n }, timeout);\n });\n\n // Race between transaction and timeout\n await Promise.race([transactionPromise, timeoutPromise]);\n }\n else\n {\n // No timeout - just await transaction\n await transactionPromise;\n }\n\n // Transaction successful (committed)\n const duration = Date.now() - startTime;\n\n if (enableLogging)\n {\n if (duration >= slowThreshold)\n {\n txLogger.warn('Slow transaction committed', {\n txId,\n route,\n duration: `${duration}ms`,\n threshold: `${slowThreshold}ms`,\n });\n }\n else\n {\n txLogger.debug('Transaction committed', {\n txId,\n route,\n duration: `${duration}ms`,\n });\n }\n }\n }\n catch (error)\n {\n // Transaction failed (rolled back)\n const duration = Date.now() - startTime;\n\n // Convert PostgreSQL error to custom error (unless it's already TransactionError)\n const customError = error instanceof TransactionError\n ? error\n : fromPostgresError(error);\n\n if (enableLogging)\n {\n txLogger.error('Transaction rolled back', {\n txId,\n route,\n duration: `${duration}ms`,\n error: customError.message,\n errorType: customError.name,\n });\n }\n\n // Re-throw for Hono's error handler\n throw customError;\n }\n });\n}","/**\n * Transaction Module\n *\n * Database transaction management with AsyncLocalStorage-based propagation\n */\n\n// AsyncLocalStorage utilities\nexport { getTransaction, runWithTransaction, getTransactionContext } from './context.js';\nexport type { TransactionContext, TransactionDB } from './context.js';\n\n// Transaction middleware\nexport { Transactional } from './middleware.js';\nexport type { TransactionalOptions } from './middleware.js';","/**\n * Database Helper Functions\n *\n * Type-safe helper functions for common database operations.\n * Automatically handles:\n * - Transaction context detection\n * - Read/Write database separation\n * - Type inference from table schema\n *\n * @example\n * ```typescript\n * // Simple object-based where\n * const user = await findOne(users, { id: 1 });\n * const labels = await findMany(cmsLabels, { section: 'hero' });\n *\n * // Complex SQL-based where\n * const user = await findOne(users, and(eq(users.id, 1), gt(users.age, 18)));\n * const labels = await findMany(cmsLabels, {\n * where: or(like(cmsLabels.key, 'hero.%'), eq(cmsLabels.section, 'footer')),\n * limit: 10\n * });\n * ```\n */\n\nimport type { SQL } from 'drizzle-orm';\nimport { eq, and } from 'drizzle-orm';\nimport type { PgTable, PgColumn } from 'drizzle-orm/pg-core';\nimport { getDatabase } from './manager';\n\n/**\n * Infer SELECT model from PgTable\n */\ntype InferSelectModel<T extends PgTable> = T['$inferSelect'];\n\n/**\n * Infer INSERT model from PgTable\n */\ntype InferInsertModel<T extends PgTable> = T['$inferInsert'];\n\n/**\n * Object-based where condition (AND only, equality only)\n */\ntype WhereObject<T> = {\n [K in keyof T]?: T[K];\n};\n\n/**\n * Check if value is SQL wrapper\n */\nfunction isSQLWrapper(value: any): value is SQL\n{\n return value && typeof value === 'object' && 'queryChunks' in value;\n}\n\n/**\n * Build SQL WHERE clause from object\n */\nfunction buildWhereFromObject<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>>\n): SQL | undefined\n{\n const entries = Object.entries(where).filter(([_, value]) => value !== undefined);\n if (entries.length === 0) return undefined;\n\n const conditions = entries.map(([key, value]) =>\n eq((table as any)[key], value)\n );\n\n return conditions.length === 1 ? conditions[0] : and(...conditions);\n}\n\n/**\n * Find a single record\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @returns Single record or null\n *\n * @example\n * ```typescript\n * // Object-based\n * const user = await findOne(users, { id: 1 });\n * const label = await findOne(cmsLabels, { key: 'hero.title', section: 'hero' });\n *\n * // SQL-based\n * const user = await findOne(users, and(eq(users.id, 1), gt(users.age, 18)));\n * ```\n */\nexport async function findOne<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>>\n): Promise<InferSelectModel<T> | null>;\n\nexport async function findOne<T extends PgTable>(\n table: T,\n where: SQL | undefined\n): Promise<InferSelectModel<T> | null>;\n\nexport async function findOne<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined\n): Promise<InferSelectModel<T> | null>\n{\n const db = getDatabase('read');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('findOne requires at least one where condition');\n }\n\n const results = await db.select().from(table as PgTable).where(whereClause).limit(1);\n return (results[0] as InferSelectModel<T>) ?? null;\n}\n\n/**\n * Find multiple records\n *\n * @param table - Drizzle table schema\n * @param options - Query options (where, orderBy, limit, offset)\n * @returns Array of records\n *\n * @example\n * ```typescript\n * // Simple object where\n * const labels = await findMany(cmsLabels, { section: 'hero' });\n *\n * // With options\n * const labels = await findMany(cmsLabels, {\n * where: { section: 'hero' },\n * orderBy: desc(cmsLabels.updatedAt),\n * limit: 10,\n * offset: 0\n * });\n *\n * // Complex SQL where\n * const labels = await findMany(cmsLabels, {\n * where: and(\n * like(cmsLabels.key, 'hero.%'),\n * eq(cmsLabels.section, 'hero')\n * ),\n * limit: 10\n * });\n * ```\n */\nexport async function findMany<T extends PgTable>(\n table: T,\n options?: {\n where?: WhereObject<InferSelectModel<T>> | SQL | undefined;\n orderBy?: SQL | SQL[];\n limit?: number;\n offset?: number;\n }\n): Promise<InferSelectModel<T>[]>\n{\n const db = getDatabase('read');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n let query = db.select().from(table as PgTable);\n\n // Apply where\n if (options?.where)\n {\n const whereClause = isSQLWrapper(options.where)\n ? options.where\n : options.where ? buildWhereFromObject(table, options.where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (whereClause)\n {\n query = query.where(whereClause) as any;\n }\n }\n\n // Apply orderBy\n if (options?.orderBy)\n {\n const orderByArray = Array.isArray(options.orderBy) ? options.orderBy : [options.orderBy];\n query = query.orderBy(...orderByArray) as any;\n }\n\n // Apply limit\n if (options?.limit)\n {\n query = query.limit(options.limit) as any;\n }\n\n // Apply offset\n if (options?.offset)\n {\n query = query.offset(options.offset) as any;\n }\n\n return query as Promise<InferSelectModel<T>[]>;\n}\n\n/**\n * Create a new record\n *\n * @param table - Drizzle table schema\n * @param data - Insert data\n * @returns Created record\n *\n * @example\n * ```typescript\n * const user = await create(users, {\n * email: 'test@example.com',\n * name: 'Test User'\n * });\n * ```\n */\nexport async function create<T extends PgTable>(\n table: T,\n data: InferInsertModel<T>\n): Promise<InferSelectModel<T>>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const [result] = await db.insert(table).values(data).returning();\n return result as InferSelectModel<T>;\n}\n\n/**\n * Create multiple records\n *\n * @param table - Drizzle table schema\n * @param data - Array of insert data\n * @returns Array of created records\n *\n * @example\n * ```typescript\n * const users = await createMany(users, [\n * { email: 'user1@example.com', name: 'User 1' },\n * { email: 'user2@example.com', name: 'User 2' }\n * ]);\n * ```\n */\nexport async function createMany<T extends PgTable>(\n table: T,\n data: InferInsertModel<T>[]\n): Promise<InferSelectModel<T>[]>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const results = await db.insert(table).values(data).returning();\n return results as InferSelectModel<T>[];\n}\n\n/**\n * Upsert a record (INSERT or UPDATE on conflict)\n *\n * @param table - Drizzle table schema\n * @param data - Insert data\n * @param options - Conflict resolution options\n * @returns Upserted record\n *\n * @example\n * ```typescript\n * // Basic upsert\n * const cache = await upsert(cmsPublishedCache, {\n * section: 'home',\n * locale: 'ko',\n * content: {...}\n * }, {\n * target: [cmsPublishedCache.section, cmsPublishedCache.locale],\n * set: {\n * content: data.content,\n * updatedAt: new Date()\n * }\n * });\n *\n * // With SQL expression\n * const cache = await upsert(cmsPublishedCache, data, {\n * target: [cmsPublishedCache.section, cmsPublishedCache.locale],\n * set: {\n * content: data.content,\n * version: sql`${cmsPublishedCache.version} + 1`\n * }\n * });\n * ```\n */\nexport async function upsert<T extends PgTable>(\n table: T,\n data: InferInsertModel<T>,\n options: {\n target: PgColumn[];\n set?: Partial<InferInsertModel<T>> | Record<string, SQL | any>;\n }\n): Promise<InferSelectModel<T>>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const [result] = await db\n .insert(table)\n .values(data)\n .onConflictDoUpdate({\n target: options.target,\n set: options.set || data,\n })\n .returning();\n\n return result as InferSelectModel<T>;\n}\n\n/**\n * Update a single record\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @param data - Update data\n * @returns Updated record or null\n *\n * @example\n * ```typescript\n * // Object-based where\n * const user = await updateOne(users, { id: 1 }, { name: 'Updated Name' });\n *\n * // SQL-based where\n * const user = await updateOne(users, eq(users.id, 1), { name: 'Updated Name' });\n * ```\n */\nexport async function updateOne<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined,\n data: Partial<InferInsertModel<T>>\n): Promise<InferSelectModel<T> | null>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('updateOne requires at least one where condition');\n }\n\n const [result] = await db.update(table).set(data).where(whereClause).returning();\n return (result as InferSelectModel<T>) ?? null;\n}\n\n/**\n * Update multiple records\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @param data - Update data\n * @returns Array of updated records\n *\n * @example\n * ```typescript\n * const users = await updateMany(users,\n * { role: 'user' },\n * { verified: true }\n * );\n * ```\n */\nexport async function updateMany<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined,\n data: Partial<InferInsertModel<T>>\n): Promise<InferSelectModel<T>[]>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('updateMany requires at least one where condition');\n }\n\n const results = await db.update(table).set(data).where(whereClause).returning();\n return results as InferSelectModel<T>[];\n}\n\n/**\n * Delete a single record\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @returns Deleted record or null\n *\n * @example\n * ```typescript\n * // Object-based where\n * const user = await deleteOne(users, { id: 1 });\n *\n * // SQL-based where\n * const user = await deleteOne(users, eq(users.id, 1));\n * ```\n */\nexport async function deleteOne<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined\n): Promise<InferSelectModel<T> | null>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('deleteOne requires at least one where condition');\n }\n\n const [result] = await db.delete(table).where(whereClause).returning();\n return (result as InferSelectModel<T>) ?? null;\n}\n\n/**\n * Delete multiple records\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @returns Array of deleted records\n *\n * @example\n * ```typescript\n * const users = await deleteMany(users, { verified: false });\n * ```\n */\nexport async function deleteMany<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined\n): Promise<InferSelectModel<T>[]>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('deleteMany requires at least one where condition');\n }\n\n const results = await db.delete(table).where(whereClause).returning();\n return results as InferSelectModel<T>[];\n}\n\n/**\n * Count records\n *\n * @param table - Drizzle table schema\n * @param where - Optional object or SQL condition\n * @returns Number of records\n *\n * @example\n * ```typescript\n * const total = await count(users);\n * const activeUsers = await count(users, { active: true });\n * const adults = await count(users, gt(users.age, 18));\n * ```\n */\nexport async function count<T extends PgTable>(\n table: T,\n where?: WhereObject<InferSelectModel<T>> | SQL | undefined\n): Promise<number>\n{\n const db = getDatabase('read');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n let query = db.select().from(table as PgTable);\n\n if (where)\n {\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (whereClause)\n {\n query = query.where(whereClause) as any;\n }\n }\n\n const results = await query;\n return results.length;\n}\n","/**\n * Database Module Exports\n *\n * Entry point for DB module (Pure re-export only)\n */\n\n// Manager (DB Instance, Factory, Connection)\nexport {\n createDatabaseFromEnv,\n initDatabase,\n getDatabase,\n setDatabase,\n closeDatabase,\n getDatabaseInfo,\n createDatabaseConnection,\n checkConnection,\n} from './manager';\n\nexport type {\n DatabaseClients,\n PoolConfig,\n RetryConfig,\n} from './manager';\n\n// Drizzle Config Generator\nexport { getDrizzleConfig, detectDialect, generateDrizzleConfigFile } from './manager/config-generator.js';\nexport type { DrizzleConfigOptions } from './manager/config-generator.js';\n\n// Schema Helpers\nexport { id, timestamps, foreignKey, optionalForeignKey } from './schema';\nexport { createFunctionSchema, packageNameToSchema, getSchemaInfo } from './schema-helper.js';\n\n// Transaction\nexport { Transactional, getTransaction, runWithTransaction } from './transaction';\nexport type { TransactionContext, TransactionDB, TransactionalOptions } from './transaction';\n\n// PostgreSQL Error Utilities\nexport { fromPostgresError } from './postgres-errors.js';\n\n// Helper Functions\nexport {\n findOne,\n findMany,\n create,\n createMany,\n upsert,\n updateOne,\n updateMany,\n deleteOne,\n deleteMany,\n count,\n} from './helpers.js';","/**\n * Cache factory with automatic environment variable detection\n * Supports Valkey and Redis with multiple deployment patterns\n *\n * Valkey is a Redis fork (7.2.4 base) with 100% protocol compatibility\n * https://valkey.io\n */\n\nimport type { Redis, Cluster, RedisOptions, ClusterOptions } from 'ioredis';\nimport { logger } from '../logger';\n\nconst cacheLogger = logger.child('cache');\n\nexport interface CacheClients {\n /** Primary cache for writes (or both read/write if no replica) */\n write?: Redis | Cluster;\n /** Replica cache for reads (optional, falls back to write) */\n read?: Redis | Cluster;\n}\n\n/**\n * Check if any cache configuration exists in environment\n *\n * Priority:\n * 1. VALKEY_* / CACHE_* (modern)\n * 2. REDIS_* (backward compatibility)\n */\nfunction hasCacheConfig(): boolean\n{\n return !!(\n // Modern (Valkey/Cache)\n process.env.VALKEY_URL ||\n process.env.CACHE_URL ||\n process.env.VALKEY_WRITE_URL ||\n process.env.VALKEY_READ_URL ||\n process.env.CACHE_WRITE_URL ||\n process.env.CACHE_READ_URL ||\n process.env.VALKEY_SENTINEL_HOSTS ||\n process.env.VALKEY_CLUSTER_NODES ||\n // Legacy (Redis - backward compatibility)\n process.env.REDIS_URL ||\n process.env.REDIS_WRITE_URL ||\n process.env.REDIS_READ_URL ||\n process.env.REDIS_SENTINEL_HOSTS ||\n process.env.REDIS_CLUSTER_NODES\n );\n}\n\n/**\n * Get environment variable with priority fallback\n * Valkey/Cache takes precedence over Redis (legacy)\n */\nfunction getEnv(valkeyKey: string, cacheKey: string, redisKey: string): string | undefined\n{\n return process.env[valkeyKey] || process.env[cacheKey] || process.env[redisKey];\n}\n\n/**\n * Create cache client with TLS support\n * Supports both valkey:// and redis:// protocols\n */\nfunction createClient(\n RedisClient: new (url: string, options?: RedisOptions) => Redis,\n url: string\n): Redis\n{\n const options: RedisOptions = {};\n\n // TLS support for secure connections\n if (url.startsWith('rediss://') || url.startsWith('valkeys://'))\n {\n const rejectUnauthorized = getEnv(\n 'VALKEY_TLS_REJECT_UNAUTHORIZED',\n 'CACHE_TLS_REJECT_UNAUTHORIZED',\n 'REDIS_TLS_REJECT_UNAUTHORIZED'\n );\n\n options.tls = {\n rejectUnauthorized: rejectUnauthorized !== 'false',\n };\n }\n\n return new RedisClient(url, options);\n}\n\n/**\n * Create cache client(s) from environment variables\n *\n * Supported patterns (priority order):\n * 1. Single instance: VALKEY_URL or CACHE_URL or REDIS_URL\n * 2. Master-Replica: VALKEY_WRITE_URL + VALKEY_READ_URL (or CACHE_*, REDIS_*)\n * 3. Sentinel: VALKEY_SENTINEL_HOSTS + VALKEY_MASTER_NAME (or REDIS_*)\n * 4. Cluster: VALKEY_CLUSTER_NODES (or REDIS_*)\n *\n * @returns Cache client(s) or undefined if no configuration found\n *\n * @example\n * ```bash\n * # Single (most common)\n * VALKEY_URL=valkey://localhost:6379\n * CACHE_URL=redis://localhost:6379\n *\n * # Legacy (still supported)\n * REDIS_URL=redis://localhost:6379\n * REDIS_URL=rediss://secure.redis.com:6380 # TLS\n *\n * # Master-Replica\n * VALKEY_WRITE_URL=valkey://master:6379\n * VALKEY_READ_URL=valkey://replica:6379\n *\n * # Sentinel\n * VALKEY_SENTINEL_HOSTS=sentinel1:26379,sentinel2:26379\n * VALKEY_MASTER_NAME=mymaster\n * VALKEY_PASSWORD=secret\n *\n * # Cluster\n * VALKEY_CLUSTER_NODES=node1:6379,node2:6379,node3:6379\n * VALKEY_PASSWORD=secret\n * ```\n */\nexport async function createCacheFromEnv(): Promise<CacheClients>\n{\n // Quick exit if no cache config\n if (!hasCacheConfig())\n {\n cacheLogger.info('No cache configuration found - running without cache');\n return { write: undefined, read: undefined };\n }\n\n try\n {\n // Dynamic import to avoid bundling if not used\n const ioredis = await import('ioredis');\n const RedisClient = ioredis.default;\n\n // Get URLs with priority fallback\n const singleUrl = getEnv('VALKEY_URL', 'CACHE_URL', 'REDIS_URL');\n const writeUrl = getEnv('VALKEY_WRITE_URL', 'CACHE_WRITE_URL', 'REDIS_WRITE_URL');\n const readUrl = getEnv('VALKEY_READ_URL', 'CACHE_READ_URL', 'REDIS_READ_URL');\n const clusterNodes = getEnv('VALKEY_CLUSTER_NODES', 'CACHE_CLUSTER_NODES', 'REDIS_CLUSTER_NODES');\n const sentinelHosts = getEnv('VALKEY_SENTINEL_HOSTS', 'CACHE_SENTINEL_HOSTS', 'REDIS_SENTINEL_HOSTS');\n const masterName = getEnv('VALKEY_MASTER_NAME', 'CACHE_MASTER_NAME', 'REDIS_MASTER_NAME');\n const password = getEnv('VALKEY_PASSWORD', 'CACHE_PASSWORD', 'REDIS_PASSWORD');\n\n // 1. Single instance (most common - highest priority)\n if (singleUrl && !writeUrl && !readUrl && !clusterNodes)\n {\n const client = createClient(RedisClient, singleUrl);\n cacheLogger.debug('Created single cache instance', { url: singleUrl.replace(/:[^:@]+@/, ':***@') });\n return { write: client, read: client };\n }\n\n // 2. Master-Replica pattern (both URLs required)\n if (writeUrl && readUrl)\n {\n const write = createClient(RedisClient, writeUrl);\n const read = createClient(RedisClient, readUrl);\n cacheLogger.debug('Created master-replica cache instances');\n return { write, read };\n }\n\n // 3. Sentinel pattern\n if (sentinelHosts && masterName)\n {\n const sentinels = sentinelHosts.split(',').map((host) =>\n {\n const [hostname, port] = host.trim().split(':');\n return { host: hostname, port: Number(port) || 26379 };\n });\n\n const options: RedisOptions = {\n sentinels,\n name: masterName,\n password,\n };\n\n const client = new RedisClient(options);\n cacheLogger.debug('Created sentinel cache instance', { masterName, sentinels: sentinels.length });\n return { write: client, read: client };\n }\n\n // 4. Cluster pattern\n if (clusterNodes)\n {\n const nodes = clusterNodes.split(',').map((node) =>\n {\n const [host, port] = node.trim().split(':');\n return { host, port: Number(port) || 6379 };\n });\n\n const clusterOptions: ClusterOptions = {\n redisOptions: {\n password,\n },\n };\n\n const cluster = new RedisClient.Cluster(nodes, clusterOptions);\n cacheLogger.debug('Created cluster cache instance', { nodes: nodes.length });\n return { write: cluster, read: cluster };\n }\n\n // 5. Fallback: Single URL with other configs present\n if (singleUrl)\n {\n const client = createClient(RedisClient, singleUrl);\n cacheLogger.debug('Created cache instance (fallback)', { url: singleUrl.replace(/:[^:@]+@/, ':***@') });\n return { write: client, read: client };\n }\n\n // No valid configuration\n cacheLogger.info('No valid cache configuration found - running without cache');\n return { write: undefined, read: undefined };\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n // Check if it's a missing dependency error\n if (error.message.includes('Cannot find module'))\n {\n cacheLogger.warn(\n 'Cache client library not installed',\n error,\n {\n suggestion: 'Install ioredis to enable cache: pnpm install ioredis',\n mode: 'disabled'\n }\n );\n }\n else\n {\n cacheLogger.warn(\n 'Failed to create cache client',\n error,\n { mode: 'disabled' }\n );\n }\n }\n else\n {\n cacheLogger.warn(\n 'Failed to create cache client',\n { error: String(error), mode: 'disabled' }\n );\n }\n return { write: undefined, read: undefined };\n }\n}\n\n/**\n * Create single cache client (backward compatibility)\n * Only returns write instance\n */\nexport async function createSingleCacheFromEnv(): Promise<Redis | Cluster | undefined>\n{\n const { write } = await createCacheFromEnv();\n return write;\n}","/**\n * Global cache instance manager\n * Provides singleton access to cache (Valkey/Redis) across all modules\n * Supports Master-Replica pattern with separate read/write instances\n *\n * When cache is unavailable, falls back to disabled mode gracefully\n */\n\nimport type { Redis, Cluster } from 'ioredis';\n\nimport { createCacheFromEnv } from './cache-factory.js';\nimport { logger } from '../logger';\n\nconst cacheLogger = logger.child('cache');\n\nlet writeInstance: Redis | Cluster | undefined;\nlet readInstance: Redis | Cluster | undefined;\nlet isDisabled = false;\n\n/**\n * Get global cache write instance\n *\n * @returns Cache write instance or undefined if disabled/not initialized\n *\n * @example\n * ```typescript\n * import { getCache } from '@spfn/core/cache';\n *\n * const cache = getCache();\n * if (cache) {\n * await cache.set('key', 'value');\n * } else {\n * // Cache disabled - handle gracefully\n * console.log('Cache unavailable, skipping...');\n * }\n * ```\n */\nexport function getCache(): Redis | Cluster | undefined\n{\n return writeInstance;\n}\n\n/**\n * Get global cache read instance (falls back to write if no replica)\n *\n * @returns Cache read instance or write instance as fallback, undefined if disabled\n *\n * @example\n * ```typescript\n * import { getCacheRead } from '@spfn/core/cache';\n *\n * const cache = getCacheRead();\n * if (cache) {\n * const value = await cache.get('key');\n * }\n * ```\n */\nexport function getCacheRead(): Redis | Cluster | undefined\n{\n return readInstance ?? writeInstance;\n}\n\n/**\n * Check if cache is disabled (connection failed or not configured)\n *\n * @example\n * ```typescript\n * import { isCacheDisabled } from '@spfn/core/cache';\n *\n * if (isCacheDisabled()) {\n * // Use alternative strategy (e.g., in-memory cache, database)\n * return await fetchFromDatabase();\n * }\n * ```\n */\nexport function isCacheDisabled(): boolean\n{\n return isDisabled;\n}\n\n/**\n * Set global cache instances (for testing or manual configuration)\n *\n * @param write - Cache write instance\n * @param read - Cache read instance (optional, defaults to write)\n *\n * @example\n * ```typescript\n * import { setCache } from '@spfn/core/cache';\n * import Redis from 'ioredis';\n *\n * const write = new Redis('redis://master:6379');\n * const read = new Redis('redis://replica:6379');\n * setCache(write, read);\n * ```\n */\nexport function setCache(\n write: Redis | Cluster | undefined,\n read?: Redis | Cluster | undefined\n): void\n{\n writeInstance = write;\n readInstance = read ?? write;\n isDisabled = !write;\n}\n\n/**\n * Initialize cache from environment variables\n * Automatically called by startServer()\n *\n * Supported environment variables (priority order):\n * - VALKEY_URL / CACHE_URL (single instance)\n * - VALKEY_WRITE_URL + VALKEY_READ_URL (master-replica)\n * - VALKEY_SENTINEL_HOSTS + VALKEY_MASTER_NAME (sentinel)\n * - VALKEY_CLUSTER_NODES (cluster)\n * - VALKEY_TLS_REJECT_UNAUTHORIZED (TLS config)\n * - Legacy: REDIS_* (backward compatibility)\n *\n * @returns Object with write and read instances, or undefined if disabled\n *\n * @example\n * ```typescript\n * import { initCache } from '@spfn/core/cache';\n *\n * // Manual initialization (not needed if using startServer)\n * const { write, read, disabled } = await initCache();\n * if (!disabled) {\n * console.log('Cache available');\n * }\n * ```\n */\nexport async function initCache(): Promise<{\n write?: Redis | Cluster;\n read?: Redis | Cluster;\n disabled: boolean;\n}>\n{\n // Already initialized\n if (writeInstance)\n {\n return { write: writeInstance, read: readInstance, disabled: isDisabled };\n }\n\n // Auto-detect from environment\n const { write, read } = await createCacheFromEnv();\n\n if (write)\n {\n try\n {\n // Test connection\n await write.ping();\n\n // Test read instance if different\n if (read && read !== write)\n {\n await read.ping();\n }\n\n writeInstance = write;\n readInstance = read;\n isDisabled = false;\n\n const hasReplica = read && read !== write;\n cacheLogger.info(\n hasReplica\n ? 'Cache connected (Master-Replica)'\n : 'Cache connected',\n { mode: 'enabled' }\n );\n\n return { write: writeInstance, read: readInstance, disabled: false };\n }\n catch (error)\n {\n cacheLogger.error(\n 'Cache connection failed - running in disabled mode',\n error instanceof Error ? error : new Error(String(error)),\n { mode: 'disabled' }\n );\n\n // Clean up failed connections\n try\n {\n await write.quit();\n if (read && read !== write)\n {\n await read.quit();\n }\n }\n catch\n {\n // Ignore cleanup errors\n }\n\n isDisabled = true;\n return { write: undefined, read: undefined, disabled: true };\n }\n }\n\n // No configuration or library not installed\n isDisabled = true;\n cacheLogger.info('Cache disabled - no configuration or library not installed', { mode: 'disabled' });\n return { write: undefined, read: undefined, disabled: true };\n}\n\n/**\n * Close all cache connections and cleanup\n *\n * @example\n * ```typescript\n * import { closeCache } from '@spfn/core/cache';\n *\n * // During graceful shutdown\n * await closeCache();\n * ```\n */\nexport async function closeCache(): Promise<void>\n{\n if (isDisabled)\n {\n cacheLogger.debug('Cache already disabled, nothing to close');\n return;\n }\n\n const closePromises: Promise<unknown>[] = [];\n\n if (writeInstance)\n {\n closePromises.push(\n writeInstance.quit().catch((err: Error) =>\n {\n cacheLogger.error('Error closing cache write instance', err);\n })\n );\n }\n\n if (readInstance && readInstance !== writeInstance)\n {\n closePromises.push(\n readInstance.quit().catch((err: Error) =>\n {\n cacheLogger.error('Error closing cache read instance', err);\n })\n );\n }\n\n await Promise.all(closePromises);\n\n writeInstance = undefined;\n readInstance = undefined;\n isDisabled = true;\n\n cacheLogger.info('Cache connections closed', { mode: 'disabled' });\n}\n\n/**\n * Get cache connection info (for debugging)\n *\n * @example\n * ```typescript\n * import { getCacheInfo } from '@spfn/core/cache';\n *\n * const info = getCacheInfo();\n * console.log(info);\n * // {\n * // hasWrite: true,\n * // hasRead: true,\n * // isReplica: true,\n * // disabled: false\n * // }\n * ```\n */\nexport function getCacheInfo(): {\n hasWrite: boolean;\n hasRead: boolean;\n isReplica: boolean;\n disabled: boolean;\n}\n{\n return {\n hasWrite: !!writeInstance,\n hasRead: !!readInstance,\n isReplica: !!(readInstance && readInstance !== writeInstance),\n disabled: isDisabled,\n };\n}\n\n// Legacy exports (backward compatibility)\n/** @deprecated Use getCache() instead */\nexport const getRedis = getCache;\n\n/** @deprecated Use getCacheRead() instead */\nexport const getRedisRead = getCacheRead;\n\n/** @deprecated Use setCache() instead */\nexport const setRedis = setCache;\n\n/** @deprecated Use initCache() instead */\nexport const initRedis = initCache;\n\n/** @deprecated Use closeCache() instead */\nexport const closeRedis = closeCache;\n\n/** @deprecated Use getCacheInfo() instead */\nexport const getRedisInfo = getCacheInfo;","/**\n * Cache infrastructure (Valkey/Redis)\n * Provides singleton cache instance management for all SPFN modules\n * Supports Master-Replica pattern with separate read/write instances\n *\n * Valkey is a Redis fork (7.2.4 base) with 100% protocol compatibility\n * https://valkey.io\n */\n\n// Modern exports (cache)\nexport {\n createCacheFromEnv,\n createSingleCacheFromEnv,\n} from './cache-factory.js';\n\nexport {\n getCache,\n getCacheRead,\n isCacheDisabled,\n setCache,\n initCache,\n closeCache,\n getCacheInfo,\n} from './cache-manager.js';\n\nexport type { CacheClients } from './cache-factory.js';\n\n// Legacy exports (backward compatibility)\n// Manager functions - re-exported from cache-manager.js\nexport {\n getRedis,\n getRedisRead,\n setRedis,\n initRedis,\n closeRedis,\n getRedisInfo,\n} from './cache-manager.js';\n\n// Factory functions - re-exported from cache-factory.js\nexport {\n createCacheFromEnv as createRedisFromEnv,\n createSingleCacheFromEnv as createSingleRedisFromEnv,\n} from './cache-factory.js';\n\nexport type { CacheClients as RedisClients } from './cache-factory.js';","import { readdir, stat } from 'fs/promises';\nimport { join, relative } from 'path';\nimport { Hono } from 'hono';\nimport type { MiddlewareHandler } from 'hono';\nimport { logger } from '../logger';\n\nconst routeLogger = logger.child('route');\n\ndeclare module 'hono'\n{\n interface ContextVariableMap\n {\n _skipMiddlewares?: string[];\n }\n}\n\n/**\n * AutoRouteLoader: Simplified File-based Routing System\n *\n * Features:\n * - Auto-discovery: Scans routes directory and auto-registers\n * - Dynamic routes: [id] → :id, [...slug] → *\n * - Statistics: Route registration stats for dashboard\n * - Grouping: Natural grouping by directory structure\n */\n\nexport type RouteInfo = {\n path: string;\n file: string;\n meta?: {\n description?: string;\n tags?: string[];\n auth?: boolean;\n [key: string]: unknown;\n };\n priority: number;\n};\n\nexport type RouteStats = {\n total: number;\n byPriority: {\n static: number;\n dynamic: number;\n catchAll: number;\n };\n byTag: Record<string, number>;\n routes: RouteInfo[];\n};\n\ntype RouteModule = {\n default: Hono & {\n _contractMetas?: Map<string, any>;\n };\n meta?: {\n description?: string;\n tags?: string[];\n skipMiddlewares?: string[];\n [key: string]: unknown;\n };\n};\n\nexport class AutoRouteLoader\n{\n private routes: RouteInfo[] = [];\n private readonly debug: boolean;\n private readonly middlewares: Array<{ name: string; handler: MiddlewareHandler }>;\n\n constructor(\n private routesDir: string,\n debug = false,\n middlewares: Array<{ name: string; handler: MiddlewareHandler }> = []\n ) {\n this.debug = debug;\n this.middlewares = middlewares;\n }\n\n async load(app: Hono): Promise<RouteStats>\n {\n const startTime = Date.now();\n\n const files = await this.scanFiles(this.routesDir);\n\n if (files.length === 0)\n {\n routeLogger.warn('No route files found');\n return this.getStats();\n }\n\n let successCount = 0;\n let failureCount = 0;\n\n for (const file of files)\n {\n const success = await this.loadRoute(app, file);\n if (success)\n {\n successCount++;\n }\n else\n {\n failureCount++;\n }\n }\n\n const elapsed = Date.now() - startTime;\n const stats = this.getStats();\n\n if (this.debug)\n {\n this.logStats(stats, elapsed);\n }\n\n if (failureCount > 0)\n {\n routeLogger.warn('Some routes failed to load', { failureCount });\n }\n\n return stats;\n }\n\n /**\n * Load routes from an external directory (e.g., from SPFN function packages)\n * Reads package.json spfn.prefix and mounts routes under that prefix\n *\n * @param app - Hono app instance\n * @param routesDir - Directory containing route handlers\n * @param packageName - Name of the package (for logging)\n * @param prefix - Optional prefix to mount routes under (from package.json spfn.prefix)\n * @returns Route statistics\n */\n async loadExternalRoutes(app: Hono, routesDir: string, packageName: string, prefix?: string): Promise<RouteStats>\n {\n const startTime = Date.now();\n const tempRoutesDir = this.routesDir;\n this.routesDir = routesDir;\n\n const files = await this.scanFiles(routesDir);\n\n if (files.length === 0)\n {\n routeLogger.warn('No route files found', { dir: routesDir, package: packageName });\n this.routesDir = tempRoutesDir;\n return this.getStats();\n }\n\n let successCount = 0;\n let failureCount = 0;\n\n // Load routes with prefix if provided (from package.json spfn.prefix)\n for (const file of files)\n {\n const success = await this.loadRoute(app, file, prefix);\n if (success)\n {\n successCount++;\n }\n else\n {\n failureCount++;\n }\n }\n\n const elapsed = Date.now() - startTime;\n\n if (this.debug)\n {\n routeLogger.info('External routes loaded', {\n package: packageName,\n prefix: prefix || '/',\n total: successCount,\n failed: failureCount,\n elapsed: `${elapsed}ms`,\n });\n }\n\n this.routesDir = tempRoutesDir;\n return this.getStats();\n }\n\n getStats(): RouteStats\n {\n const stats: RouteStats = {\n total: this.routes.length,\n byPriority: { static: 0, dynamic: 0, catchAll: 0 },\n byTag: {},\n routes: this.routes,\n };\n\n for (const route of this.routes)\n {\n if (route.priority === 1) stats.byPriority.static++;\n else if (route.priority === 2) stats.byPriority.dynamic++;\n else if (route.priority === 3) stats.byPriority.catchAll++;\n\n if (route.meta?.tags)\n {\n for (const tag of route.meta.tags)\n {\n stats.byTag[tag] = (stats.byTag[tag] || 0) + 1;\n }\n }\n }\n\n return stats;\n }\n\n private async scanFiles(dir: string, files: string[] = []): Promise<string[]>\n {\n const entries = await readdir(dir);\n\n for (const entry of entries)\n {\n const fullPath = join(dir, entry);\n const fileStat = await stat(fullPath);\n\n if (fileStat.isDirectory())\n {\n await this.scanFiles(fullPath, files);\n }\n else if (this.isValidRouteFile(entry))\n {\n files.push(fullPath);\n }\n }\n\n return files;\n }\n\n private isValidRouteFile(fileName: string): boolean\n {\n // Strict convention: Only index.ts, index.js, or index.mjs files are route handlers\n // This prevents accidental loading of utility files, helpers, types, etc.\n return fileName === 'index.ts' || fileName === 'index.js' || fileName === 'index.mjs';\n }\n\n private async loadRoute(app: Hono, absolutePath: string, prefix?: string): Promise<boolean>\n {\n const relativePath = relative(this.routesDir, absolutePath);\n\n try\n {\n const module = await import(absolutePath) as RouteModule;\n\n if (!this.validateModule(module, relativePath))\n {\n return false;\n }\n\n // Contract-based routing: Use contract paths directly\n const hasContractMetas = module.default._contractMetas && module.default._contractMetas.size > 0;\n\n if (!hasContractMetas)\n {\n routeLogger.error('Route must use contract-based routing', {\n file: relativePath,\n hint: 'Export contracts using satisfies RouteContract and use app.bind()'\n });\n return false;\n }\n\n // Extract paths from contract metas for logging and stats\n const contractPaths = this.extractContractPaths(module);\n\n // Validate contract paths against prefix (if prefix is provided)\n if (prefix)\n {\n const invalidPaths = contractPaths.filter(path => !path.startsWith(prefix));\n if (invalidPaths.length > 0)\n {\n routeLogger.error('Contract paths must include the package prefix', {\n file: relativePath,\n prefix,\n invalidPaths,\n hint: `Contract paths should start with \"${prefix}\". Example: path: \"${prefix}/labels\"`\n });\n return false;\n }\n }\n\n // Register contract-based middlewares\n this.registerContractBasedMiddlewares(app, contractPaths, module);\n\n // Mount directly (contracts already include full path with prefix)\n app.route('/', module.default);\n\n // Track routes for stats\n contractPaths.forEach(path => {\n this.routes.push({\n path: path, // Use contract path as-is (already includes prefix)\n file: relativePath,\n meta: module.meta,\n priority: this.calculateContractPriority(path),\n });\n\n if (this.debug)\n {\n const icon = path.includes('*') ? '⭐' : path.includes(':') ? '🔸' : '🔹';\n routeLogger.debug(`Registered route: ${path}`, { icon, file: relativePath });\n }\n });\n\n return true;\n }\n catch (error)\n {\n this.categorizeAndLogError(error as Error, relativePath);\n return false;\n }\n }\n\n private extractContractPaths(module: RouteModule): string[]\n {\n const paths = new Set<string>();\n\n if (module.default._contractMetas)\n {\n for (const key of module.default._contractMetas.keys())\n {\n // key format: \"GET /teams/:id\"\n const path = key.split(' ')[1];\n if (path)\n {\n paths.add(path);\n }\n }\n }\n\n return Array.from(paths);\n }\n\n private calculateContractPriority(path: string): number\n {\n if (path.includes('*')) return 3; // Catch-all\n if (path.includes(':')) return 2; // Dynamic\n return 1; // Static\n }\n\n private validateModule(module: RouteModule, relativePath: string): boolean\n {\n if (!module.default)\n {\n routeLogger.error('Route must export Hono instance as default', { file: relativePath });\n return false;\n }\n\n if (typeof module.default.route !== 'function')\n {\n routeLogger.error('Default export is not a Hono instance', { file: relativePath });\n return false;\n }\n\n return true;\n }\n\n private registerContractBasedMiddlewares(app: Hono, contractPaths: string[], module: RouteModule): void\n {\n // Register middleware checker for all contract paths\n app.use('*', (c, next) =>\n {\n const method = c.req.method;\n const requestPath = new URL(c.req.url).pathname;\n\n const key = `${method} ${requestPath}`;\n const meta = module.default._contractMetas?.get(key);\n\n if (meta?.skipMiddlewares)\n {\n c.set('_skipMiddlewares', meta.skipMiddlewares);\n }\n\n return next();\n });\n\n // Register middlewares for each contract path\n for (const contractPath of contractPaths)\n {\n const middlewarePath = contractPath === '/' ? '/*' : `${contractPath}/*`;\n\n for (const middleware of this.middlewares)\n {\n app.use(middlewarePath, async (c, next) =>\n {\n const skipList = c.get('_skipMiddlewares') || [];\n\n if (skipList.includes(middleware.name))\n {\n return next();\n }\n\n return middleware.handler(c, next);\n });\n }\n }\n }\n\n private categorizeAndLogError(error: Error, relativePath: string): void\n {\n const message = error.message;\n const stack = error.stack;\n\n if (message.includes('Cannot find module') || message.includes('MODULE_NOT_FOUND'))\n {\n routeLogger.error('Missing dependency', {\n file: relativePath,\n error: message,\n hint: 'Run: npm install',\n });\n }\n else if (message.includes('SyntaxError') || stack?.includes('SyntaxError'))\n {\n routeLogger.error('Syntax error', {\n file: relativePath,\n error: message,\n ...(this.debug && stack && {\n stack: stack.split('\\n').slice(0, 5).join('\\n')\n }),\n });\n }\n else if (message.includes('Unexpected token'))\n {\n routeLogger.error('Parse error', {\n file: relativePath,\n error: message,\n hint: 'Check for syntax errors or invalid TypeScript',\n });\n }\n else\n {\n routeLogger.error('Route loading failed', {\n file: relativePath,\n error: message,\n ...(this.debug && stack && { stack }),\n });\n }\n }\n\n private logStats(stats: RouteStats, elapsed: number): void\n {\n const tagCounts = Object.entries(stats.byTag)\n .map(([tag, count]) => `${tag}(${count})`)\n .join(', ');\n\n routeLogger.info('Routes loaded successfully', {\n total: stats.total,\n priority: {\n static: stats.byPriority.static,\n dynamic: stats.byPriority.dynamic,\n catchAll: stats.byPriority.catchAll,\n },\n ...(tagCounts && { tags: tagCounts }),\n elapsed: `${elapsed}ms`,\n });\n }\n}\n\nexport async function loadRoutes(\n app: Hono,\n options?: {\n routesDir?: string;\n debug?: boolean;\n middlewares?: Array<{ name: string; handler: MiddlewareHandler }>;\n includeFunctionRoutes?: boolean;\n }\n): Promise<RouteStats>\n{\n const routesDir = options?.routesDir ?? join(process.cwd(), 'src', 'server', 'routes');\n const debug = options?.debug ?? false;\n const middlewares = options?.middlewares ?? [];\n const includeFunctionRoutes = options?.includeFunctionRoutes ?? true; // Default: true\n\n const loader = new AutoRouteLoader(routesDir, debug, middlewares);\n const stats = await loader.load(app);\n\n // Load function routes if enabled\n if (includeFunctionRoutes)\n {\n const { discoverFunctionRoutes } = await import('./function-routes.js');\n const functionRoutes = discoverFunctionRoutes();\n\n if (functionRoutes.length > 0)\n {\n routeLogger.info('Loading function routes', { count: functionRoutes.length });\n\n for (const func of functionRoutes)\n {\n try\n {\n await loader.loadExternalRoutes(app, func.routesDir, func.packageName, func.prefix);\n routeLogger.info('Function routes loaded', {\n package: func.packageName,\n routesDir: func.routesDir,\n prefix: func.prefix || '/',\n });\n }\n catch (error)\n {\n routeLogger.error('Failed to load function routes', {\n package: func.packageName,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n }\n }\n\n return stats;\n}","import type { Context } from 'hono';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { Value } from '@sinclair/typebox/value';\nimport type { RouteContract, RouteContext, InferContract } from './types.js';\nimport { ValidationError } from '../errors';\nimport type { ApiSuccessResponse } from './api-response.js';\n\n/**\n * Contract-based Route Handler Wrapper\n *\n * Binds a contract to a route handler, providing automatic validation\n * and type-safe context creation.\n *\n * Features:\n * - Automatic params/query/body validation using TypeBox\n * - Type-safe RouteContext with contract-based inference\n * - Clean separation: bind() for validation, Hono for middleware\n */\nexport function bind<TContract extends RouteContract>(\n contract: TContract,\n handler: (c: RouteContext<TContract>) => Response | Promise<Response>\n) {\n return async (rawContext: Context) =>\n {\n let params = rawContext.req.param();\n if (contract.params)\n {\n // Convert types (e.g., string \"123\" -> number 123)\n params = Value.Convert(contract.params, params) as typeof params;\n\n // Then validate\n const errors = [...Value.Errors(contract.params, params)];\n if (errors.length > 0)\n {\n throw new ValidationError(\n 'Invalid path parameters',\n {\n fields: errors.map(e => ({\n path: e.path,\n message: e.message,\n value: e.value,\n }))\n }\n );\n }\n }\n\n const url = new URL(rawContext.req.url);\n let query: Record<string, string | string[]> = {};\n url.searchParams.forEach((v, k) =>\n {\n const existing = query[k];\n if (existing)\n {\n query[k] = Array.isArray(existing) ? [...existing, v] : [existing, v];\n }\n else\n {\n query[k] = v;\n }\n });\n\n if (contract.query)\n {\n // Convert types (e.g., string \"123\" -> number 123, \"true\" -> boㅇolean true)\n query = Value.Convert(contract.query, query) as typeof query;\n\n // Then validate\n const errors = [...Value.Errors(contract.query, query)];\n if (errors.length > 0)\n {\n throw new ValidationError(\n 'Invalid query parameters',\n {\n fields: errors.map(e => ({\n path: e.path,\n message: e.message,\n value: e.value,\n }))\n }\n );\n }\n }\n\n const routeContext: RouteContext<TContract> =\n {\n params: params as InferContract<TContract>['params'],\n query: query as InferContract<TContract>['query'],\n\n data: async () =>\n {\n let body = await rawContext.req.json();\n if (contract.body)\n {\n // Convert types (e.g., handle nested objects, arrays, etc.)\n body = Value.Convert(contract.body, body) as any;\n\n // Then validate\n const errors = [...Value.Errors(contract.body, body)];\n if (errors.length > 0)\n {\n throw new ValidationError(\n 'Invalid request body',\n {\n fields: errors.map(e => ({\n path: e.path,\n message: e.message,\n value: e.value,\n }))\n }\n );\n }\n }\n\n return body as InferContract<TContract>['body'];\n },\n\n json: (data, status, headers) =>\n {\n // Warn if ErrorHandler is enabled but response doesn't follow standard format\n const errorHandlerEnabled = rawContext.get('errorHandlerEnabled');\n if (errorHandlerEnabled && process.env.NODE_ENV !== 'production')\n {\n const hasSuccessField = data && typeof data === 'object' && 'success' in data;\n if (!hasSuccessField)\n {\n console.warn(\n '[SPFN] Warning: ErrorHandler is enabled but c.json() is being used with non-standard response format.\\n' +\n 'Consider using c.success() for consistent API responses, or disable ErrorHandler if you prefer custom formats.'\n );\n }\n }\n\n return rawContext.json(data, status, headers);\n },\n\n success: <T>(data: T, meta?: ApiSuccessResponse<T>['meta'], status: ContentfulStatusCode | undefined = 200) =>\n {\n const response: ApiSuccessResponse<T> = {\n success: true,\n data,\n };\n\n if (meta)\n {\n response.meta = meta;\n }\n\n return rawContext.json(response, status);\n },\n\n paginated: <T>(data: T[], page: number, limit: number, total: number) =>\n {\n const response: ApiSuccessResponse<T[]> = {\n success: true,\n data,\n meta: {\n pagination: {\n page,\n limit,\n total,\n totalPages: Math.ceil(total / limit),\n },\n },\n };\n\n return rawContext.json(response, 200 as ContentfulStatusCode);\n },\n\n raw: rawContext,\n };\n\n return handler(routeContext);\n };\n}","/**\n * Error Handler Middleware\n *\n * Generic middleware that converts errors with statusCode to HTTP responses\n */\nimport type { Context } from 'hono';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { logger } from '../logger';\nimport type { ErrorResponse } from '../types/api-response.js';\n\nconst errorLogger = logger.child('error-handler');\n\nexport interface ErrorHandlerOptions\n{\n /**\n * Include stack trace in response\n * @default process.env.NODE_ENV !== 'production'\n */\n includeStack?: boolean;\n\n /**\n * Enable error logging\n * @default true\n */\n enableLogging?: boolean;\n}\n\ninterface ErrorWithStatusCode extends Error\n{\n statusCode?: number;\n details?: any;\n}\n\n/**\n * Standard error response format\n *\n * Re-exported from @spfn/core/types for convenience\n */\nexport type { ErrorResponse } from '../types/api-response.js';\n\n/**\n * Error handler middleware\n *\n * Used in Hono's onError hook\n */\nexport function ErrorHandler(options: ErrorHandlerOptions = {}): (err: Error, c: Context) => Response | Promise<Response>\n{\n const {\n includeStack = process.env.NODE_ENV !== 'production',\n enableLogging = true,\n } = options;\n\n return (err: Error, c: Context) =>\n {\n const errorWithCode = err as ErrorWithStatusCode;\n const statusCode = errorWithCode.statusCode || 500;\n const errorType = err.name || 'Error';\n\n if (enableLogging)\n {\n const logLevel = statusCode >= 500 ? 'error' : 'warn';\n\n const logData: Record<string, any> = {\n type: errorType,\n message: err.message,\n statusCode,\n path: c.req.path,\n method: c.req.method,\n };\n\n // Include details if available\n if (errorWithCode.details)\n {\n logData.details = errorWithCode.details;\n }\n\n // Include stack trace for 500 errors in development\n if (statusCode >= 500 && includeStack)\n {\n logData.stack = err.stack;\n }\n\n errorLogger[logLevel]('Error occurred', logData);\n }\n\n const response: ErrorResponse = {\n success: false,\n error: {\n message: err.message || 'Internal Server Error',\n type: errorType,\n statusCode,\n },\n };\n\n if (errorWithCode.details)\n {\n response.error.details = errorWithCode.details;\n }\n\n if (includeStack)\n {\n response.error.stack = err.stack;\n }\n\n return c.json(response, statusCode as ContentfulStatusCode);\n };\n}\n","/**\n * Request Logger Middleware\n *\n * Automatic API request/response logging with performance monitoring\n */\nimport type { Context, Next } from 'hono';\nimport { randomBytes } from 'crypto';\nimport { logger } from '../logger';\n\nexport interface RequestLoggerConfig\n{\n /**\n * Paths to exclude from logging (health checks, etc.)\n */\n excludePaths?: string[];\n\n /**\n * Field names to mask for sensitive data\n */\n sensitiveFields?: string[];\n\n /**\n * Slow request threshold (ms)\n */\n slowRequestThreshold?: number;\n}\n\nconst DEFAULT_CONFIG: Required<RequestLoggerConfig> = {\n excludePaths: ['/health', '/ping', '/favicon.ico'],\n sensitiveFields: ['password', 'token', 'apiKey', 'secret', 'authorization'],\n slowRequestThreshold: 1000,\n};\n\n/**\n * Generate cryptographically secure request ID\n */\nfunction generateRequestId(): string\n{\n const timestamp = Date.now();\n const randomPart = randomBytes(6).toString('hex');\n return `req_${timestamp}_${randomPart}`;\n}\n\n/**\n * Mask sensitive data with circular reference handling\n */\nexport function maskSensitiveData(\n obj: any,\n sensitiveFields: string[],\n seen = new WeakSet()\n): any\n{\n if (!obj || typeof obj !== 'object') return obj;\n\n if (seen.has(obj)) return '[Circular]';\n seen.add(obj);\n\n const lowerFields = sensitiveFields.map(f => f.toLowerCase());\n const masked = Array.isArray(obj) ? [...obj] : { ...obj };\n\n for (const key in masked)\n {\n const lowerKey = key.toLowerCase();\n\n if (lowerFields.some(field => lowerKey.includes(field)))\n {\n masked[key] = '***MASKED***';\n }\n else if (typeof masked[key] === 'object' && masked[key] !== null)\n {\n masked[key] = maskSensitiveData(masked[key], sensitiveFields, seen);\n }\n }\n\n return masked;\n}\n\n/**\n * Request Logger middleware\n */\nexport function RequestLogger(config?: RequestLoggerConfig)\n{\n const cfg = { ...DEFAULT_CONFIG, ...config };\n const apiLogger = logger.child('api');\n\n return async (c: Context, next: Next) =>\n {\n const path = new URL(c.req.url).pathname;\n\n if (cfg.excludePaths.includes(path))\n {\n return next();\n }\n\n const requestId = generateRequestId();\n c.set('requestId', requestId);\n\n const method = c.req.method;\n const userAgent = c.req.header('user-agent');\n const ip = c.req.header('x-forwarded-for') || c.req.header('x-real-ip') || 'unknown';\n\n const startTime = Date.now();\n\n apiLogger.info('Request received', {\n requestId,\n method,\n path,\n ip,\n userAgent,\n });\n\n try\n {\n await next();\n\n const duration = Date.now() - startTime;\n const status = c.res.status;\n\n const logData: Record<string, any> = {\n requestId,\n method,\n path,\n status,\n duration,\n };\n\n const isSlowRequest = duration >= cfg.slowRequestThreshold;\n if (isSlowRequest)\n {\n logData.slow = true;\n }\n\n // Add detailed error information for 4xx/5xx responses\n if (status >= 400)\n {\n try\n {\n // Clone response to read body without consuming it\n const responseBody = await c.res.clone().json();\n logData.response = responseBody;\n }\n catch\n {\n // Response is not JSON or already consumed - ignore\n }\n\n // Add request body for POST/PUT/PATCH to see what data caused the error\n if (['POST', 'PUT', 'PATCH'].includes(method))\n {\n try\n {\n // Try to get the already parsed body from context\n const requestBody = await c.req.json();\n logData.request = maskSensitiveData(requestBody, cfg.sensitiveFields);\n }\n catch\n {\n // Body is not JSON or already consumed - ignore\n }\n }\n }\n\n const logLevel = status >= 500 ? 'error' : status >= 400 ? 'warn' : 'info';\n apiLogger[logLevel]('Request completed', logData);\n }\n catch (error)\n {\n const duration = Date.now() - startTime;\n\n apiLogger.error('Request failed', error as Error, {\n requestId,\n method,\n path,\n duration,\n });\n\n throw error;\n }\n };\n}","import type { Context } from 'hono';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport type { TSchema, Static } from '@sinclair/typebox';\nimport type { ApiSuccessResponse } from './api-response.js';\n\n/**\n * File-based Routing System Type Definitions\n */\n\nexport type HeaderRecord = Record<string, string | string[]>;\n\nexport type RouteMeta = {\n public?: boolean;\n skipMiddlewares?: string[];\n tags?: string[];\n description?: string;\n deprecated?: boolean;\n};\n\n/**\n * Route Contract: TypeBox-based type-safe route definition\n *\n * Defines the shape of request/response for a route endpoint\n */\nexport type RouteContract = {\n method: HttpMethod;\n path: string;\n params?: TSchema;\n query?: TSchema;\n body?: TSchema;\n response: TSchema;\n meta?: RouteMeta;\n};\n\n/**\n * Infer types from RouteContract\n *\n * Extracts TypeScript types from TypeBox schemas\n */\nexport type InferContract<TContract extends RouteContract> = {\n params: TContract['params'] extends TSchema\n ? Static<TContract['params']>\n : Record<string, never>;\n query: TContract['query'] extends TSchema\n ? Static<TContract['query']>\n : Record<string, never>;\n body: TContract['body'] extends TSchema\n ? Static<TContract['body']>\n : Record<string, never>;\n response: TContract['response'] extends TSchema\n ? Static<TContract['response']>\n : unknown;\n};\n\n/**\n * RouteContext: Route Handler Dedicated Context\n *\n * Generic version with contract-based type inference\n */\nexport type RouteContext<TContract extends RouteContract = any> = {\n params: InferContract<TContract>['params'];\n query: InferContract<TContract>['query'];\n data(): Promise<InferContract<TContract>['body']>;\n json(\n data: InferContract<TContract>['response'],\n status?: ContentfulStatusCode,\n headers?: HeaderRecord\n ): Response;\n success<T>(\n data: T,\n meta?: ApiSuccessResponse<T>['meta'],\n status?: number\n ): Response;\n paginated<T>(\n data: T[],\n page: number,\n limit: number,\n total: number\n ): Response;\n raw: Context;\n};\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\nexport type RouteHandler<TContract extends RouteContract = any> =\n (c: RouteContext<TContract>) => Response | Promise<Response>;\n\nexport function isHttpMethod(value: unknown): value is HttpMethod\n{\n return (\n typeof value === 'string' &&\n ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(value)\n );\n}","/**\n * Create Hono Server\n *\n * Creates and configures a Hono application instance.\n */\n\nimport { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\n\nimport { loadRoutes } from '../route';\nimport { ErrorHandler, RequestLogger } from '../middleware';\nimport { logger } from '../logger';\nimport { createHealthCheckHandler } from './helpers.js';\n\nimport type { ServerConfig, AppFactory } from './types.js';\n\n// Extend Hono context with error handler flag\ndeclare module 'hono'\n{\n interface ContextVariableMap\n {\n errorHandlerEnabled?: boolean;\n }\n}\n\nconst serverLogger = logger.child('server');\n\n/**\n * Create Hono app with automatic configuration\n *\n * Levels:\n * 1. No app.ts -> Full auto config\n * 2. server.config.ts -> Partial customization\n * 3. app.ts -> Full control (no auto config)\n */\nexport async function createServer(config?: ServerConfig): Promise<Hono>\n{\n const cwd = process.cwd();\n const appPath = join(cwd, 'src', 'server', 'app.ts');\n const appJsPath = join(cwd, 'src', 'server', 'app.js');\n\n // Level 3: Full control with app.ts\n if (existsSync(appPath) || existsSync(appJsPath))\n {\n return await loadCustomApp(appPath, appJsPath, config);\n }\n\n // Level 1 & 2: Auto config\n return await createAutoConfiguredApp(config);\n}\n\nasync function loadCustomApp(\n appPath: string,\n appJsPath: string,\n config?: ServerConfig\n): Promise<Hono>\n{\n const appModule = await import(existsSync(appPath) ? appPath : appJsPath);\n const appFactory: AppFactory = appModule.default;\n\n if (!appFactory)\n {\n throw new Error('app.ts must export a default function that returns a Hono app');\n }\n\n const app = await appFactory();\n\n // Only load routes, everything else is user's responsibility\n const debug = config?.debug ?? process.env.NODE_ENV === 'development';\n await loadRoutes(app, { routesDir: config?.routesPath, debug });\n\n return app;\n}\n\nasync function createAutoConfiguredApp(config?: ServerConfig): Promise<Hono>\n{\n const app = new Hono();\n\n const middlewareConfig = config?.middleware ?? {};\n const enableLogger = middlewareConfig.logger !== false;\n const enableCors = middlewareConfig.cors !== false;\n const enableErrorHandler = middlewareConfig.errorHandler !== false;\n\n // 1. Set error handler flag in context\n if (enableErrorHandler)\n {\n app.use('*', async (c, next) =>\n {\n c.set('errorHandlerEnabled', true);\n await next();\n });\n }\n\n // 2. Default middleware\n applyDefaultMiddleware(app, config, enableLogger, enableCors);\n\n // 3. Custom middleware\n config?.use?.forEach(mw => app.use('*', mw));\n\n // 4. Health check endpoint\n registerHealthCheckEndpoint(app, config);\n\n // 5. beforeRoutes hook\n await executeBeforeRoutesHook(app, config);\n\n // 6. Load routes\n await loadAppRoutes(app, config);\n\n // 7. afterRoutes hook\n await executeAfterRoutesHook(app, config);\n\n // 8. Error handler\n if (enableErrorHandler)\n {\n app.onError(ErrorHandler());\n }\n\n return app;\n}\n\nfunction applyDefaultMiddleware(\n app: Hono,\n config: ServerConfig | undefined,\n enableLogger: boolean,\n enableCors: boolean\n): void\n{\n if (enableLogger)\n {\n app.use('*', RequestLogger());\n }\n\n if (enableCors && config?.cors !== false)\n {\n app.use('*', cors(config?.cors));\n }\n}\n\nfunction registerHealthCheckEndpoint(app: Hono, config?: ServerConfig): void\n{\n const healthCheckConfig = config?.healthCheck ?? {};\n const healthCheckEnabled = healthCheckConfig.enabled !== false;\n const healthCheckPath = healthCheckConfig.path ?? '/health';\n const healthCheckDetailed = healthCheckConfig.detailed\n ?? process.env.NODE_ENV === 'development';\n\n if (healthCheckEnabled)\n {\n app.get(healthCheckPath, createHealthCheckHandler(healthCheckDetailed));\n serverLogger.debug(`Health check endpoint enabled at ${healthCheckPath}`);\n }\n}\n\nasync function executeBeforeRoutesHook(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (!config?.lifecycle?.beforeRoutes)\n {\n return;\n }\n\n try\n {\n await config.lifecycle.beforeRoutes(app);\n }\n catch (error)\n {\n serverLogger.error('beforeRoutes hook failed', error as Error);\n throw new Error('Server initialization failed in beforeRoutes hook');\n }\n}\n\nasync function loadAppRoutes(app: Hono, config?: ServerConfig): Promise<void>\n{\n const debug = config?.debug ?? process.env.NODE_ENV === 'development';\n await loadRoutes(app, {\n routesDir: config?.routesPath,\n debug,\n middlewares: config?.middlewares\n });\n}\n\nasync function executeAfterRoutesHook(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (!config?.lifecycle?.afterRoutes)\n {\n return;\n }\n\n try\n {\n await config.lifecycle.afterRoutes(app);\n }\n catch (error)\n {\n serverLogger.error('afterRoutes hook failed', error as Error);\n throw new Error('Server initialization failed in afterRoutes hook');\n }\n}\n","import type { Hono, Handler } from 'hono';\nimport type { Server } from 'http';\n\nexport function createHealthCheckHandler(detailed: boolean): Handler\n{\n return async (c) =>\n {\n const response: any = {\n status: 'ok',\n timestamp: new Date().toISOString(),\n };\n\n if (detailed)\n {\n const { getDatabase } = await import('../db/index.js');\n const { getRedis } = await import('../cache/index.js');\n\n const db = getDatabase();\n let dbStatus = 'disconnected';\n let dbError: string | undefined;\n if (db)\n {\n try\n {\n await db.execute('SELECT 1');\n dbStatus = 'connected';\n }\n catch (error)\n {\n dbStatus = 'error';\n dbError = error instanceof Error ? error.message : String(error);\n }\n }\n\n const redis = getRedis();\n let redisStatus = 'disconnected';\n let redisError: string | undefined;\n if (redis)\n {\n try\n {\n await redis.ping();\n redisStatus = 'connected';\n }\n catch (error)\n {\n redisStatus = 'error';\n redisError = error instanceof Error ? error.message : String(error);\n }\n }\n\n response.services = {\n database: {\n status: dbStatus,\n ...(dbError && { error: dbError }),\n },\n redis: {\n status: redisStatus,\n ...(redisError && { error: redisError }),\n },\n };\n\n const hasErrors = dbStatus === 'error' || redisStatus === 'error';\n response.status = hasErrors ? 'degraded' : 'ok';\n }\n\n const statusCode = response.status === 'ok' ? 200 : 503;\n return c.json(response, statusCode);\n };\n}\n\nexport function applyServerTimeouts(\n server: Server,\n timeouts: {\n request: number;\n keepAlive: number;\n headers: number;\n }\n): void\n{\n if ('timeout' in server)\n {\n server.timeout = timeouts.request;\n server.keepAliveTimeout = timeouts.keepAlive;\n server.headersTimeout = timeouts.headers;\n }\n}\n\nexport function getTimeoutConfig(config?: {\n request?: number;\n keepAlive?: number;\n headers?: number;\n}): {\n request: number;\n keepAlive: number;\n headers: number;\n}\n{\n return {\n request: config?.request ?? (parseInt(process.env.SERVER_TIMEOUT || '', 10) || 120000),\n keepAlive: config?.keepAlive ?? (parseInt(process.env.SERVER_KEEPALIVE_TIMEOUT || '', 10) || 65000),\n headers: config?.headers ?? (parseInt(process.env.SERVER_HEADERS_TIMEOUT || '', 10) || 60000),\n };\n}\n\nexport function getShutdownTimeout(config?: { timeout?: number }): number\n{\n return config?.timeout ?? (parseInt(process.env.SHUTDOWN_TIMEOUT || '', 10) || 30000);\n}\n\nexport function buildMiddlewareOrder(config: {\n middleware?: {\n logger?: boolean;\n cors?: boolean;\n errorHandler?: boolean;\n };\n use?: any[];\n beforeRoutes?: (app: Hono) => void | Promise<void>;\n afterRoutes?: (app: Hono) => void | Promise<void>;\n}): string[]\n{\n const order: string[] = [];\n const middlewareConfig = config.middleware ?? {};\n const enableLogger = middlewareConfig.logger !== false;\n const enableCors = middlewareConfig.cors !== false;\n const enableErrorHandler = middlewareConfig.errorHandler !== false;\n\n if (enableLogger) order.push('RequestLogger');\n if (enableCors) order.push('CORS');\n config.use?.forEach((_, i) => order.push(`Custom[${i}]`));\n if (config.beforeRoutes) order.push('beforeRoutes hook');\n order.push('Routes');\n if (config.afterRoutes) order.push('afterRoutes hook');\n if (enableErrorHandler) order.push('ErrorHandler');\n\n return order;\n}\n\nexport function buildStartupConfig(\n config: {\n middleware?: {\n logger?: boolean;\n cors?: boolean;\n errorHandler?: boolean;\n };\n use?: any[];\n healthCheck?: {\n enabled?: boolean;\n path?: string;\n detailed?: boolean;\n };\n beforeRoutes?: (app: Hono) => void | Promise<void>;\n afterRoutes?: (app: Hono) => void | Promise<void>;\n shutdown?: {\n timeout?: number;\n };\n },\n timeouts: {\n request: number;\n keepAlive: number;\n headers: number;\n }\n): any\n{\n const middlewareConfig = config.middleware ?? {};\n const healthCheckConfig = config.healthCheck ?? {};\n const healthCheckEnabled = healthCheckConfig.enabled !== false;\n const healthCheckPath = healthCheckConfig.path ?? '/health';\n const healthCheckDetailed = healthCheckConfig.detailed ?? (process.env.NODE_ENV === 'development');\n\n return {\n middleware: {\n logger: middlewareConfig.logger !== false,\n cors: middlewareConfig.cors !== false,\n errorHandler: middlewareConfig.errorHandler !== false,\n custom: config.use?.length ?? 0,\n },\n healthCheck: healthCheckEnabled ? {\n enabled: true,\n path: healthCheckPath,\n detailed: healthCheckDetailed,\n } : { enabled: false },\n hooks: {\n beforeRoutes: !!config.beforeRoutes,\n afterRoutes: !!config.afterRoutes,\n },\n timeout: {\n request: `${timeouts.request}ms`,\n keepAlive: `${timeouts.keepAlive}ms`,\n headers: `${timeouts.headers}ms`,\n },\n shutdown: {\n timeout: `${config.shutdown?.timeout ?? 30000}ms`,\n },\n };\n}\n","/**\n * Start SPFN Server\n *\n * Starts and configures the SPFN HTTP server with graceful shutdown.\n */\n\nimport { serve } from '@hono/node-server';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport type { Server } from 'http';\n\nimport { initRedis, closeRedis } from '../cache';\nimport { initDatabase, closeDatabase } from '../db';\nimport { logger } from '../logger';\nimport { printBanner } from './banner.js';\nimport { validateServerConfig } from './validation.js';\nimport { createServer } from './create-server.js';\nimport {\n applyServerTimeouts,\n getTimeoutConfig,\n getShutdownTimeout,\n buildMiddlewareOrder,\n buildStartupConfig,\n} from './helpers.js';\n\nimport type { ServerConfig, ServerInstance } from './types.js';\n\nconst serverLogger = logger.child('server');\n\n/**\n * Start SPFN server\n *\n * Automatically loads server.config.ts if exists\n * Automatically initializes Database and Redis from environment\n * Sets up graceful shutdown handlers for SIGTERM and SIGINT\n *\n * @returns ServerInstance with server, app, config, and close() method\n */\nexport async function startServer(config?: ServerConfig): Promise<ServerInstance>\n{\n const finalConfig = await loadAndMergeConfig(config);\n const { host, port, debug } = finalConfig;\n\n validateServerConfig(finalConfig);\n\n if (debug)\n {\n logMiddlewareOrder(finalConfig);\n }\n\n try\n {\n await initializeInfrastructure(finalConfig);\n\n const app = await createServer(finalConfig);\n const server = startHttpServer(app, host!, port!);\n\n const timeouts = getTimeoutConfig(finalConfig.timeout);\n applyServerTimeouts(server as Server, timeouts);\n\n logServerTimeouts(timeouts);\n printBanner({\n mode: debug ? 'Development' : 'Production',\n host: host!,\n port: port!,\n });\n\n logServerStarted(debug, host!, port!, finalConfig, timeouts);\n\n const shutdownServer = createShutdownHandler(server as Server, finalConfig);\n const shutdown = createGracefulShutdown(shutdownServer, finalConfig);\n\n registerShutdownHandlers(shutdown);\n\n const serverInstance: ServerInstance = {\n server: server as Server,\n app,\n config: finalConfig,\n close: async () =>\n {\n serverLogger.info('Manual server shutdown requested');\n await shutdownServer();\n },\n };\n\n // Execute afterStart hook\n if (finalConfig.lifecycle?.afterStart)\n {\n serverLogger.debug('Executing afterStart hook...');\n try\n {\n await finalConfig.lifecycle.afterStart(serverInstance);\n }\n catch (error)\n {\n serverLogger.error('afterStart hook failed', error as Error);\n // Don't throw - server is already running\n // Just log the error and continue\n }\n }\n\n return serverInstance;\n }\n catch (error)\n {\n const err = error as Error;\n serverLogger.error('Server initialization failed', err);\n\n await cleanupOnFailure(finalConfig);\n\n throw error;\n }\n}\n\nasync function loadAndMergeConfig(config?: ServerConfig): Promise<ServerConfig>\n{\n const cwd = process.cwd();\n const configPath = join(cwd, 'src', 'server', 'server.config.ts');\n const configJsPath = join(cwd, 'src', 'server', 'server.config.js');\n const builtConfigMjsPath = join(cwd, '.spfn', 'server', 'server.config.mjs');\n const builtConfigPath = join(cwd, '.spfn', 'server', 'server.config.js');\n\n let fileConfig: ServerConfig = {};\n\n // Check in order: .spfn/server (built .mjs), .spfn/server (built .js), src/server (.js), src/server (.ts)\n if (existsSync(builtConfigMjsPath))\n {\n const configModule = await import(builtConfigMjsPath);\n fileConfig = configModule.default ?? {};\n }\n else if (existsSync(builtConfigPath))\n {\n const configModule = await import(builtConfigPath);\n fileConfig = configModule.default ?? {};\n }\n else if (existsSync(configJsPath))\n {\n const configModule = await import(configJsPath);\n fileConfig = configModule.default ?? {};\n }\n else if (existsSync(configPath))\n {\n const configModule = await import(configPath);\n fileConfig = configModule.default ?? {};\n }\n\n return {\n ...fileConfig,\n ...config,\n port: config?.port ?? fileConfig?.port ?? (parseInt(process.env.PORT || '', 10) || 4000),\n host: config?.host ?? fileConfig?.host ?? (process.env.HOST || 'localhost'),\n };\n}\n\nfunction logMiddlewareOrder(config: ServerConfig): void\n{\n const middlewareOrder = buildMiddlewareOrder(config);\n serverLogger.debug('Middleware execution order', {\n order: middlewareOrder,\n });\n}\n\nasync function initializeInfrastructure(config: ServerConfig): Promise<void>\n{\n // Execute beforeInfrastructure hook\n if (config.lifecycle?.beforeInfrastructure)\n {\n serverLogger.debug('Executing beforeInfrastructure hook...');\n try\n {\n await config.lifecycle.beforeInfrastructure(config);\n }\n catch (error)\n {\n serverLogger.error('beforeInfrastructure hook failed', error as Error);\n throw new Error('Server initialization failed in beforeInfrastructure hook');\n }\n }\n\n // Initialize database if not explicitly disabled\n const shouldInitDatabase = config.infrastructure?.database !== false;\n if (shouldInitDatabase)\n {\n serverLogger.debug('Initializing database...');\n await initDatabase(config.database);\n }\n else\n {\n serverLogger.debug('Database initialization disabled');\n }\n\n // Initialize Redis if not explicitly disabled\n const shouldInitRedis = config.infrastructure?.redis !== false;\n if (shouldInitRedis)\n {\n serverLogger.debug('Initializing Redis...');\n await initRedis();\n }\n else\n {\n serverLogger.debug('Redis initialization disabled');\n }\n\n // Execute afterInfrastructure hook\n if (config.lifecycle?.afterInfrastructure)\n {\n serverLogger.debug('Executing afterInfrastructure hook...');\n try\n {\n await config.lifecycle.afterInfrastructure();\n }\n catch (error)\n {\n serverLogger.error('afterInfrastructure hook failed', error as Error);\n throw new Error('Server initialization failed in afterInfrastructure hook');\n }\n }\n}\n\nfunction startHttpServer(app: any, host: string, port: number): any\n{\n serverLogger.debug(`Starting server on ${host}:${port}...`);\n\n return serve({\n fetch: app.fetch,\n port,\n hostname: host,\n });\n}\n\nfunction logServerTimeouts(timeouts: {\n request: number;\n keepAlive: number;\n headers: number;\n}): void\n{\n serverLogger.info('Server timeouts configured', {\n request: `${timeouts.request}ms`,\n keepAlive: `${timeouts.keepAlive}ms`,\n headers: `${timeouts.headers}ms`,\n });\n}\n\nfunction logServerStarted(\n debug: boolean | undefined,\n host: string,\n port: number,\n config: ServerConfig,\n timeouts: { request: number; keepAlive: number; headers: number }\n): void\n{\n const startupConfig = buildStartupConfig(config, timeouts);\n\n serverLogger.info('Server started successfully', {\n mode: debug ? 'development' : 'production',\n host,\n port,\n config: startupConfig,\n });\n}\n\nfunction createShutdownHandler(server: Server, config: ServerConfig): () => Promise<void>\n{\n return async () =>\n {\n serverLogger.debug('Closing HTTP server...');\n await new Promise<void>((resolve) =>\n {\n server.close(() =>\n {\n serverLogger.info('HTTP server closed');\n resolve();\n });\n });\n\n // Execute beforeShutdown hook\n if (config.lifecycle?.beforeShutdown)\n {\n serverLogger.debug('Executing beforeShutdown hook...');\n try\n {\n await config.lifecycle.beforeShutdown();\n }\n catch (error)\n {\n serverLogger.error('beforeShutdown hook failed', error as Error);\n // Continue with shutdown even if hook fails\n }\n }\n\n // Only close resources that were enabled for initialization\n const shouldCloseDatabase = config.infrastructure?.database !== false;\n const shouldCloseRedis = config.infrastructure?.redis !== false;\n\n if (shouldCloseDatabase)\n {\n serverLogger.debug('Closing database connections...');\n await closeDatabase();\n }\n\n if (shouldCloseRedis)\n {\n serverLogger.debug('Closing Redis connections...');\n await closeRedis();\n }\n\n serverLogger.info('Server shutdown completed');\n };\n}\n\nfunction createGracefulShutdown(\n shutdownServer: () => Promise<void>,\n config: ServerConfig\n): (signal: string) => Promise<void>\n{\n return async (signal: string) =>\n {\n serverLogger.info(`${signal} received, starting graceful shutdown...`);\n\n const shutdownTimeout = getShutdownTimeout(config.shutdown);\n\n const timeoutPromise = new Promise<never>((_, reject) =>\n {\n setTimeout(() =>\n {\n reject(new Error(`Graceful shutdown timeout after ${shutdownTimeout}ms`));\n }, shutdownTimeout);\n });\n\n try\n {\n await Promise.race([\n shutdownServer(),\n timeoutPromise,\n ]);\n\n serverLogger.info('Graceful shutdown completed successfully');\n process.exit(0);\n }\n catch (error)\n {\n const err = error as Error;\n\n if (err.message && err.message.includes('timeout'))\n {\n serverLogger.error('Graceful shutdown timeout, forcing exit', err);\n }\n else\n {\n serverLogger.error('Error during graceful shutdown', err);\n }\n\n process.exit(1);\n }\n };\n}\n\nfunction registerShutdownHandlers(shutdown: (signal: string) => Promise<void>): void\n{\n // Increase max listeners to prevent warnings in development with hot reload\n process.setMaxListeners(15);\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n\n process.on('uncaughtException', (error) =>\n {\n serverLogger.error('Uncaught exception', error);\n shutdown('UNCAUGHT_EXCEPTION');\n });\n\n process.on('unhandledRejection', (reason, promise) =>\n {\n serverLogger.error('Unhandled promise rejection', {\n reason,\n promise,\n });\n shutdown('UNHANDLED_REJECTION');\n });\n}\n\nasync function cleanupOnFailure(config: ServerConfig): Promise<void>\n{\n try\n {\n serverLogger.debug('Cleaning up after initialization failure...');\n\n // Only cleanup resources that were enabled for initialization\n const shouldCleanupDatabase = config.infrastructure?.database !== false;\n const shouldCleanupRedis = config.infrastructure?.redis !== false;\n\n if (shouldCleanupDatabase)\n {\n await closeDatabase();\n }\n\n if (shouldCleanupRedis)\n {\n await closeRedis();\n }\n\n serverLogger.debug('Cleanup completed');\n }\n catch (cleanupError)\n {\n serverLogger.error('Cleanup failed', cleanupError as Error);\n }\n}","/**\n * Server Startup Banner\n *\n * Displays SPFN logo and server information at startup.\n */\n\nimport { networkInterfaces } from 'os';\n\n/**\n * Get local network IP address\n */\nfunction getNetworkAddress(): string | null\n{\n const nets = networkInterfaces();\n\n for (const name of Object.keys(nets))\n {\n const netGroup = nets[name];\n if (!netGroup) continue;\n\n for (const net of netGroup)\n {\n // IPv4, non-internal address\n if (net.family === 'IPv4' && !net.internal)\n {\n return net.address;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Print server startup banner\n */\nexport function printBanner(options: {\n mode: string;\n host: string;\n port: number;\n}): void\n{\n const { mode, host, port } = options;\n\n console.log('');\n console.log(' _____ ____ ______ _ _');\n console.log(' / ____| _ \\\\| ____| \\\\ | |');\n console.log(' | (___ | |_) | |__ | \\\\| |');\n console.log(' \\\\___ \\\\| __/| __| | . ` |');\n console.log(' ____) | | | | | |\\\\ |');\n console.log(' |_____/|_| |_| |_| \\\\_|');\n console.log('');\n console.log(` Mode: ${mode}`);\n\n // Show Local and Network addresses like Next.js\n if (host === '0.0.0.0')\n {\n const networkIP = getNetworkAddress();\n console.log(` ▲ Local: http://localhost:${port}`);\n if (networkIP)\n {\n console.log(` ▲ Network: http://${networkIP}:${port}`);\n }\n }\n else\n {\n console.log(` ▲ Local: http://${host}:${port}`);\n }\n\n console.log('');\n}\n","/**\n * Server Configuration Validation\n *\n * Validates server configuration to catch errors early with clear messages.\n */\n\nimport type { ServerConfig } from './types.js';\n\n/**\n * Validate server configuration\n * Throws descriptive errors for invalid configurations\n */\nexport function validateServerConfig(config: ServerConfig): void\n{\n // Port validation\n if (config.port !== undefined)\n {\n if (!Number.isInteger(config.port) || config.port < 0 || config.port > 65535)\n {\n throw new Error(\n `Invalid port: ${config.port}. Port must be an integer between 0 and 65535.`\n );\n }\n }\n\n // Timeout validation\n if (config.timeout)\n {\n const { request, keepAlive, headers } = config.timeout;\n\n if (request !== undefined && (request < 0 || !Number.isFinite(request)))\n {\n throw new Error(`Invalid timeout.request: ${request}. Must be a positive number.`);\n }\n\n if (keepAlive !== undefined && (keepAlive < 0 || !Number.isFinite(keepAlive)))\n {\n throw new Error(`Invalid timeout.keepAlive: ${keepAlive}. Must be a positive number.`);\n }\n\n if (headers !== undefined && (headers < 0 || !Number.isFinite(headers)))\n {\n throw new Error(`Invalid timeout.headers: ${headers}. Must be a positive number.`);\n }\n\n // Logical validation\n if (headers && request && headers > request)\n {\n throw new Error(\n `Invalid timeout configuration: headers timeout (${headers}ms) cannot exceed request timeout (${request}ms).`\n );\n }\n }\n\n // Shutdown timeout validation\n if (config.shutdown?.timeout !== undefined)\n {\n const timeout = config.shutdown.timeout;\n if (timeout < 0 || !Number.isFinite(timeout))\n {\n throw new Error(`Invalid shutdown.timeout: ${timeout}. Must be a positive number.`);\n }\n }\n\n // Health check path validation\n if (config.healthCheck?.path)\n {\n if (!config.healthCheck.path.startsWith('/'))\n {\n throw new Error(\n `Invalid healthCheck.path: \"${config.healthCheck.path}\". Must start with \"/\".`\n );\n }\n }\n}"]}
|
|
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/logger/index.ts","../src/route/function-routes.ts","../src/errors/database-errors.ts","../src/errors/http-errors.ts","../src/errors/error-utils.ts","../src/errors/index.ts","../src/env/config.ts","../src/env/loader.ts","../src/env/validator.ts","../src/env/index.ts","../src/db/postgres-errors.ts","../src/db/manager/connection.ts","../src/db/manager/config.ts","../src/db/manager/factory.ts","../src/db/manager/global-state.ts","../src/db/manager/health-check.ts","../src/db/manager/manager.ts","../src/db/manager/index.ts","../src/db/manager/config-generator.ts","../src/db/schema/helpers.ts","../src/db/schema/index.ts","../src/db/schema-helper.ts","../src/db/transaction/context.ts","../src/db/transaction/middleware.ts","../src/db/transaction/index.ts","../src/db/helpers.ts","../src/db/index.ts","../src/cache/cache-factory.ts","../src/cache/cache-manager.ts","../src/cache/index.ts","../src/route/auto-loader.ts","../src/route/bind.ts","../src/middleware/error-handler.ts","../src/middleware/request-logger.ts","../src/route/types.ts","../src/server/create-server.ts","../src/server/helpers.ts","../src/server/start-server.ts","../src/server/banner.ts","../src/server/validation.ts"],"names":["timestamp","newPath","existsSync","mkdirSync","join","unlinkSync","init_logger","init_config","dotenvConfig","dbLogger","init_factory","getDatabase","closeDatabase","init_manager","readdirSync","stat","statSync","dirname","readFileSync","packageSchemas","schema","txLogger","init_helpers","cacheLogger","routeLogger","count","discoverFunctionRoutes","maskSensitiveData","getRedis","Hono","serverLogger"],"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 const valueStr = typeof value === 'string' ? value : String(value);\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Slack 메시지 포맷\n */\nexport function formatSlack(metadata: LogMetadata): string\n{\n const emoji = {\n debug: ':bug:',\n info: ':information_source:',\n warn: ':warning:',\n error: ':x:',\n fatal: ':fire:',\n };\n\n const parts: string[] = [];\n\n parts.push(`${emoji[metadata.level]} *${metadata.level.toUpperCase()}*`);\n\n if (metadata.module)\n {\n parts.push(`\\`[${metadata.module}]\\``);\n }\n\n parts.push(metadata.message);\n\n let message = parts.join(' ');\n\n if (metadata.context)\n {\n message += '\\n```\\n' + JSON.stringify(metadata.context, null, 2) + '\\n```';\n }\n\n if (metadata.error)\n {\n message += '\\n```\\n' + formatError(metadata.error) + '\\n```';\n }\n\n return message;\n}\n\n/**\n * Email 제목 생성\n */\nexport function formatEmailSubject(metadata: LogMetadata): string\n{\n const prefix = `[${metadata.level.toUpperCase()}]`;\n const module = metadata.module ? `[${metadata.module}]` : '';\n\n return `${prefix}${module} ${metadata.message}`;\n}\n\n/**\n * Email 본문 생성 (HTML)\n */\nexport function formatEmailBody(metadata: LogMetadata): string\n{\n const parts: string[] = [];\n\n parts.push('<html>');\n parts.push('<body style=\"font-family: monospace; padding: 20px;\">');\n\n // 헤더\n parts.push(`<h2 style=\"color: ${getEmailColor(metadata.level)};\">`);\n parts.push(`${metadata.level.toUpperCase()}`);\n parts.push('</h2>');\n\n // 시간\n parts.push('<p>');\n parts.push(`<strong>Timestamp:</strong> ${formatTimestamp(metadata.timestamp)}`);\n parts.push('</p>');\n\n // 모듈\n if (metadata.module)\n {\n parts.push('<p>');\n parts.push(`<strong>Module:</strong> ${metadata.module}`);\n parts.push('</p>');\n }\n\n // 메시지\n parts.push('<p>');\n parts.push(`<strong>Message:</strong> ${metadata.message}`);\n parts.push('</p>');\n\n // Context\n if (metadata.context)\n {\n parts.push('<h3>Context</h3>');\n parts.push('<pre style=\"background: #f4f4f4; padding: 10px; border-radius: 4px;\">');\n parts.push(JSON.stringify(metadata.context, null, 2));\n parts.push('</pre>');\n }\n\n // 에러\n if (metadata.error)\n {\n parts.push('<h3>Error Stack Trace</h3>');\n parts.push('<pre style=\"background: #fff0f0; padding: 10px; border-radius: 4px;\">');\n parts.push(formatError(metadata.error));\n parts.push('</pre>');\n }\n\n parts.push('</body>');\n parts.push('</html>');\n\n return parts.join('\\n');\n}\n\n/**\n * Email 레벨별 컬러\n */\nfunction getEmailColor(level: LogLevel): string\n{\n const colors: Record<LogLevel, string> = {\n debug: '#00BCD4',\n info: '#4CAF50',\n warn: '#FF9800',\n error: '#F44336',\n fatal: '#9C27B0',\n };\n\n return colors[level];\n}","/**\n * Logger Class\n *\n * Central logging class with multiple transports, child loggers, and sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata, LoggerConfig, Transport } from './types';\nimport { LOG_LEVEL_PRIORITY } from './types';\nimport { maskSensitiveData } from './formatters';\n\n/**\n * Logger class\n */\nexport class Logger\n{\n private readonly config: LoggerConfig;\n private readonly module?: string;\n\n constructor(config: LoggerConfig)\n {\n this.config = config;\n this.module = config.module;\n }\n\n /**\n * Get current log level\n */\n get level(): LogLevel\n {\n return this.config.level;\n }\n\n /**\n * Create child logger (per module)\n */\n child(module: string): Logger\n {\n return new Logger({\n ...this.config,\n module,\n });\n }\n\n /**\n * Debug log\n */\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.log('debug', message, undefined, context);\n }\n\n /**\n * Info log\n */\n info(message: string, context?: Record<string, unknown>): void\n {\n this.log('info', message, undefined, context);\n }\n\n /**\n * Warn log\n */\n warn(message: string, context?: Record<string, unknown>): void;\n warn(message: string, error: Error, context?: Record<string, unknown>): void;\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('warn', message, errorOrContext, context);\n }\n else\n {\n this.log('warn', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Error log\n */\n error(message: string, context?: Record<string, unknown>): void;\n error(message: string, error: Error, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('error', message, errorOrContext, context);\n }\n else\n {\n this.log('error', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Fatal log\n */\n fatal(message: string, context?: Record<string, unknown>): void;\n fatal(message: string, error: Error, context?: Record<string, unknown>): void;\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('fatal', message, errorOrContext, context);\n }\n else\n {\n this.log('fatal', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Log processing (internal)\n */\n private log(level: LogLevel, message: string, error?: Error, context?: Record<string, unknown>): void\n {\n // Early return if log level is below configured level\n // This prevents unnecessary metadata creation and processing\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level])\n {\n return;\n }\n\n const metadata: LogMetadata = {\n timestamp: new Date(),\n level,\n message,\n module: this.module,\n error,\n // Mask sensitive information in context to prevent credential leaks\n context: context ? maskSensitiveData(context) as Record<string, unknown> : undefined,\n };\n\n // Pass to all enabled Transports\n this.processTransports(metadata);\n }\n\n /**\n * Process Transports\n */\n private processTransports(metadata: LogMetadata): void\n {\n const promises = this.config.transports\n .filter(transport => transport.enabled)\n .map(transport => this.safeTransportLog(transport, metadata));\n\n // Async processing to prevent Transport errors from blocking logs\n Promise.all(promises).catch(error =>\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport error: ${errorMessage}\\n`);\n });\n }\n\n /**\n * Transport log (error-safe)\n */\n private async safeTransportLog(transport: Transport, metadata: LogMetadata): Promise<void>\n {\n try\n {\n await transport.log(metadata);\n }\n catch (error)\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport \"${transport.name}\" failed: ${errorMessage}\\n`);\n }\n }\n\n /**\n * Close all Transports\n */\n async close(): Promise<void>\n {\n const closePromises = this.config.transports\n .filter(transport => transport.close)\n .map(transport => transport.close!());\n\n await Promise.all(closePromises);\n }\n}","/**\n * Console Transport\n *\n * 콘솔 출력 Transport\n *\n * ✅ 구현 완료:\n * - 콘솔 출력 (stdout/stderr)\n * - 컬러 출력 지원\n * - 로그 레벨별 스트림 분리 (warn/error/fatal → stderr)\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (Transport 인터페이스)\n * - src/logger/formatters.ts (포맷터)\n * - src/logger/config.ts (설정)\n */\n\nimport type { Transport, LogMetadata, LogLevel, ConsoleTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatConsole } from '../formatters';\n\n/**\n * Console Transport\n */\nexport class ConsoleTransport implements Transport\n{\n public readonly name = 'console';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private colorize: boolean;\n\n constructor(config: ConsoleTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.colorize = config.colorize ?? true;\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // 포맷팅\n const message = formatConsole(metadata, this.colorize);\n\n // warn/error/fatal은 stderr로, 나머지는 stdout으로\n if (metadata.level === 'warn' || metadata.level === 'error' || metadata.level === 'fatal')\n {\n console.error(message);\n }\n else\n {\n console.log(message);\n }\n }\n}","/**\n * File Transport\n *\n * File output transport with date and size-based rotation, automatic cleanup.\n */\n\nimport { createWriteStream, existsSync, mkdirSync, statSync, readdirSync, unlinkSync, renameSync } from 'fs';\nimport type { WriteStream } from 'fs';\nimport { join } from 'path';\nimport type { Transport, LogMetadata, LogLevel, FileTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatJSON } from '../formatters';\n\n/**\n * File Transport\n */\nexport class FileTransport implements Transport\n{\n public readonly name = 'file';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private readonly logDir: string;\n private readonly maxFileSize: number;\n private readonly maxFiles: number;\n private currentStream: WriteStream | null = null;\n private currentFilename: string | null = null;\n\n constructor(config: FileTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.logDir = config.logDir;\n this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024; // 10MB\n this.maxFiles = config.maxFiles ?? 10;\n\n // 로그 디렉토리가 없으면 생성\n if (!existsSync(this.logDir))\n {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // JSON 포맷으로 변환\n const message = formatJSON(metadata);\n\n // 파일명: YYYY-MM-DD.log\n const filename = this.getLogFilename(metadata.timestamp);\n\n // 날짜가 변경되면 스트림 교체\n if (this.currentFilename !== filename)\n {\n await this.rotateStream(filename);\n await this.cleanOldFiles(); // 오래된 파일 정리\n }\n // 파일 크기 체크 및 로테이션\n else if (this.currentFilename)\n {\n await this.checkAndRotateBySize();\n }\n\n // 스트림에 쓰기\n if (this.currentStream)\n {\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.write(message + '\\n', 'utf-8', (error: Error | null | undefined) =>\n {\n if (error)\n {\n // 파일 쓰기 실패 시 stderr로 출력 (fallback)\n process.stderr.write(`[FileTransport] Failed to write log: ${error.message}\\n`);\n reject(error);\n }\n else\n {\n resolve();\n }\n });\n });\n }\n }\n\n /**\n * 스트림 교체 (날짜 변경 시)\n */\n private async rotateStream(filename: string): Promise<void>\n {\n // 기존 스트림 닫기\n if (this.currentStream)\n {\n await this.closeStream();\n }\n\n // 새 스트림 생성\n const filepath = join(this.logDir, filename);\n\n this.currentStream = createWriteStream(filepath, {\n flags: 'a', // append mode\n encoding: 'utf-8',\n });\n\n this.currentFilename = filename;\n\n // 스트림 에러 핸들링\n this.currentStream.on('error', (error) =>\n {\n process.stderr.write(`[FileTransport] Stream error: ${error.message}\\n`);\n // 에러 발생 시 스트림 초기화\n this.currentStream = null;\n this.currentFilename = null;\n });\n }\n\n /**\n * 현재 스트림 닫기\n */\n private async closeStream(): Promise<void>\n {\n if (!this.currentStream)\n {\n return;\n }\n\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.end((error: Error | null | undefined) =>\n {\n if (error)\n {\n reject(error);\n }\n else\n {\n this.currentStream = null;\n this.currentFilename = null;\n resolve();\n }\n });\n });\n }\n\n /**\n * 파일 크기 체크 및 크기 기반 로테이션\n */\n private async checkAndRotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n const filepath = join(this.logDir, this.currentFilename);\n\n // 파일이 존재하지 않으면 스킵\n if (!existsSync(filepath))\n {\n return;\n }\n\n try\n {\n const stats = statSync(filepath);\n\n // 파일 크기가 maxFileSize를 초과하면 로테이션\n if (stats.size >= this.maxFileSize)\n {\n await this.rotateBySize();\n }\n }\n catch (error)\n {\n // 파일 stat 실패 시 무시\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 크기 기반 로테이션 수행\n * 예: 2025-01-01.log -> 2025-01-01.1.log, 2025-01-01.1.log -> 2025-01-01.2.log\n */\n private async rotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n // 기존 스트림 닫기\n await this.closeStream();\n\n const baseName = this.currentFilename.replace(/\\.log$/, '');\n const files = readdirSync(this.logDir);\n\n // 현재 날짜의 로그 파일들 찾기 (예: 2025-01-01.log, 2025-01-01.1.log, ...)\n const relatedFiles = files\n .filter(file => file.startsWith(baseName) && file.endsWith('.log'))\n .sort()\n .reverse(); // 역순 정렬로 높은 번호부터 처리\n\n // 기존 파일들을 번호 증가시켜 이동 (예: .1.log -> .2.log)\n for (const file of relatedFiles)\n {\n const match = file.match(/\\.(\\d+)\\.log$/);\n if (match)\n {\n const oldNum = parseInt(match[1], 10);\n const newNum = oldNum + 1;\n const oldPath = join(this.logDir, file);\n const newPath = join(this.logDir, `${baseName}.${newNum}.log`);\n\n try\n {\n renameSync(oldPath, newPath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}\\n`);\n }\n }\n }\n\n // 현재 파일을 .1.log로 이동\n const currentPath = join(this.logDir, this.currentFilename);\n const newPath = join(this.logDir, `${baseName}.1.log`);\n\n try\n {\n if (existsSync(currentPath))\n {\n renameSync(currentPath, newPath);\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}\\n`);\n }\n\n // 새 스트림 생성 (동일한 파일명으로)\n await this.rotateStream(this.currentFilename);\n }\n\n /**\n * 오래된 로그 파일 정리\n * maxFiles 개수를 초과하는 로그 파일 삭제\n */\n private async cleanOldFiles(): Promise<void>\n {\n try\n {\n // 디렉토리가 존재하지 않으면 스킵\n if (!existsSync(this.logDir))\n {\n return;\n }\n\n const files = readdirSync(this.logDir);\n\n // .log로 끝나는 파일만 필터링 후 수정 시간 기준 정렬\n const logFiles = files\n .filter(file => file.endsWith('.log'))\n .map(file =>\n {\n const filepath = join(this.logDir, file);\n const stats = statSync(filepath);\n return { file, mtime: stats.mtime };\n })\n .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); // 최신 파일이 앞으로\n\n // maxFiles를 초과하는 오래된 파일들 삭제\n if (logFiles.length > this.maxFiles)\n {\n const filesToDelete = logFiles.slice(this.maxFiles);\n\n for (const { file } of filesToDelete)\n {\n const filepath = join(this.logDir, file);\n try\n {\n unlinkSync(filepath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to delete old file \"${file}\": ${errorMessage}\\n`);\n }\n }\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 날짜별 로그 파일명 생성\n */\n private getLogFilename(date: Date): string\n {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}.log`;\n }\n\n async close(): Promise<void>\n {\n // 스트림 정리\n await this.closeStream();\n }\n}","/**\n * Logger Configuration\n *\n * Environment-based logger configuration with validation for console, file, Slack, and Email transports.\n */\n\nimport { existsSync, accessSync, constants, mkdirSync, writeFileSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type {\n LogLevel,\n ConsoleTransportConfig,\n FileTransportConfig,\n SlackTransportConfig,\n EmailTransportConfig,\n} from './types';\n\n/**\n * Check if file logging is enabled (for self-hosted)\n */\nexport function isFileLoggingEnabled(): boolean\n{\n return process.env.LOGGER_FILE_ENABLED === 'true';\n}\n\n/**\n * Get default log level by environment\n */\nexport function getDefaultLogLevel(): LogLevel\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment)\n {\n return 'debug';\n }\n\n if (isProduction)\n {\n return 'info';\n }\n\n // Test environment\n return 'warn';\n}\n\n/**\n * Console Transport configuration\n */\nexport function getConsoleConfig(): ConsoleTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'debug',\n enabled: true,\n colorize: !isProduction, // Dev: colored output, Production: plain text\n };\n}\n\n/**\n * File Transport configuration\n */\nexport function getFileConfig(): FileTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'info',\n enabled: isProduction, // File logging in production only\n logDir: process.env.LOG_DIR || './logs',\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n };\n}\n\n/**\n * Slack Transport configuration\n */\nexport function getSlackConfig(): SlackTransportConfig | null\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return null; // Disabled if not configured\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'error', // Send error and above to Slack\n enabled: isProduction, // Enabled in production only\n webhookUrl,\n channel: process.env.SLACK_CHANNEL,\n username: process.env.SLACK_USERNAME || 'Logger Bot',\n };\n}\n\n/**\n * Email Transport configuration\n */\nexport function getEmailConfig(): EmailTransportConfig | null\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // Disabled if required settings are missing\n if (!smtpHost || !smtpPort || !emailFrom || !emailTo)\n {\n return null;\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'fatal', // Send fatal level only via email\n enabled: isProduction, // Enabled in production only\n from: emailFrom,\n to: emailTo.split(',').map(email => email.trim()),\n smtpHost,\n smtpPort: parseInt(smtpPort, 10),\n smtpUser: process.env.SMTP_USER,\n smtpPassword: process.env.SMTP_PASSWORD,\n };\n}\n\n/**\n * Validate directory path and write permissions\n */\nfunction validateDirectoryWritable(dirPath: string): void\n{\n // Check if directory exists\n if (!existsSync(dirPath))\n {\n // Try to create directory\n try\n {\n mkdirSync(dirPath, { recursive: true });\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to create log directory \"${dirPath}\": ${errorMessage}`);\n }\n }\n\n // Check write permission\n try\n {\n accessSync(dirPath, constants.W_OK);\n }\n catch\n {\n throw new Error(`Log directory \"${dirPath}\" is not writable. Please check permissions.`);\n }\n\n // Try to write a test file\n const testFile = join(dirPath, '.logger-write-test');\n try\n {\n writeFileSync(testFile, 'test', 'utf-8');\n unlinkSync(testFile);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Cannot write to log directory \"${dirPath}\": ${errorMessage}`);\n }\n}\n\n/**\n * Validate file transport configuration\n */\nfunction validateFileConfig(): void\n{\n if (!isFileLoggingEnabled())\n {\n return; // File logging disabled, skip validation\n }\n\n const logDir = process.env.LOG_DIR;\n\n // Check if LOG_DIR is set\n if (!logDir)\n {\n throw new Error(\n 'LOG_DIR environment variable is required when LOGGER_FILE_ENABLED=true. ' +\n 'Example: LOG_DIR=/var/log/myapp'\n );\n }\n\n // Validate directory\n validateDirectoryWritable(logDir);\n}\n\n/**\n * Validate Slack transport configuration\n */\nfunction validateSlackConfig(): void\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return; // Slack disabled, skip validation\n }\n\n // Validate webhook URL format\n if (!webhookUrl.startsWith('https://hooks.slack.com/'))\n {\n throw new Error(\n `Invalid SLACK_WEBHOOK_URL: \"${webhookUrl}\". ` +\n 'Slack webhook URLs must start with \"https://hooks.slack.com/\"'\n );\n }\n}\n\n/**\n * Validate Email transport configuration\n */\nfunction validateEmailConfig(): void\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // If any email config is set, all required fields must be present\n const hasAnyEmailConfig = smtpHost || smtpPort || emailFrom || emailTo;\n if (!hasAnyEmailConfig)\n {\n return; // Email disabled, skip validation\n }\n\n // Validate all required fields\n const missingFields: string[] = [];\n if (!smtpHost) missingFields.push('SMTP_HOST');\n if (!smtpPort) missingFields.push('SMTP_PORT');\n if (!emailFrom) missingFields.push('EMAIL_FROM');\n if (!emailTo) missingFields.push('EMAIL_TO');\n\n if (missingFields.length > 0)\n {\n throw new Error(\n `Email transport configuration incomplete. Missing: ${missingFields.join(', ')}. ` +\n 'Either set all required fields or remove all email configuration.'\n );\n }\n\n // Validate SMTP port is a number\n const port = parseInt(smtpPort!, 10);\n if (isNaN(port) || port < 1 || port > 65535)\n {\n throw new Error(\n `Invalid SMTP_PORT: \"${smtpPort}\". Must be a number between 1 and 65535.`\n );\n }\n\n // Validate email format (basic check)\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(emailFrom!))\n {\n throw new Error(`Invalid EMAIL_FROM format: \"${emailFrom}\"`);\n }\n\n // Validate email recipients\n const recipients = emailTo!.split(',').map(e => e.trim());\n for (const email of recipients)\n {\n if (!emailRegex.test(email))\n {\n throw new Error(`Invalid email address in EMAIL_TO: \"${email}\"`);\n }\n }\n}\n\n/**\n * Validate environment variables\n */\nfunction validateEnvironment(): void\n{\n const nodeEnv = process.env.NODE_ENV;\n\n if (!nodeEnv)\n {\n process.stderr.write(\n '[Logger] Warning: NODE_ENV is not set. Defaulting to test environment.\\n'\n );\n }\n // Allow any NODE_ENV value (development, production, test, staging, local, etc.)\n // No validation needed - users can use custom environments\n}\n\n/**\n * Validate all logger configuration\n * Throws an error if configuration is invalid\n */\nexport function validateConfig(): void\n{\n try\n {\n validateEnvironment();\n validateFileConfig();\n validateSlackConfig();\n validateEmailConfig();\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n throw new Error(`[Logger] Configuration validation failed: ${error.message}`);\n }\n throw error;\n }\n}","/**\n * 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 * Logger Module Exports\n *\n * Entry point for logger module\n *\n * 💡 Usage examples:\n * ```typescript\n * import { logger } from '@spfn/core';\n *\n * // Basic usage\n * logger.info('Application started');\n * logger.error('Connection failed', error);\n *\n * // Create module-specific logger\n * const dbLogger = logger.child('database');\n * dbLogger.debug('Connecting to database...');\n *\n * // Add context\n * logger.warn('Retry attempt', { attempt: 3, delay: 1000 });\n * ```\n *\n * 💡 Transports:\n * - Console: Colored output for development, JSON for production\n * - File: Automatic file logging in production (LOG_FILE_ENABLED=true)\n * - Future: Slack, Email, and custom transports\n */\n\n// Logger Instance\nexport { logger } from './factory.js';\nexport { Logger } from './logger.js';\n\n// Types\nexport type { LogLevel, Transport } from './types.js';\n","/**\n * Function Route Discovery\n *\n * Automatically discovers and loads routes from SPFN functions\n *\n * NOTE: Contract-based routing - routes use absolute paths defined in contracts\n * No basePath needed - each contract defines its own absolute path (e.g., '/cms/labels')\n */\n\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { logger } from '../logger';\n\nconst routeLogger = logger.child('function-routes');\n\nexport type FunctionRouteInfo = {\n packageName: string;\n routesDir: string;\n packagePath: string;\n prefix?: string; // From package.json spfn.prefix\n};\n\n/**\n * Discover SPFN functions with route declarations\n *\n * Scans node_modules for packages that declare routes in package.json\n *\n * Example package.json:\n * ```json\n * {\n * \"name\": \"@spfn/cms\",\n * \"spfn\": {\n * \"routes\": {\n * \"dir\": \"./dist/routes\"\n * }\n * }\n * }\n * ```\n */\nexport function discoverFunctionRoutes(cwd: string = process.cwd()): FunctionRouteInfo[]\n{\n const functions: FunctionRouteInfo[] = [];\n const nodeModulesPath = join(cwd, 'node_modules');\n\n try\n {\n // Read package.json to get dependencies\n const projectPkgPath = join(cwd, 'package.json');\n const projectPkg = JSON.parse(readFileSync(projectPkgPath, 'utf-8'));\n\n const dependencies = {\n ...projectPkg.dependencies,\n ...projectPkg.devDependencies,\n };\n\n // Scan each dependency for spfn.routes\n for (const [packageName] of Object.entries(dependencies))\n {\n // Only scan @spfn/* and packages starting with spfn-\n if (!packageName.startsWith('@spfn/') && !packageName.startsWith('spfn-'))\n {\n continue;\n }\n\n try\n {\n const pkgPath = join(nodeModulesPath, ...packageName.split('/'), 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n\n if (pkg.spfn?.routes?.dir)\n {\n const { dir } = pkg.spfn.routes;\n const prefix = pkg.spfn.prefix; // Read prefix from package.json\n const packagePath = dirname(pkgPath);\n const routesDir = join(packagePath, dir);\n\n functions.push({\n packageName,\n routesDir,\n packagePath,\n prefix, // Include prefix in function info\n });\n\n routeLogger.debug('Discovered function routes', {\n package: packageName,\n dir,\n prefix: prefix || '(none)',\n });\n }\n }\n catch (error)\n {\n // Silently skip packages that don't exist or can't be read\n // This is normal for optional dependencies or workspace links\n }\n }\n }\n catch (error)\n {\n routeLogger.warn('Failed to discover function routes', {\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n\n return functions;\n}","/**\n * Database Error Classes\n *\n * Type-safe error handling with custom error class hierarchy\n * Mapped to HTTP status codes for API responses\n */\n\n/**\n * Base Database Error\n *\n * Base class for all database-related errors\n */\nexport class DatabaseError<TDetails extends Record<string, unknown> = Record<string, unknown>> extends Error\n{\n public readonly statusCode: number;\n public readonly details?: TDetails;\n public readonly timestamp: Date;\n\n constructor(\n message: string,\n statusCode: number = 500,\n details?: TDetails\n )\n {\n super(message);\n this.name = 'DatabaseError';\n this.statusCode = statusCode;\n this.details = details;\n this.timestamp = new Date();\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * Serialize error for API response\n */\n toJSON()\n {\n return {\n name: this.name,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n timestamp: this.timestamp.toISOString()\n };\n }\n}\n\n/**\n * Connection Error (503 Service Unavailable)\n *\n * Database connection failure, connection pool exhaustion, etc.\n */\nexport class ConnectionError extends DatabaseError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 503, details);\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Query Error (500 Internal Server Error)\n *\n * SQL query execution failure, syntax errors, etc.\n */\nexport class QueryError extends DatabaseError\n{\n constructor(message: string, statusCode: number = 500, details?: Record<string, any>)\n {\n super(message, statusCode, details);\n this.name = 'QueryError';\n }\n}\n\n/**\n * Entity Not Found Error (404 Not Found)\n *\n * Database entity does not exist\n */\nexport class EntityNotFoundError extends QueryError\n{\n constructor(resource: string, id: string | number)\n {\n super(`${resource} with id ${id} not found`, 404, { resource, id });\n this.name = 'EntityNotFoundError';\n }\n}\n\n/**\n * Constraint Violation Error (400 Bad Request)\n *\n * Database constraint violation (NOT NULL, CHECK, FOREIGN KEY, etc.)\n * This is different from HTTP ValidationError which validates request input\n */\nexport class ConstraintViolationError extends QueryError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'ConstraintViolationError';\n }\n}\n\n/**\n * Transaction Error (500 Internal Server Error)\n *\n * Transaction start/commit/rollback failure\n */\nexport class TransactionError extends DatabaseError\n{\n constructor(message: string, statusCode: number = 500, details?: Record<string, any>)\n {\n super(message, statusCode, details);\n this.name = 'TransactionError';\n }\n}\n\n/**\n * Deadlock Error (409 Conflict)\n *\n * Database deadlock detected\n */\nexport class DeadlockError extends TransactionError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 409, details);\n this.name = 'DeadlockError';\n }\n}\n\n/**\n * Duplicate Entry Error (409 Conflict)\n *\n * Unique constraint violation (e.g., duplicate email)\n */\nexport class DuplicateEntryError extends QueryError\n{\n constructor(field: string, value: string | number)\n {\n super(`${field} '${value}' already exists`, 409, { field, value });\n this.name = 'DuplicateEntryError';\n }\n}","/**\n * HTTP Error Classes\n *\n * Standard HTTP error classes for API responses\n * Covers common HTTP status codes beyond database errors\n */\n\n/**\n * Base HTTP Error\n *\n * Base class for all HTTP-related errors\n */\nexport class HttpError<TDetails extends Record<string, unknown> = Record<string, unknown>> extends Error\n{\n public readonly statusCode: number;\n public readonly details?: TDetails;\n public readonly timestamp: Date;\n\n constructor(\n message: string,\n statusCode: number,\n details?: TDetails\n )\n {\n super(message);\n this.name = 'HttpError';\n this.statusCode = statusCode;\n this.details = details;\n this.timestamp = new Date();\n Error.captureStackTrace(this, this.constructor);\n }\n\n /**\n * Serialize error for API response\n */\n toJSON()\n {\n return {\n name: this.name,\n message: this.message,\n statusCode: this.statusCode,\n details: this.details,\n timestamp: this.timestamp.toISOString()\n };\n }\n}\n\n/**\n * Bad Request Error (400)\n *\n * Generic bad request - malformed syntax, invalid parameters, etc.\n */\nexport class BadRequestError extends HttpError\n{\n constructor(message: string = 'Bad request', details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'BadRequestError';\n }\n}\n\n/**\n * Validation Error (400)\n *\n * Input validation failure (request params, query, body)\n * Used by contract-based routing for automatic validation\n */\nexport class ValidationError extends HttpError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Unauthorized Error (401)\n *\n * Authentication required or authentication failed\n */\nexport class UnauthorizedError extends HttpError\n{\n constructor(message: string = 'Authentication required', details?: Record<string, any>)\n {\n super(message, 401, details);\n this.name = 'UnauthorizedError';\n }\n}\n\n/**\n * Forbidden Error (403)\n *\n * Authenticated but lacks permission to access resource\n */\nexport class ForbiddenError extends HttpError\n{\n constructor(message: string = 'Access forbidden', details?: Record<string, any>)\n {\n super(message, 403, details);\n this.name = 'ForbiddenError';\n }\n}\n\n/**\n * Not Found Error (404)\n *\n * Requested resource does not exist\n * Generic HTTP 404 error (for database-specific NotFoundError, see database-errors.ts)\n */\nexport class NotFoundError extends HttpError\n{\n constructor(message: string = 'Resource not found', details?: Record<string, any>)\n {\n super(message, 404, details);\n this.name = 'NotFoundError';\n }\n}\n\n/**\n * Conflict Error (409)\n *\n * Generic conflict - resource state conflict, concurrent modification, etc.\n * More general than DuplicateEntryError\n */\nexport class ConflictError extends HttpError\n{\n constructor(message: string = 'Resource conflict', details?: Record<string, any>)\n {\n super(message, 409, details);\n this.name = 'ConflictError';\n }\n}\n\n/**\n * Too Many Requests Error (429)\n *\n * Rate limit exceeded\n */\nexport class TooManyRequestsError extends HttpError\n{\n constructor(\n message: string = 'Too many requests',\n retryAfter?: number,\n details?: Record<string, any>\n )\n {\n const fullDetails = retryAfter\n ? { ...details, retryAfter }\n : details;\n\n super(message, 429, fullDetails);\n this.name = 'TooManyRequestsError';\n }\n}\n\n/**\n * Internal Server Error (500)\n *\n * Generic server error when no specific error type applies\n */\nexport class InternalServerError extends HttpError\n{\n constructor(message: string = 'Internal server error', details?: Record<string, any>)\n {\n super(message, 500, details);\n this.name = 'InternalServerError';\n }\n}\n\n/**\n * Unprocessable Entity Error (422)\n *\n * Request is well-formed but contains semantic errors\n */\nexport class UnprocessableEntityError extends HttpError\n{\n constructor(message: string = 'Unprocessable entity', details?: Record<string, any>)\n {\n super(message, 422, details);\n this.name = 'UnprocessableEntityError';\n }\n}\n\n/**\n * Service Unavailable Error (503)\n *\n * Service temporarily unavailable (maintenance, overload, etc.)\n */\nexport class ServiceUnavailableError extends HttpError\n{\n constructor(\n message: string = 'Service unavailable',\n retryAfter?: number,\n details?: Record<string, any>\n )\n {\n const fullDetails = retryAfter\n ? { ...details, retryAfter }\n : details;\n\n super(message, 503, fullDetails);\n this.name = 'ServiceUnavailableError';\n }\n}","/**\n * Error Utility Functions\n *\n * Generic error type checking utilities\n */\n\nimport { DatabaseError } from './database-errors.js';\nimport { HttpError } from './http-errors.js';\n\n/**\n * Check if error is a DatabaseError\n */\nexport function isDatabaseError(error: unknown): error is DatabaseError\n{\n return error instanceof DatabaseError;\n}\n\n/**\n * Check if error is an HttpError\n */\nexport function isHttpError(error: unknown): error is HttpError\n{\n return error instanceof HttpError;\n}\n\n/**\n * Check if error has a statusCode property\n */\nexport function hasStatusCode(error: unknown): error is { statusCode: number }\n{\n return (\n typeof error === 'object' &&\n error !== null &&\n 'statusCode' in error &&\n typeof (error as any).statusCode === 'number'\n );\n}\n","/**\n * Error Module Exports\n *\n * Entry point for error handling module (Pure re-export only)\n */\n\n// Database Error Classes\nexport {\n DatabaseError,\n ConnectionError,\n QueryError,\n EntityNotFoundError,\n ConstraintViolationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n} from './database-errors.js';\n\n// HTTP Error Classes\nexport {\n HttpError,\n BadRequestError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n TooManyRequestsError,\n UnprocessableEntityError,\n InternalServerError,\n ServiceUnavailableError,\n} from './http-errors.js';\n\n// Error Utilities\nexport {\n isDatabaseError,\n isHttpError,\n hasStatusCode,\n} from './error-utils.js';\n","/**\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}","/**\n * Environment Variable Management\n *\n * Centralized environment variable loading with dotenv priority support\n *\n * @example\n * ```typescript\n * import { loadEnvironment, requireEnvVar } from '@spfn/core/env';\n *\n * // Load environment variables\n * loadEnvironment({\n * debug: true,\n * required: ['DATABASE_URL'],\n * });\n *\n * // Get required variables\n * const dbUrl = requireEnvVar('DATABASE_URL');\n * ```\n *\n * @module env\n */\n\n// Core loader functions\nexport {\n loadEnvironment,\n getEnvVar,\n requireEnvVar,\n hasEnvVar,\n getEnvVars,\n isEnvironmentLoaded,\n resetEnvironment,\n} from './loader.js';\n\n// Type definitions\nexport type {\n LoadEnvironmentOptions,\n LoadResult,\n GetEnvOptions,\n} from './config.js';\n\nexport {\n ENV_FILE_PRIORITY,\n TEST_ONLY_FILES,\n} from './config.js';\n\n// Validation utilities\nexport {\n validateUrl,\n createUrlValidator,\n validateNumber,\n createNumberValidator,\n validateBoolean,\n parseBoolean,\n validateEnum,\n createEnumValidator,\n validatePattern,\n createPatternValidator,\n validateNotEmpty,\n validateMinLength,\n createMinLengthValidator,\n combineValidators,\n validatePostgresUrl,\n validateRedisUrl,\n} from './validator.js';","/**\n * PostgreSQL Error Conversion Utilities\n *\n * Converts PostgreSQL-specific error codes to custom error types\n * @see https://www.postgresql.org/docs/current/errcodes-appendix.html\n */\n\nimport {\n DatabaseError,\n ConnectionError,\n DuplicateEntryError,\n DeadlockError,\n ConstraintViolationError,\n QueryError,\n TransactionError,\n} from '../errors';\n\n/**\n * Extract field and value from PostgreSQL unique violation message\n *\n * Handles various formats:\n * - Simple: Key (email)=(test@example.com)\n * - Complex: Key (user_id, tenant_id)=(123, 456)\n * - With quotes: Key (\"field\")=('value')\n */\nfunction parseUniqueViolation(message: string): { field: string; value: string } | null\n{\n // Try multiple patterns for robustness\n const patterns = [\n // Standard format: Key (field)=(value)\n /Key \\(([^)]+)\\)=\\(([^)]+)\\)/i,\n // With quotes: Key (\"field\")=('value')\n /Key \\([\"']?([^)\"']+)[\"']?\\)=\\([\"']?([^)\"']+)[\"']?\\)/i,\n // Alternative format\n /Key `([^`]+)`=`([^`]+)`/i,\n ];\n\n for (const pattern of patterns)\n {\n const match = message.match(pattern);\n if (match)\n {\n // Clean up extracted values\n const field = match[1].trim().replace(/[\"'`]/g, '');\n const value = match[2].trim().replace(/[\"'`]/g, '');\n return { field, value };\n }\n }\n\n return null;\n}\n\n/**\n * Convert PostgreSQL error to custom DatabaseError\n *\n * Maps PostgreSQL error codes to appropriate error classes with correct status codes\n *\n * @param error - PostgreSQL error object (from pg driver or Drizzle)\n * @returns Custom DatabaseError instance\n *\n * @example\n * ```typescript\n * import { fromPostgresError } from '@spfn/core/db';\n *\n * try {\n * await db.insert(users).values(data);\n * } catch (pgError) {\n * throw fromPostgresError(pgError);\n * }\n * ```\n */\nexport function fromPostgresError(error: any): DatabaseError\n{\n const code = error?.code;\n const message = error?.message || 'Database error occurred';\n\n switch (code)\n {\n // Class 08 — Connection Exception\n case '08000': // connection_exception\n case '08001': // sqlclient_unable_to_establish_sqlconnection\n case '08003': // connection_does_not_exist\n case '08004': // sqlserver_rejected_establishment_of_sqlconnection\n case '08006': // connection_failure\n case '08007': // transaction_resolution_unknown\n case '08P01': // protocol_violation\n return new ConnectionError(message, { code });\n\n // Class 23 — Integrity Constraint Violation\n case '23000': // integrity_constraint_violation\n case '23001': // restrict_violation\n return new ConstraintViolationError(message, { code, constraint: 'integrity' });\n\n case '23502': // not_null_violation\n return new ConstraintViolationError(message, { code, constraint: 'not_null' });\n\n case '23503': // foreign_key_violation\n return new ConstraintViolationError(message, { code, constraint: 'foreign_key' });\n\n case '23505': // unique_violation\n const parsed = parseUniqueViolation(message);\n if (parsed)\n {\n return new DuplicateEntryError(parsed.field, parsed.value);\n }\n return new DuplicateEntryError('field', 'value');\n\n case '23514': // check_violation\n return new ConstraintViolationError(message, { code, constraint: 'check' });\n\n // Class 40 — Transaction Rollback\n case '40000': // transaction_rollback\n case '40001': // serialization_failure\n case '40002': // transaction_integrity_constraint_violation\n case '40003': // statement_completion_unknown\n return new TransactionError(message, 500, { code });\n\n case '40P01': // deadlock_detected\n return new DeadlockError(message, { code });\n\n // Class 42 — Syntax Error or Access Rule Violation\n case '42000': // syntax_error_or_access_rule_violation\n case '42601': // syntax_error\n case '42501': // insufficient_privilege\n case '42602': // invalid_name\n case '42622': // name_too_long\n case '42701': // duplicate_column\n case '42702': // ambiguous_column\n case '42703': // undefined_column\n case '42704': // undefined_object\n case '42P01': // undefined_table\n case '42P02': // undefined_parameter\n return new QueryError(message, 400, { code });\n\n // Class 53 — Insufficient Resources\n case '53000': // insufficient_resources\n case '53100': // disk_full\n case '53200': // out_of_memory\n case '53300': // too_many_connections\n return new ConnectionError(message, { code });\n\n // Class 57 — Operator Intervention\n case '57000': // operator_intervention\n case '57014': // query_canceled\n case '57P01': // admin_shutdown\n case '57P02': // crash_shutdown\n case '57P03': // cannot_connect_now\n return new ConnectionError(message, { code });\n\n // Default: Unknown error\n default:\n return new QueryError(message, 500, { code });\n }\n}","import postgres from 'postgres';\nimport type { Sql } from 'postgres';\n\nimport { logger } from '../../logger';\nimport { ConnectionError } from '../../errors';\nimport { fromPostgresError } from '../postgres-errors';\nimport type { PoolConfig, RetryConfig } from './config';\n\nconst dbLogger = logger.child('database');\n\n/**\n * 지연 함수\n */\nfunction delay(ms: number): Promise<void>\n{\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Exponential Backoff로 DB 연결 생성\n *\n * @param connectionString - PostgreSQL 연결 문자열\n * @param poolConfig - Connection Pool 설정\n * @param retryConfig - 재시도 설정\n * @returns PostgreSQL 클라이언트\n */\nexport async function createDatabaseConnection(\n connectionString: string,\n poolConfig: PoolConfig,\n retryConfig: RetryConfig\n) {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++)\n {\n try\n {\n // PostgreSQL 클라이언트 생성\n const client = postgres(connectionString, {\n max: poolConfig.max,\n idle_timeout: poolConfig.idleTimeout,\n });\n\n // 연결 테스트 쿼리\n await client`SELECT 1 as test`;\n\n // 연결 성공\n if (attempt > 0)\n {\n dbLogger.info(`Database connected successfully after ${attempt} retries`);\n }\n else\n {\n dbLogger.info('Database connected successfully');\n }\n\n return client;\n }\n catch (error)\n {\n lastError = fromPostgresError(error);\n\n // 마지막 시도가 아니면 재시도\n if (attempt < retryConfig.maxRetries)\n {\n // Exponential Backoff 계산\n const delayMs = Math.min(\n retryConfig.initialDelay * Math.pow(retryConfig.factor, attempt),\n retryConfig.maxDelay\n );\n\n dbLogger.warn(\n `Connection failed (attempt ${attempt + 1}/${retryConfig.maxRetries + 1}), retrying in ${delayMs}ms...`,\n lastError,\n {\n attempt: attempt + 1,\n maxRetries: retryConfig.maxRetries + 1,\n delayMs,\n }\n );\n\n await delay(delayMs);\n }\n }\n }\n\n // 모든 재시도 실패\n const errorMessage =\n `Failed to connect to database after ${retryConfig.maxRetries + 1} attempts: ${lastError?.message || 'Unknown error'}`;\n\n throw new ConnectionError(errorMessage);\n}\n\n/**\n * DB 연결 상태 확인\n *\n * @param client - PostgreSQL 클라이언트\n * @returns 연결 가능 여부\n */\nexport async function checkConnection(client: Sql): Promise<boolean>\n{\n try\n {\n await client`SELECT 1 as health_check`;\n return true;\n }\n catch (error)\n {\n dbLogger.error('Database health check failed', error as Error);\n return false;\n }\n}","/**\n * Database Configuration\n *\n * DB 연결 및 Connection Pool 설정\n *\n * ✅ 구현 완료:\n * - 환경별 Connection Pool 설정\n * - 재시도 설정 (Exponential Backoff)\n * - 환경변수 기반 설정\n *\n * 🔗 관련 파일:\n * - src/server/core/db/connection.ts (연결 로직)\n * - src/server/core/db/index.ts (메인 export)\n */\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\";\nimport type { Sql } from \"postgres\";\n\nexport interface DatabaseClients\n{\n /** Primary database for writes (or both read/write if no replica) */\n write?: PostgresJsDatabase;\n /** Replica database for reads (optional, falls back to write) */\n read?: PostgresJsDatabase;\n /** Raw postgres client for write operations (for cleanup) */\n writeClient?: Sql;\n /** Raw postgres client for read operations (for cleanup) */\n readClient?: Sql;\n}\n\n/**\n * Health check configuration\n */\nexport interface HealthCheckConfig\n{\n enabled: boolean;\n interval: number;\n reconnect: boolean;\n maxRetries: number;\n retryInterval: number;\n}\n\n/**\n * Query performance monitoring configuration\n */\nexport interface MonitoringConfig\n{\n enabled: boolean;\n slowThreshold: number;\n logQueries: boolean;\n}\n\n/**\n * Database initialization options\n */\nexport interface DatabaseOptions\n{\n /**\n * Connection pool configuration\n * Overrides environment variables and defaults\n */\n pool?: Partial<PoolConfig>;\n\n /**\n * Health check configuration\n * Periodic checks to ensure database connection is alive\n */\n healthCheck?: Partial<HealthCheckConfig>;\n\n /**\n * Query performance monitoring configuration\n * Tracks slow queries and logs performance metrics\n */\n monitoring?: Partial<MonitoringConfig>;\n}\n\n/**\n * Connection Pool 설정\n */\nexport interface PoolConfig\n{\n max: number; // 최대 연결 수\n idleTimeout: number; // 유휴 연결 타임아웃 (초)\n}\n\n/**\n * 재시도 설정\n */\nexport interface RetryConfig\n{\n maxRetries: number; // 최대 재시도 횟수\n initialDelay: number; // 초기 대기 시간 (ms)\n maxDelay: number; // 최대 대기 시간 (ms)\n factor: number; // 지수 증가 배수\n}\n\n// ============================================================================\n// Environment Variable Parsing Utilities\n// ============================================================================\n\n/**\n * Parse environment variable as number with production/development defaults\n *\n * @param key - Environment variable name\n * @param prodDefault - Default value for production\n * @param devDefault - Default value for development\n * @returns Parsed number or default based on NODE_ENV\n *\n * @example\n * ```typescript\n * const max = parseEnvNumber('DB_POOL_MAX', 20, 10);\n * // Production: 20, Development: 10, or parsed value from env\n * ```\n */\nfunction parseEnvNumber(\n key: string,\n prodDefault: number,\n devDefault: number\n): number\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const envValue = parseInt(process.env[key] || '', 10);\n\n // If parsing fails (NaN), use environment-based default\n return isNaN(envValue)\n ? (isProduction ? prodDefault : devDefault)\n : envValue;\n}\n\n/**\n * Parse environment variable as boolean\n *\n * @param key - Environment variable name\n * @param defaultValue - Default value if not set\n * @returns Boolean value\n *\n * @example\n * ```typescript\n * const enabled = parseEnvBoolean('DB_HEALTH_CHECK_ENABLED', true);\n * // Returns true if env var is 'true', false if 'false', or default\n * ```\n */\nfunction parseEnvBoolean(key: string, defaultValue: boolean): boolean\n{\n const value = process.env[key];\n if (value === undefined) return defaultValue;\n return value.toLowerCase() === 'true';\n}\n\n// ============================================================================\n// Configuration Builders\n// ============================================================================\n\n/**\n * 환경별 Connection Pool 설정\n *\n * 우선순위:\n * 1. options 파라미터 (ServerConfig에서 전달)\n * 2. 환경변수 (DB_POOL_MAX, DB_POOL_IDLE_TIMEOUT)\n * 3. 기본값 (NODE_ENV에 따라)\n *\n * @param options - Optional pool configuration from ServerConfig\n * @returns Pool configuration\n *\n * @example\n * ```typescript\n * // 1. ServerConfig priority (highest)\n * const config = getPoolConfig({ max: 50, idleTimeout: 60 });\n *\n * // 2. Environment variable priority\n * // DB_POOL_MAX=30 DB_POOL_IDLE_TIMEOUT=45\n * const config = getPoolConfig();\n *\n * // 3. Default (lowest)\n * // Production: max=20, idleTimeout=30\n * // Development: max=10, idleTimeout=20\n * ```\n */\nexport function getPoolConfig(options?: Partial<PoolConfig>): PoolConfig\n{\n return {\n max: options?.max ?? parseEnvNumber('DB_POOL_MAX', 20, 10),\n idleTimeout: options?.idleTimeout ?? parseEnvNumber('DB_POOL_IDLE_TIMEOUT', 30, 20),\n };\n}\n\n/**\n * 환경별 재시도 설정\n *\n * 우선순위: 환경변수 > 기본값 (NODE_ENV에 따라)\n *\n * @returns Retry configuration\n *\n * @example\n * ```typescript\n * // Environment variables (highest priority)\n * // DB_RETRY_MAX=10\n * // DB_RETRY_INITIAL_DELAY=200\n * const config = getRetryConfig();\n *\n * // Defaults (lowest priority)\n * // Production: 5 retries, 100ms initial, 10s max, factor 2\n * // Development: 3 retries, 50ms initial, 5s max, factor 2\n * ```\n */\nexport function getRetryConfig(): RetryConfig\n{\n return {\n maxRetries: parseEnvNumber('DB_RETRY_MAX', 5, 3),\n initialDelay: parseEnvNumber('DB_RETRY_INITIAL_DELAY', 100, 50),\n maxDelay: parseEnvNumber('DB_RETRY_MAX_DELAY', 10000, 5000),\n factor: parseEnvNumber('DB_RETRY_FACTOR', 2, 2),\n };\n}\n\n/**\n * Build health check configuration with priority resolution\n *\n * 우선순위: options > env > defaults\n *\n * @param options - Optional health check configuration\n * @returns Health check configuration\n *\n * @example\n * ```typescript\n * // Custom options (highest priority)\n * const config = buildHealthCheckConfig({ enabled: false });\n *\n * // Environment variables\n * // DB_HEALTH_CHECK_ENABLED=true\n * // DB_HEALTH_CHECK_INTERVAL=30000\n * const config = buildHealthCheckConfig();\n *\n * // Defaults (lowest priority)\n * // enabled: true, interval: 60000ms, reconnect: true\n * ```\n */\nexport function buildHealthCheckConfig(options?: Partial<HealthCheckConfig>): HealthCheckConfig\n{\n return {\n enabled: options?.enabled\n ?? parseEnvBoolean('DB_HEALTH_CHECK_ENABLED', true),\n interval: options?.interval\n ?? parseEnvNumber('DB_HEALTH_CHECK_INTERVAL', 60000, 60000),\n reconnect: options?.reconnect\n ?? parseEnvBoolean('DB_HEALTH_CHECK_RECONNECT', true),\n maxRetries: options?.maxRetries\n ?? parseEnvNumber('DB_HEALTH_CHECK_MAX_RETRIES', 3, 3),\n retryInterval: options?.retryInterval\n ?? parseEnvNumber('DB_HEALTH_CHECK_RETRY_INTERVAL', 5000, 5000),\n };\n}\n\n/**\n * Build monitoring configuration with priority resolution\n *\n * 우선순위: options > env > defaults\n *\n * @param options - Optional monitoring configuration\n * @returns Monitoring configuration\n *\n * @example\n * ```typescript\n * // Custom options (highest priority)\n * const config = buildMonitoringConfig({ slowThreshold: 2000 });\n *\n * // Environment variables\n * // DB_MONITORING_ENABLED=true\n * // DB_MONITORING_SLOW_THRESHOLD=500\n * const config = buildMonitoringConfig();\n *\n * // Defaults (lowest priority)\n * // Development: enabled=true, slowThreshold=1000ms, logQueries=false\n * // Production: enabled=false, slowThreshold=1000ms, logQueries=false\n * ```\n */\nexport function buildMonitoringConfig(options?: Partial<MonitoringConfig>): MonitoringConfig\n{\n const isDevelopment = process.env.NODE_ENV !== 'production';\n\n return {\n enabled: options?.enabled\n ?? parseEnvBoolean('DB_MONITORING_ENABLED', isDevelopment),\n slowThreshold: options?.slowThreshold\n ?? parseEnvNumber('DB_MONITORING_SLOW_THRESHOLD', 1000, 1000),\n logQueries: options?.logQueries\n ?? parseEnvBoolean('DB_MONITORING_LOG_QUERIES', false),\n };\n}","/**\n * Database factory with automatic environment variable detection\n * Supports: Single primary, Primary + Replica\n */\n\nimport { drizzle } from 'drizzle-orm/postgres-js';\n\nimport { logger } from '../../logger';\nimport { loadEnvironment } from '../../env';\nimport { createDatabaseConnection } from './connection.js';\nimport { getPoolConfig, getRetryConfig, type DatabaseOptions, type DatabaseClients, type PoolConfig, type RetryConfig } from './config.js';\n\nconst dbLogger = logger.child('database');\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Database configuration pattern types\n *\n * Represents different ways to configure database connections via environment variables.\n */\ntype DatabasePattern =\n | { type: 'write-read'; write: string; read: string } // Explicit write/read separation\n | { type: 'legacy'; primary: string; replica: string } // Legacy replica pattern\n | { type: 'single'; url: string } // Single database\n | { type: 'none' }; // No configuration\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if any database configuration exists in environment\n */\nfunction hasDatabaseConfig(): boolean\n{\n return !!(\n process.env.DATABASE_URL ||\n process.env.DATABASE_WRITE_URL ||\n process.env.DATABASE_READ_URL\n );\n}\n\n/**\n * Detect database configuration pattern from environment variables\n *\n * Priority order (highest to lowest):\n * 1. write-read: DATABASE_WRITE_URL + DATABASE_READ_URL (explicit separation)\n * 2. legacy: DATABASE_URL + DATABASE_REPLICA_URL (backward compatibility)\n * 3. single: DATABASE_URL (most common)\n * 4. single: DATABASE_WRITE_URL (write-only, no replica)\n * 5. none: No configuration found\n *\n * @returns Detected database configuration pattern\n *\n * @example\n * ```typescript\n * const pattern = detectDatabasePattern();\n *\n * if (pattern.type === 'write-read') {\n * console.log(`Write: ${pattern.write}, Read: ${pattern.read}`);\n * }\n * ```\n */\nfunction detectDatabasePattern(): DatabasePattern\n{\n // Priority 1: Explicit write/read separation (recommended)\n if (process.env.DATABASE_WRITE_URL && process.env.DATABASE_READ_URL)\n {\n return {\n type: 'write-read',\n write: process.env.DATABASE_WRITE_URL,\n read: process.env.DATABASE_READ_URL,\n };\n }\n\n // Priority 2: Legacy replica pattern (backward compatibility)\n if (process.env.DATABASE_URL && process.env.DATABASE_REPLICA_URL)\n {\n return {\n type: 'legacy',\n primary: process.env.DATABASE_URL,\n replica: process.env.DATABASE_REPLICA_URL,\n };\n }\n\n // Priority 3: Single primary (most common)\n if (process.env.DATABASE_URL)\n {\n return {\n type: 'single',\n url: process.env.DATABASE_URL,\n };\n }\n\n // Priority 4: Write-only (no replica)\n if (process.env.DATABASE_WRITE_URL)\n {\n return {\n type: 'single',\n url: process.env.DATABASE_WRITE_URL,\n };\n }\n\n // No configuration found\n return { type: 'none' };\n}\n\n/**\n * Create write and read database clients\n *\n * @param writeUrl - Write database connection string\n * @param readUrl - Read database connection string\n * @param poolConfig - Connection pool configuration\n * @param retryConfig - Retry configuration\n * @returns Database clients\n */\nasync function createWriteReadClients(\n writeUrl: string,\n readUrl: string,\n poolConfig: PoolConfig,\n retryConfig: RetryConfig\n): Promise<DatabaseClients>\n{\n const writeClient = await createDatabaseConnection(writeUrl, poolConfig, retryConfig);\n const readClient = await createDatabaseConnection(readUrl, poolConfig, retryConfig);\n\n return {\n write: drizzle(writeClient),\n read: drizzle(readClient),\n writeClient,\n readClient,\n };\n}\n\n/**\n * Create single database client (used for both read and write)\n *\n * @param url - Database connection string\n * @param poolConfig - Connection pool configuration\n * @param retryConfig - Retry configuration\n * @returns Database clients\n */\nasync function createSingleClient(\n url: string,\n poolConfig: PoolConfig,\n retryConfig: RetryConfig\n): Promise<DatabaseClients>\n{\n const client = await createDatabaseConnection(url, poolConfig, retryConfig);\n const db = drizzle(client);\n\n return {\n write: db,\n read: db,\n writeClient: client,\n readClient: client,\n };\n}\n\n/**\n * Create database client(s) from environment variables\n *\n * Supported patterns (priority order):\n * 1. Single primary: DATABASE_URL\n * 2. Primary + Replica: DATABASE_WRITE_URL + DATABASE_READ_URL\n * 3. Legacy replica: DATABASE_URL + DATABASE_REPLICA_URL\n *\n * @param options - Optional database configuration (pool settings, etc.)\n * @returns Database client(s) or undefined if no configuration found\n *\n * @example\n * ```bash\n * # Single primary (most common)\n * DATABASE_URL=postgresql://localhost:5432/mydb\n *\n * # Primary + Replica\n * DATABASE_WRITE_URL=postgresql://primary:5432/mydb\n * DATABASE_READ_URL=postgresql://replica:5432/mydb\n *\n * # Legacy (backward compatibility)\n * DATABASE_URL=postgresql://primary:5432/mydb\n * DATABASE_REPLICA_URL=postgresql://replica:5432/mydb\n * ```\n *\n * @example\n * ```typescript\n * // Custom pool configuration\n * const db = await createDatabaseFromEnv({\n * pool: { max: 50, idleTimeout: 60 }\n * });\n * ```\n */\nexport async function createDatabaseFromEnv(options?: DatabaseOptions): Promise<DatabaseClients>\n{\n // Load environment variables using centralized loader\n if (!hasDatabaseConfig())\n {\n dbLogger.debug('No DATABASE_URL found, loading environment variables');\n\n const result = loadEnvironment({\n debug: true,\n });\n\n dbLogger.debug('Environment variables loaded', {\n success: result.success,\n loaded: result.loaded.length,\n hasDatabaseUrl: !!process.env.DATABASE_URL,\n hasWriteUrl: !!process.env.DATABASE_WRITE_URL,\n hasReadUrl: !!process.env.DATABASE_READ_URL,\n });\n }\n\n // Quick exit if no database config\n if (!hasDatabaseConfig())\n {\n dbLogger.warn('No database configuration found', {\n cwd: process.cwd(),\n nodeEnv: process.env.NODE_ENV,\n checkedVars: ['DATABASE_URL', 'DATABASE_WRITE_URL', 'DATABASE_READ_URL'],\n });\n return { write: undefined, read: undefined };\n }\n\n try\n {\n const poolConfig = getPoolConfig(options?.pool);\n const retryConfig = getRetryConfig();\n const pattern = detectDatabasePattern();\n\n // Create database clients based on detected pattern\n switch (pattern.type)\n {\n case 'write-read':\n dbLogger.debug('Using write-read pattern', {\n write: pattern.write.replace(/:[^:@]+@/, ':***@'),\n read: pattern.read.replace(/:[^:@]+@/, ':***@'),\n });\n return await createWriteReadClients(\n pattern.write,\n pattern.read,\n poolConfig,\n retryConfig\n );\n\n case 'legacy':\n dbLogger.debug('Using legacy replica pattern', {\n primary: pattern.primary.replace(/:[^:@]+@/, ':***@'),\n replica: pattern.replica.replace(/:[^:@]+@/, ':***@'),\n });\n return await createWriteReadClients(\n pattern.primary,\n pattern.replica,\n poolConfig,\n retryConfig\n );\n\n case 'single':\n dbLogger.debug('Using single database pattern', {\n url: pattern.url.replace(/:[^:@]+@/, ':***@'),\n });\n return await createSingleClient(pattern.url, poolConfig, retryConfig);\n\n case 'none':\n dbLogger.warn('No database pattern detected');\n return { write: undefined, read: undefined };\n }\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n dbLogger.error('Failed to create database connection', {\n error: message,\n stage: 'initialization',\n hasWriteUrl: !!process.env.DATABASE_WRITE_URL,\n hasReadUrl: !!process.env.DATABASE_READ_URL,\n hasUrl: !!process.env.DATABASE_URL,\n hasReplicaUrl: !!process.env.DATABASE_REPLICA_URL,\n });\n\n // If DATABASE_URL is configured, connection failure should be fatal\n // This prevents the server from starting without a database connection\n throw new Error(`Database connection failed: ${message}`, { cause: error });\n }\n}","/**\n * Global Database State Management\n *\n * Manages global database instances using globalThis for persistence across module reloads.\n * This is particularly useful in development with hot module replacement (HMR).\n *\n * The singleton pattern ensures database connections persist even when modules are reloaded\n * during development (e.g., with tsx watch mode).\n */\n\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport type { Sql } from 'postgres';\nimport type { MonitoringConfig } from './config.js';\n\n// ============================================================================\n// Global Type Declarations\n// ============================================================================\n\n/**\n * Extend globalThis with database-specific properties\n *\n * Using globalThis allows database instances to persist across module reloads,\n * which is essential for development environments with hot module replacement.\n */\ndeclare global\n{\n var __SPFN_DB_WRITE__: PostgresJsDatabase<Record<string, unknown>> | undefined;\n var __SPFN_DB_READ__: PostgresJsDatabase<Record<string, unknown>> | undefined;\n var __SPFN_DB_WRITE_CLIENT__: Sql | undefined;\n var __SPFN_DB_READ_CLIENT__: Sql | undefined;\n var __SPFN_DB_HEALTH_CHECK__: NodeJS.Timeout | undefined;\n var __SPFN_DB_MONITORING__: MonitoringConfig | undefined;\n}\n\n// ============================================================================\n// Database Instance Accessors\n// ============================================================================\n\n/**\n * Get write database instance from global state\n */\nexport const getWriteInstance = (): PostgresJsDatabase<Record<string, unknown>> | undefined =>\n globalThis.__SPFN_DB_WRITE__;\n\n/**\n * Set write database instance in global state\n */\nexport const setWriteInstance = (instance: PostgresJsDatabase<Record<string, unknown>> | undefined): void => {\n globalThis.__SPFN_DB_WRITE__ = instance;\n};\n\n/**\n * Get read database instance from global state\n */\nexport const getReadInstance = (): PostgresJsDatabase<Record<string, unknown>> | undefined =>\n globalThis.__SPFN_DB_READ__;\n\n/**\n * Set read database instance in global state\n */\nexport const setReadInstance = (instance: PostgresJsDatabase<Record<string, unknown>> | undefined): void => {\n globalThis.__SPFN_DB_READ__ = instance;\n};\n\n// ============================================================================\n// Raw Client Accessors\n// ============================================================================\n\n/**\n * Get write client from global state (for cleanup)\n */\nexport const getWriteClient = (): Sql | undefined =>\n globalThis.__SPFN_DB_WRITE_CLIENT__;\n\n/**\n * Set write client in global state\n */\nexport const setWriteClient = (client: Sql | undefined): void => {\n globalThis.__SPFN_DB_WRITE_CLIENT__ = client;\n};\n\n/**\n * Get read client from global state (for cleanup)\n */\nexport const getReadClient = (): Sql | undefined =>\n globalThis.__SPFN_DB_READ_CLIENT__;\n\n/**\n * Set read client in global state\n */\nexport const setReadClient = (client: Sql | undefined): void => {\n globalThis.__SPFN_DB_READ_CLIENT__ = client;\n};\n\n// ============================================================================\n// Health Check Accessors\n// ============================================================================\n\n/**\n * Get health check interval from global state\n */\nexport const getHealthCheckInterval = (): NodeJS.Timeout | undefined =>\n globalThis.__SPFN_DB_HEALTH_CHECK__;\n\n/**\n * Set health check interval in global state\n */\nexport const setHealthCheckInterval = (interval: NodeJS.Timeout | undefined): void => {\n globalThis.__SPFN_DB_HEALTH_CHECK__ = interval;\n};\n\n// ============================================================================\n// Monitoring Config Accessors\n// ============================================================================\n\n/**\n * Get monitoring configuration from global state\n */\nexport const getMonitoringConfig = (): MonitoringConfig | undefined =>\n globalThis.__SPFN_DB_MONITORING__;\n\n/**\n * Set monitoring configuration in global state\n */\nexport const setMonitoringConfig = (config: MonitoringConfig | undefined): void => {\n globalThis.__SPFN_DB_MONITORING__ = config;\n};","/**\n * Database Health Check\n *\n * Periodic health checks for database connections with automatic reconnection.\n * Monitors both write and read database instances and attempts recovery on failure.\n */\n\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nimport { logger } from '../../logger';\nimport { createDatabaseFromEnv } from './factory.js';\nimport type { DatabaseOptions, HealthCheckConfig } from './config.js';\nimport {\n getHealthCheckInterval,\n setHealthCheckInterval,\n setWriteInstance,\n setReadInstance,\n setWriteClient,\n setReadClient,\n} from './global-state.js';\n\nconst dbLogger = logger.child('database');\n\n/**\n * Start database health check\n *\n * Periodically checks database connection health and attempts reconnection if enabled.\n * Automatically started by initDatabase() when health check is enabled.\n *\n * @param config - Health check configuration\n * @param options - Optional database configuration (pool settings, etc.)\n * @param getDatabase - Function to get database instance (to avoid circular dependency)\n * @param closeDatabase - Function to close database (for reconnection)\n *\n * @example\n * ```typescript\n * import { startHealthCheck } from '@spfn/core/db/manager/health-check';\n *\n * startHealthCheck(\n * {\n * enabled: true,\n * interval: 30000, // 30 seconds\n * reconnect: true,\n * maxRetries: 5,\n * retryInterval: 10000, // 10 seconds\n * },\n * undefined,\n * getDatabase,\n * closeDatabase\n * );\n * ```\n */\nimport type { GetDatabaseFn } from './manager';\n\nexport function startHealthCheck(\n config: HealthCheckConfig,\n options: DatabaseOptions | undefined,\n getDatabase: GetDatabaseFn,\n closeDatabase: () => Promise<void>\n): void\n{\n const healthCheck = getHealthCheckInterval();\n if (healthCheck)\n {\n dbLogger.debug('Health check already running');\n return;\n }\n\n dbLogger.info('Starting database health check', {\n interval: `${config.interval}ms`,\n reconnect: config.reconnect,\n });\n\n const interval = setInterval(async () =>\n {\n try\n {\n const write = getDatabase('write');\n const read = getDatabase('read');\n\n // Check write connection\n if (write)\n {\n await write.execute('SELECT 1');\n }\n\n // Check read connection (if different)\n if (read && read !== write)\n {\n await read.execute('SELECT 1');\n }\n\n // Health check passed - no need to log (only log failures)\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n dbLogger.error('Database health check failed', { error: message });\n\n // Attempt reconnection if enabled\n if (config.reconnect)\n {\n await attemptReconnection(config, options, closeDatabase);\n }\n }\n }, config.interval);\n\n setHealthCheckInterval(interval);\n}\n\n/**\n * Attempt database reconnection with retry logic\n *\n * Closes existing connections and attempts to reinitialize the database.\n * Retries multiple times with configurable delay between attempts.\n *\n * @param config - Health check configuration\n * @param options - Optional database configuration (pool settings, etc.)\n * @param closeDatabase - Function to close existing database connections\n */\nasync function attemptReconnection(\n config: HealthCheckConfig,\n options: DatabaseOptions | undefined,\n closeDatabase: () => Promise<void>\n): Promise<void>\n{\n dbLogger.warn('Attempting database reconnection', {\n maxRetries: config.maxRetries,\n retryInterval: `${config.retryInterval}ms`,\n });\n\n for (let attempt = 1; attempt <= config.maxRetries; attempt++)\n {\n try\n {\n dbLogger.debug(`Reconnection attempt ${attempt}/${config.maxRetries}`);\n\n // Close existing connections\n await closeDatabase();\n\n // Wait before retry\n await new Promise(resolve => setTimeout(resolve, config.retryInterval));\n\n // Reinitialize database\n const result = await createDatabaseFromEnv(options);\n\n if (result.write)\n {\n // Test connection\n await result.write.execute('SELECT 1');\n\n // Store instances\n setWriteInstance(result.write);\n setReadInstance(result.read);\n setWriteClient(result.writeClient);\n setReadClient(result.readClient);\n\n dbLogger.info('Database reconnection successful', { attempt });\n return;\n }\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n dbLogger.error(`Reconnection attempt ${attempt} failed`, {\n error: message,\n attempt,\n maxRetries: config.maxRetries,\n });\n\n if (attempt === config.maxRetries)\n {\n dbLogger.error('Max reconnection attempts reached, giving up');\n }\n }\n }\n}\n\n/**\n * Stop database health check\n *\n * Automatically called by closeDatabase().\n * Can also be called manually to stop health checks.\n *\n * @example\n * ```typescript\n * import { stopHealthCheck } from '@spfn/core/db/manager/health-check';\n *\n * stopHealthCheck();\n * ```\n */\nexport function stopHealthCheck(): void\n{\n const healthCheck = getHealthCheckInterval();\n if (healthCheck)\n {\n clearInterval(healthCheck);\n setHealthCheckInterval(undefined);\n dbLogger.info('Database health check stopped');\n }\n}","/**\n * Global Database instance manager\n * Provides singleton access to database across all modules\n * Supports Primary + Replica pattern with separate read/write instances\n */\n\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nimport { logger } from '../../logger';\nimport { createDatabaseFromEnv } from './factory.js';\nimport type { DatabaseOptions, MonitoringConfig } from \"./config.js\";\nimport { buildHealthCheckConfig, buildMonitoringConfig } from \"./config.js\";\nimport {\n getWriteInstance,\n setWriteInstance,\n getReadInstance,\n setReadInstance,\n getWriteClient,\n setWriteClient,\n getReadClient,\n setReadClient,\n getMonitoringConfig,\n setMonitoringConfig,\n} from './global-state.js';\nimport { startHealthCheck, stopHealthCheck } from './health-check.js';\n\nconst dbLogger = logger.child('database');\n\n/**\n * DB connection type\n */\nexport type DbConnectionType = 'read' | 'write';\n\n/**\n * GetDatabase function type\n */\nexport type GetDatabaseFn = (type?: DbConnectionType) => PostgresJsDatabase<Record<string, unknown>> | undefined;\n\n/**\n * Get caller information from stack trace\n */\nfunction getCallerInfo(): string | undefined\n{\n try\n {\n const stack = new Error().stack;\n if (!stack) return undefined;\n\n const lines = stack.split('\\n');\n // Skip first 3 lines: Error, getCallerInfo, getDatabase\n for (let i = 3; i < lines.length; i++)\n {\n const line = lines[i];\n // Find first meaningful caller (not node_modules/@spfn/core/db)\n if (!line.includes('node_modules') && !line.includes('/db/manager/'))\n {\n // Extract file:line from stack line\n const match = line.match(/\\((.+):(\\d+):(\\d+)\\)/) || line.match(/at (.+):(\\d+):(\\d+)/);\n if (match)\n {\n const fullPath = match[1];\n // Get relative path from project root\n const parts = fullPath.split('/');\n const srcIndex = parts.lastIndexOf('src');\n if (srcIndex !== -1)\n {\n const relativePath = parts.slice(srcIndex).join('/');\n return `${relativePath}:${match[2]}`;\n }\n return `${fullPath}:${match[2]}`;\n }\n break;\n }\n }\n }\n catch\n {\n // Ignore errors in stack trace parsing\n }\n return undefined;\n}\n\n/**\n * Get global database write instance\n *\n * @returns Database write instance or undefined if not initialized\n *\n * @example\n * ```typescript\n * import { getDatabase } from '@spfn/core/db';\n *\n * const db = getDatabase();\n * if (db) {\n * const users = await db.select().from(usersTable);\n * }\n * ```\n */\nexport function getDatabase(type?: DbConnectionType): PostgresJsDatabase<Record<string, unknown>> | undefined\n{\n const writeInst = getWriteInstance();\n const readInst = getReadInstance();\n\n // Detailed debug logging with caller info (only if DB_DEBUG_TRACE is enabled)\n if (process.env.DB_DEBUG_TRACE === 'true')\n {\n const caller = getCallerInfo();\n dbLogger.debug('getDatabase() called', {\n type: type || 'write',\n hasWrite: !!writeInst,\n hasRead: !!readInst,\n caller,\n });\n }\n\n if (type === 'read')\n {\n return readInst ?? writeInst;\n }\n\n return writeInst;\n}\n\n/**\n * Set global database instances (for testing or manual configuration)\n *\n * @param write - Database write instance\n * @param read - Database read instance (optional, defaults to write)\n *\n * @example\n * ```typescript\n * import { setDatabase } from '@spfn/core/db';\n * import { drizzle } from 'drizzle-orm/postgres-js';\n * import postgres from 'postgres';\n *\n * const writeClient = postgres('postgresql://primary:5432/mydb');\n * const readClient = postgres('postgresql://replica:5432/mydb');\n * setDatabase(drizzle(writeClient), drizzle(readClient));\n * ```\n */\nexport function setDatabase(\n write: PostgresJsDatabase<Record<string, unknown>> | undefined,\n read?: PostgresJsDatabase<Record<string, unknown>> | undefined\n): void\n{\n setWriteInstance(write);\n setReadInstance(read ?? write);\n}\n\n/**\n * Initialize database from environment variables\n * Automatically called by server startup\n *\n * Supported environment variables:\n * - DATABASE_URL (single primary)\n * - DATABASE_WRITE_URL + DATABASE_READ_URL (primary + replica)\n * - DATABASE_URL + DATABASE_REPLICA_URL (legacy replica)\n * - DB_POOL_MAX (connection pool max size)\n * - DB_POOL_IDLE_TIMEOUT (connection idle timeout in seconds)\n * - DB_HEALTH_CHECK_ENABLED (enable health checks, default: true)\n * - DB_HEALTH_CHECK_INTERVAL (health check interval in ms, default: 60000)\n * - DB_HEALTH_CHECK_RECONNECT (enable auto-reconnect, default: true)\n * - DB_HEALTH_CHECK_MAX_RETRIES (max reconnection attempts, default: 3)\n * - DB_HEALTH_CHECK_RETRY_INTERVAL (retry interval in ms, default: 5000)\n * - DB_MONITORING_ENABLED (enable query monitoring, default: true in dev, false in prod)\n * - DB_MONITORING_SLOW_THRESHOLD (slow query threshold in ms, default: 1000)\n * - DB_MONITORING_LOG_QUERIES (log actual SQL queries, default: false)\n * - DB_DEBUG_TRACE (enable detailed getDatabase() call tracing with caller info, default: false)\n *\n * Configuration priority:\n * 1. options parameter (ServerConfig)\n * 2. Environment variables\n * 3. Defaults (based on NODE_ENV)\n *\n * @param options - Optional database configuration (pool settings, etc.)\n * @returns Object with write and read instances\n *\n * @example\n * ```typescript\n * import { initDatabase } from '@spfn/core/db';\n *\n * // Manual initialization (not needed if using server startup)\n * const { write, read } = await initDatabase();\n * if (write) {\n * console.log('Database connected');\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Custom pool configuration\n * const { write, read } = await initDatabase({\n * pool: { max: 50, idleTimeout: 60 }\n * });\n * ```\n */\nexport async function initDatabase(options?: DatabaseOptions): Promise<{\n write?: PostgresJsDatabase<Record<string, unknown>>;\n read?: PostgresJsDatabase<Record<string, unknown>>;\n}>\n{\n // Already initialized\n const writeInst = getWriteInstance();\n if (writeInst)\n {\n dbLogger.debug('Database already initialized');\n return { write: writeInst, read: getReadInstance() };\n }\n\n // Auto-detect from environment\n const result = await createDatabaseFromEnv(options);\n\n if (result.write)\n {\n try\n {\n // Test connection with a simple query\n await result.write.execute('SELECT 1');\n\n // Test read instance if different\n if (result.read && result.read !== result.write)\n {\n await result.read.execute('SELECT 1');\n }\n\n // Store instances in globalThis\n setWriteInstance(result.write);\n setReadInstance(result.read);\n setWriteClient(result.writeClient);\n setReadClient(result.readClient);\n\n const hasReplica = result.read && result.read !== result.write;\n dbLogger.info(\n hasReplica\n ? 'Database connected (Primary + Replica)'\n : 'Database connected'\n );\n\n // Start health check (automatic)\n const healthCheckConfig = buildHealthCheckConfig(options?.healthCheck);\n if (healthCheckConfig.enabled)\n {\n startHealthCheck(healthCheckConfig, options, getDatabase, closeDatabase);\n }\n\n // Initialize monitoring configuration\n const monConfig = buildMonitoringConfig(options?.monitoring);\n setMonitoringConfig(monConfig);\n if (monConfig.enabled)\n {\n dbLogger.info('Database query monitoring enabled', {\n slowThreshold: `${monConfig.slowThreshold}ms`,\n logQueries: monConfig.logQueries,\n });\n }\n }\n catch (error)\n {\n const message = error instanceof Error ? error.message : 'Unknown error';\n dbLogger.error('Database connection failed', { error: message });\n\n // Cleanup on failure\n await closeDatabase();\n\n // If DATABASE_URL is configured, connection failure should be fatal\n throw new Error(`Database connection test failed: ${message}`, { cause: error });\n }\n }\n else\n {\n dbLogger.warn('No database configuration found');\n dbLogger.warn('Set DATABASE_URL environment variable to enable database');\n }\n\n return { write: getWriteInstance(), read: getReadInstance() };\n}\n\n/**\n * Close all database connections and cleanup\n *\n * Properly closes postgres connection pools with timeout.\n * Should be called during graceful shutdown or after tests.\n *\n * @example\n * ```typescript\n * import { closeDatabase } from '@spfn/core/db';\n *\n * // During graceful shutdown\n * process.on('SIGTERM', async () => {\n * await closeDatabase();\n * process.exit(0);\n * });\n *\n * // In tests\n * afterAll(async () => {\n * await closeDatabase();\n * });\n * ```\n */\nexport async function closeDatabase(): Promise<void>\n{\n const writeInst = getWriteInstance();\n const readInst = getReadInstance();\n if (!writeInst && !readInst)\n {\n dbLogger.debug('No database connections to close');\n return;\n }\n\n // Stop health check\n stopHealthCheck();\n\n try\n {\n const closePromises: Promise<void>[] = [];\n\n // Close write client\n const writeC = getWriteClient();\n if (writeC)\n {\n dbLogger.debug('Closing write connection...');\n closePromises.push(\n writeC.end({ timeout: 5 })\n .then(() => dbLogger.debug('Write connection closed'))\n .catch(err => dbLogger.error('Error closing write connection', err))\n );\n }\n\n // Close read client (if different from write)\n const readC = getReadClient();\n if (readC && readC !== writeC)\n {\n dbLogger.debug('Closing read connection...');\n closePromises.push(\n readC.end({ timeout: 5 })\n .then(() => dbLogger.debug('Read connection closed'))\n .catch(err => dbLogger.error('Error closing read connection', err))\n );\n }\n\n // Wait for all connections to close\n await Promise.all(closePromises);\n\n dbLogger.info('All database connections closed');\n }\n catch (error)\n {\n dbLogger.error('Error during database cleanup', error as Error);\n throw error;\n }\n finally\n {\n // Always clear instances\n setWriteInstance(undefined);\n setReadInstance(undefined);\n setWriteClient(undefined);\n setReadClient(undefined);\n setMonitoringConfig(undefined);\n }\n}\n\n/**\n * Get database connection info (for debugging)\n */\nexport function getDatabaseInfo(): {\n hasWrite: boolean;\n hasRead: boolean;\n isReplica: boolean;\n}\n{\n const writeInst = getWriteInstance();\n const readInst = getReadInstance();\n\n return {\n hasWrite: !!writeInst,\n hasRead: !!readInst,\n isReplica: !!(readInst && readInst !== writeInst),\n };\n}\n\n/**\n * Get current monitoring configuration\n *\n * Returns the monitoring configuration that was set during database initialization.\n * Used by Repository to determine if and how to monitor query performance.\n *\n * @returns Current monitoring configuration or undefined if database not initialized\n *\n * @example\n * ```typescript\n * import { getDatabaseMonitoringConfig } from '@spfn/core/db';\n *\n * const config = getDatabaseMonitoringConfig();\n * if (config?.enabled) {\n * console.log(`Slow query threshold: ${config.slowThreshold}ms`);\n * }\n * ```\n */\nexport function getDatabaseMonitoringConfig(): MonitoringConfig | undefined\n{\n return getMonitoringConfig();\n}","/**\n * Database Manager Module Exports\n */\n\n// Database Factory (Environment Detection)\nexport { createDatabaseFromEnv } from './factory.js';\nexport type { DatabaseClients } from './config.js';\n\n// Database Manager (Singleton Pattern)\nexport {\n initDatabase,\n getDatabase,\n setDatabase,\n closeDatabase,\n getDatabaseInfo,\n getDatabaseMonitoringConfig,\n} from './manager.js';\n\n// Connection Functions\nexport { createDatabaseConnection, checkConnection } from './connection.js';\n\n// Configuration Types\nexport type { PoolConfig, RetryConfig } from './config.js';","/**\n * Drizzle Kit configuration generator\n * Automatically generates drizzle.config.ts from environment variables\n */\n\nimport { existsSync, readdirSync, readFileSync, statSync } from 'fs';\nimport { join, dirname, basename } from 'path';\n\nexport interface DrizzleConfigOptions\n{\n /** Database connection URL (defaults to process.env.DATABASE_URL) */\n databaseUrl?: string;\n\n /** Schema files glob pattern or array of patterns (defaults to './src/server/entities/\\*\\*\\/*.ts') */\n schema?: string | string[];\n\n /** Migration output directory (defaults to './src/server/drizzle') */\n out?: string;\n\n /** Database dialect (auto-detected from URL if not provided) */\n dialect?: 'postgresql' | 'mysql' | 'sqlite';\n\n /** Current working directory for discovering package schemas */\n cwd?: string;\n\n /** Disable automatic package schema discovery */\n disablePackageDiscovery?: boolean;\n\n /** Only include schemas from specific package (e.g., '@spfn/cms') */\n packageFilter?: string;\n}\n\n/**\n * Expand glob patterns to actual file paths\n * Handles patterns like:\n * - ./dist/entities/*.js → [./dist/entities/foo.js, ./dist/entities/bar.js]\n * - ./dist/entities/**\\/*.js → recursively finds all .js files\n *\n * @param pattern - Glob pattern or file path\n * @returns Array of expanded file paths\n */\nfunction expandGlobPattern(pattern: string): string[]\n{\n // If pattern doesn't contain wildcards, return as-is\n if (!pattern.includes('*'))\n {\n return existsSync(pattern) ? [pattern] : [];\n }\n\n const files: string[] = [];\n\n // Handle /**/* pattern (recursive)\n if (pattern.includes('**'))\n {\n const [baseDir, ...rest] = pattern.split('**');\n const extension = rest.join('').replace(/[\\/\\\\]\\*\\./g, '').trim();\n\n const scanRecursive = (dir: string) =>\n {\n if (!existsSync(dir)) return;\n\n try\n {\n const entries = readdirSync(dir);\n\n for (const entry of entries)\n {\n const fullPath = join(dir, entry);\n\n try\n {\n const stat = statSync(fullPath);\n\n if (stat.isDirectory())\n {\n scanRecursive(fullPath);\n }\n else if (stat.isFile())\n {\n // Check if file matches extension\n if (!extension || fullPath.endsWith(extension))\n {\n files.push(fullPath);\n }\n }\n }\n catch\n {\n // Skip files we can't stat\n }\n }\n }\n catch\n {\n // Skip directories we can't read\n }\n };\n\n scanRecursive(baseDir.trim() || '.');\n }\n // Handle /* pattern (single level)\n else if (pattern.includes('*'))\n {\n const dir = dirname(pattern);\n const filePattern = basename(pattern);\n\n if (!existsSync(dir)) return [];\n\n try\n {\n const entries = readdirSync(dir);\n\n for (const entry of entries)\n {\n const fullPath = join(dir, entry);\n\n try\n {\n const stat = statSync(fullPath);\n\n if (stat.isFile())\n {\n // Simple pattern matching (*.js matches foo.js)\n if (filePattern === '*' ||\n (filePattern.startsWith('*.') && entry.endsWith(filePattern.slice(1))))\n {\n files.push(fullPath);\n }\n }\n }\n catch\n {\n // Skip files we can't stat\n }\n }\n }\n catch\n {\n // Skip directories we can't read\n }\n }\n\n return files;\n}\n\n/**\n * Discover schema paths from installed packages\n * Only scans packages that:\n * 1. Are in @spfn scope\n * 2. Are direct dependencies with \"spfn\" keyword or \"spfn\" field in package.json\n */\nfunction discoverPackageSchemas(cwd: string): string[]\n{\n const schemas: string[] = [];\n const nodeModulesPath = join(cwd, 'node_modules');\n\n if (!existsSync(nodeModulesPath))\n {\n return schemas;\n }\n\n // Get direct dependencies from project's package.json\n const projectPkgPath = join(cwd, 'package.json');\n let directDeps: Set<string> = new Set();\n\n if (existsSync(projectPkgPath))\n {\n try\n {\n const projectPkg = JSON.parse(readFileSync(projectPkgPath, 'utf-8'));\n directDeps = new Set([\n ...Object.keys(projectPkg.dependencies || {}),\n ...Object.keys(projectPkg.devDependencies || {})\n ]);\n }\n catch (error)\n {\n // If we can't read project package.json, just scan @spfn packages\n }\n }\n\n const checkPackage = (_pkgName: string, pkgPath: string) =>\n {\n const pkgJsonPath = join(pkgPath, 'package.json');\n\n if (!existsSync(pkgJsonPath)) return;\n\n try\n {\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));\n\n // Check if package has schema declarations\n if (pkgJson.spfn?.schemas)\n {\n const packageSchemas = Array.isArray(pkgJson.spfn.schemas)\n ? pkgJson.spfn.schemas\n : [pkgJson.spfn.schemas];\n\n // Convert to absolute paths from package root and expand globs\n for (const schema of packageSchemas)\n {\n const absolutePath = join(pkgPath, schema);\n\n // Expand glob patterns to actual file lists\n // This prevents drizzle-kit from hanging on glob patterns\n const expandedFiles = expandGlobPattern(absolutePath);\n\n // Filter out index files (they are re-exports, not schema definitions)\n const schemaFiles = expandedFiles.filter(file =>\n !file.endsWith('/index.js') &&\n !file.endsWith('/index.ts') &&\n !file.endsWith('/index.mjs') &&\n !file.endsWith('\\\\index.js') &&\n !file.endsWith('\\\\index.ts') &&\n !file.endsWith('\\\\index.mjs')\n );\n\n schemas.push(...schemaFiles);\n }\n }\n }\n catch (error)\n {\n // Skip packages with invalid package.json\n }\n };\n\n // 1. Always scan @spfn/* packages\n const spfnDir = join(nodeModulesPath, '@spfn');\n if (existsSync(spfnDir))\n {\n try\n {\n const spfnPackages = readdirSync(spfnDir);\n for (const pkg of spfnPackages)\n {\n checkPackage(`@spfn/${pkg}`, join(spfnDir, pkg));\n }\n }\n catch (error)\n {\n // Skip if can't read @spfn directory\n }\n }\n\n // 2. Check direct dependencies for SPFN integration\n for (const depName of directDeps)\n {\n // Skip if already checked (@spfn/* packages)\n if (depName.startsWith('@spfn/')) continue;\n\n // Resolve package path (handle scoped packages)\n const pkgPath = depName.startsWith('@')\n ? join(nodeModulesPath, ...depName.split('/'))\n : join(nodeModulesPath, depName);\n\n checkPackage(depName, pkgPath);\n }\n\n return schemas;\n}\n\n/**\n * Detect database dialect from connection URL\n */\nexport function detectDialect(url: string): 'postgresql' | 'mysql' | 'sqlite'\n{\n if (url.startsWith('postgres://') || url.startsWith('postgresql://'))\n {\n return 'postgresql';\n }\n\n if (url.startsWith('mysql://'))\n {\n return 'mysql';\n }\n\n if (url.startsWith('sqlite://') || url.includes('.db') || url.includes('.sqlite'))\n {\n return 'sqlite';\n }\n\n throw new Error(\n `Unsupported database URL format: ${url}. Supported: postgresql://, mysql://, sqlite://`\n );\n}\n\n/**\n * Generate Drizzle Kit configuration\n *\n * @param options - Configuration options\n * @returns Drizzle Kit configuration object\n *\n * @example\n * ```ts\n * // Zero-config (reads from process.env.DATABASE_URL)\n * const config = getDrizzleConfig();\n *\n * // Custom config\n * const config = getDrizzleConfig({\n * databaseUrl: 'postgresql://localhost/mydb',\n * schema: './src/db/schema/*.ts',\n * out: './migrations',\n * });\n * ```\n */\nexport function getDrizzleConfig(options: DrizzleConfigOptions = {})\n{\n const databaseUrl = options.databaseUrl ?? process.env.DATABASE_URL;\n\n if (!databaseUrl)\n {\n throw new Error(\n 'DATABASE_URL is required. Set it in .env or pass it to getDrizzleConfig()'\n );\n }\n\n const dialect = options.dialect ?? detectDialect(databaseUrl);\n const out = options.out ?? './src/server/drizzle';\n\n // If packageFilter is specified, only include that package's schemas\n if (options.packageFilter)\n {\n const packageSchemas = options.disablePackageDiscovery\n ? []\n : discoverPackageSchemas(options.cwd ?? process.cwd());\n\n // Filter to only the specified package\n const filteredSchemas = packageSchemas.filter(schemaPath =>\n schemaPath.includes(`node_modules/${options.packageFilter}/`)\n );\n\n if (filteredSchemas.length === 0)\n {\n throw new Error(\n `No schemas found for package ${options.packageFilter}. ` +\n `Make sure the package is installed and has \"spfn.schemas\" in package.json.`\n );\n }\n\n const schema = filteredSchemas.length === 1 ? filteredSchemas[0] : filteredSchemas;\n\n return {\n schema,\n out,\n dialect,\n dbCredentials: getDbCredentials(dialect, databaseUrl),\n };\n }\n\n // Default: merge user schemas and all package schemas\n const userSchema = options.schema ?? './src/server/entities/**/*.ts'; // Support nested folders\n const userSchemas = Array.isArray(userSchema) ? userSchema : [userSchema];\n\n // Discover package schemas unless disabled\n const packageSchemas = options.disablePackageDiscovery\n ? []\n : discoverPackageSchemas(options.cwd ?? process.cwd());\n\n // Merge user schemas and package schemas\n const allSchemas = [...userSchemas, ...packageSchemas];\n const schema = allSchemas.length === 1 ? allSchemas[0] : allSchemas;\n\n return {\n schema,\n out,\n dialect,\n dbCredentials: getDbCredentials(dialect, databaseUrl),\n };\n}\n\n/**\n * Get database credentials based on dialect\n */\nfunction getDbCredentials(dialect: string, url: string)\n{\n switch (dialect)\n {\n case 'postgresql':\n case 'mysql':\n return { url };\n\n case 'sqlite':\n // Extract file path from sqlite:// URL\n const dbPath = url.replace('sqlite://', '').replace('sqlite:', '');\n return { url: dbPath };\n\n default:\n throw new Error(`Unsupported dialect: ${dialect}`);\n }\n}\n\n/**\n * Generate drizzle.config.ts file content\n *\n * @param options - Configuration options\n * @returns File content as string\n */\nexport function generateDrizzleConfigFile(options: DrizzleConfigOptions = {}): string\n{\n const config = getDrizzleConfig(options);\n\n // Format schema value (handle both string and array)\n const schemaValue = Array.isArray(config.schema)\n ? `[\\n ${config.schema.map(s => `'${s}'`).join(',\\n ')}\\n ]`\n : `'${config.schema}'`;\n\n return `import { defineConfig } from 'drizzle-kit';\n\nexport default defineConfig({\n schema: ${schemaValue},\n out: '${config.out}',\n dialect: '${config.dialect}',\n dbCredentials: ${JSON.stringify(config.dbCredentials, null, 4)},\n});\n`;\n}","/**\n * Schema Helper Functions\n *\n * Common field patterns for Drizzle ORM entities to reduce boilerplate.\n *\n * @example\n * ```typescript\n * import { pgTable, text } from 'drizzle-orm/pg-core';\n * import { id, timestamps } from '@spfn/core';\n *\n * export const users = pgTable('users', {\n * id: id(),\n * email: text('email').unique(),\n * ...timestamps(),\n * });\n * ```\n */\n\nimport type { PgColumn } from 'drizzle-orm/pg-core';\nimport { bigserial, timestamp, text, uuid as pgUuid } from 'drizzle-orm/pg-core';\n\n/**\n * Standard auto-incrementing primary key\n *\n * @returns bigserial primary key column\n *\n * @example\n * ```typescript\n * export const users = pgTable('users', {\n * id: id(),\n * // ...\n * });\n * ```\n */\nexport function id()\n{\n return bigserial('id', { mode: 'number' }).primaryKey();\n}\n\n/**\n * Standard timestamp fields (createdAt, updatedAt)\n *\n * Both fields are timezone-aware, auto-set to current time on creation.\n * When autoUpdate is enabled, updatedAt will be automatically updated on record updates.\n *\n * @param options - Optional configuration\n * @param options.autoUpdate - Automatically update updatedAt on record updates (default: false)\n * @returns Object with createdAt and updatedAt columns\n *\n * @example\n * ```typescript\n * // Without auto-update\n * export const users = pgTable('users', {\n * id: id(),\n * email: text('email'),\n * ...timestamps(),\n * });\n *\n * // With auto-update\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * ...timestamps({ autoUpdate: true }),\n * });\n * ```\n */\nexport function timestamps(options?: { autoUpdate?: boolean })\n{\n const updatedAtColumn = timestamp('updated_at', { withTimezone: true, mode: 'date' })\n .defaultNow()\n .notNull();\n\n // Mark column for auto-update if enabled\n if (options?.autoUpdate)\n {\n (updatedAtColumn as any).__autoUpdate = true;\n }\n\n return {\n createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' })\n .defaultNow()\n .notNull(),\n updatedAt: updatedAtColumn,\n };\n}\n\n/**\n * Auto-updating timestamp field (for custom timestamp fields)\n *\n * Creates a timestamp field that automatically updates on record updates.\n * Useful when you need a custom name like 'modifiedAt', 'lastUpdated', etc.\n *\n * @param fieldName - Field name in camelCase (default: 'updatedAt')\n * @returns Object with the timestamp column (converts camelCase to snake_case)\n *\n * @example\n * ```typescript\n * // Custom field name\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * ...autoUpdateTimestamp('modifiedAt'), // Creates 'modified_at' column\n * });\n *\n * // Default field name\n * export const articles = pgTable('articles', {\n * id: id(),\n * ...autoUpdateTimestamp(), // Creates 'updatedAt' -> 'updated_at'\n * });\n * ```\n */\nexport function autoUpdateTimestamp(fieldName: string = 'updatedAt')\n{\n // Convert camelCase to snake_case for column name\n const columnName = fieldName.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');\n\n const column = timestamp(columnName, { withTimezone: true, mode: 'date' })\n .defaultNow()\n .notNull();\n\n // Mark column for auto-update\n (column as any).__autoUpdate = true;\n\n return {\n [fieldName]: column,\n };\n}\n\n/**\n * Foreign key reference to another table\n *\n * Creates a bigserial column with cascade delete.\n * Type-safe: ensures the reference points to a valid PostgreSQL column.\n *\n * @param name - Column name (e.g., 'author' creates 'author_id')\n * @param reference - Reference to parent table column\n * @param options - Optional foreign key options\n *\n * @example\n * ```typescript\n * import { users } from './users';\n *\n * export const posts = pgTable('posts', {\n * id: id(),\n * authorId: foreignKey('author', () => users.id),\n * ...timestamps(),\n * });\n * ```\n */\nexport function foreignKey<T extends PgColumn>(\n name: string,\n reference: () => T,\n options?: { onDelete?: 'cascade' | 'set null' | 'restrict' | 'no action' }\n)\n{\n return bigserial(`${name}_id`, { mode: 'number' })\n .notNull()\n .references(reference, { onDelete: options?.onDelete ?? 'cascade' });\n}\n\n/**\n * Optional foreign key reference (nullable)\n *\n * Type-safe: ensures the reference points to a valid PostgreSQL column.\n *\n * @param name - Column name (e.g., 'author' creates 'author_id')\n * @param reference - Reference to parent table column\n * @param options - Optional foreign key options\n *\n * @example\n * ```typescript\n * export const posts = pgTable('posts', {\n * id: id(),\n * authorId: optionalForeignKey('author', () => users.id),\n * });\n * ```\n */\nexport function optionalForeignKey<T extends PgColumn>(\n name: string,\n reference: () => T,\n options?: { onDelete?: 'cascade' | 'set null' | 'restrict' | 'no action' }\n)\n{\n return bigserial(`${name}_id`, { mode: 'number' })\n .references(reference, { onDelete: options?.onDelete ?? 'set null' });\n}\n\n/**\n * UUID primary key\n *\n * Creates a UUID column as primary key with automatic default value generation.\n * Useful for distributed systems or when you need globally unique identifiers.\n *\n * @returns uuid primary key column with gen_random_uuid() default\n *\n * @example\n * ```typescript\n * export const sessions = pgTable('sessions', {\n * id: uuid(),\n * userId: foreignKey('user', () => users.id),\n * ...timestamps(),\n * });\n * ```\n */\nexport function uuid()\n{\n return pgUuid('id').defaultRandom().primaryKey();\n}\n\n/**\n * Audit fields for tracking record creators and updaters\n *\n * Adds createdBy and updatedBy fields for user tracking.\n * Typically stores user IDs, emails, or usernames.\n *\n * @returns Object with createdBy and updatedBy columns\n *\n * @example\n * ```typescript\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * ...timestamps(),\n * ...auditFields(),\n * });\n *\n * // Usage in route\n * await db.insert(posts).values({\n * title: 'New Post',\n * createdBy: currentUser.email,\n * });\n * ```\n */\nexport function auditFields()\n{\n return {\n createdBy: text('created_by'),\n updatedBy: text('updated_by'),\n };\n}\n\n/**\n * Publishing fields for content management\n *\n * Tracks when and by whom content was published.\n * Useful for CMS, blog posts, articles, etc.\n *\n * @returns Object with publishedAt and publishedBy columns\n *\n * @example\n * ```typescript\n * export const articles = pgTable('articles', {\n * id: id(),\n * title: text('title'),\n * status: text('status'), // draft/published/archived\n * ...publishingFields(),\n * ...timestamps(),\n * });\n *\n * // Publishing an article\n * await db.update(articles)\n * .set({\n * status: 'published',\n * publishedAt: new Date(),\n * publishedBy: currentUser.email,\n * })\n * .where(eq(articles.id, articleId));\n * ```\n */\nexport function publishingFields()\n{\n return {\n publishedAt: timestamp('published_at', { withTimezone: true, mode: 'date' }),\n publishedBy: text('published_by'),\n };\n}\n\n/**\n * Custom verification timestamp field\n *\n * Creates a nullable timestamp field for tracking verification status.\n * Useful for email verification, phone verification, etc.\n *\n * @param fieldName - Field name in camelCase (e.g., 'emailVerified', 'phoneVerified')\n * @returns Object with verification timestamp column (converts to snake_case + '_at')\n *\n * @example\n * ```typescript\n * export const users = pgTable('users', {\n * id: id(),\n * email: text('email'),\n * phone: text('phone'),\n * ...verificationTimestamp('emailVerified'), // emailVerifiedAt -> email_verified_at\n * ...verificationTimestamp('phoneVerified'), // phoneVerifiedAt -> phone_verified_at\n * ...timestamps(),\n * });\n *\n * // Verify email\n * await db.update(users)\n * .set({ emailVerifiedAt: new Date() })\n * .where(eq(users.email, userEmail));\n * ```\n */\nexport function verificationTimestamp(fieldName: string)\n{\n // Convert camelCase to snake_case and add '_at' suffix\n const columnName = fieldName\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '') + '_at';\n\n return {\n [fieldName + 'At']: timestamp(columnName, { withTimezone: true, mode: 'date' }),\n };\n}\n\n/**\n * Soft delete fields\n *\n * Adds deletedAt and deletedBy for logical deletion.\n * Records are marked as deleted instead of being physically removed.\n *\n * @returns Object with deletedAt and deletedBy columns\n *\n * @example\n * ```typescript\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * ...timestamps(),\n * ...softDelete(),\n * });\n *\n * // Soft delete\n * await db.update(posts)\n * .set({\n * deletedAt: new Date(),\n * deletedBy: currentUser.email,\n * })\n * .where(eq(posts.id, postId));\n *\n * // Query only non-deleted records\n * const activePosts = await db.select()\n * .from(posts)\n * .where(isNull(posts.deletedAt));\n * ```\n */\nexport function softDelete()\n{\n return {\n deletedAt: timestamp('deleted_at', { withTimezone: true, mode: 'date' }),\n deletedBy: text('deleted_by'),\n };\n}\n\n/**\n * Type-safe status enum field\n *\n * Creates a status text column with enum constraint and default value.\n * Provides compile-time type safety for status values.\n *\n * @param statuses - Array of status values (at least 2 required)\n * @param defaultStatus - Default status value (defaults to first status)\n * @returns Status column with enum constraint\n *\n * @example\n * ```typescript\n * // Basic usage\n * export const posts = pgTable('posts', {\n * id: id(),\n * title: text('title'),\n * status: statusEnum(['draft', 'published', 'archived'] as const),\n * ...timestamps(),\n * });\n *\n * // With custom default\n * export const users = pgTable('users', {\n * id: id(),\n * email: text('email'),\n * status: statusEnum(['active', 'inactive', 'suspended'] as const, 'active'),\n * ...timestamps(),\n * });\n *\n * // TypeScript infers the type\n * type PostStatus = 'draft' | 'published' | 'archived';\n * ```\n */\nexport function statusEnum<T extends readonly [string, ...string[]]>(\n statuses: T,\n defaultStatus?: T[number]\n)\n{\n return text('status', { enum: statuses as any })\n .notNull()\n .default((defaultStatus ?? statuses[0]) as any);\n}","/**\n * Schema Module Exports\n */\n\n// Schema Helpers\nexport {\n id,\n uuid,\n timestamps,\n autoUpdateTimestamp,\n foreignKey,\n optionalForeignKey,\n auditFields,\n publishingFields,\n verificationTimestamp,\n softDelete,\n statusEnum,\n} from './helpers.js';","/**\n * Database Schema Helper\n *\n * Provides utilities for creating isolated PostgreSQL schemas for SPFN functions\n */\n\nimport { pgSchema } from 'drizzle-orm/pg-core';\n\n/**\n * Create a namespaced PostgreSQL schema for a function\n *\n * @param packageName - NPM package name (e.g., '@spfn/cms', 'spfn-auth')\n * @returns PostgreSQL schema object for creating tables\n *\n * @example\n * ```typescript\n * // @spfn/cms → spfn_cms schema\n * import { createFunctionSchema } from '@spfn/core/db';\n *\n * const schema = createFunctionSchema('@spfn/cms');\n *\n * export const labels = schema.table('labels', {\n * id: id(),\n * name: text('name').notNull(),\n * });\n * // Creates table: spfn_cms.labels\n * ```\n */\nexport function createFunctionSchema(packageName: string)\n{\n const schemaName = packageNameToSchema(packageName);\n return pgSchema(schemaName);\n}\n\n/**\n * Convert package name to PostgreSQL schema name\n *\n * @param packageName - NPM package name\n * @returns Schema name in PostgreSQL format\n *\n * @example\n * ```typescript\n * packageNameToSchema('@spfn/cms') // 'spfn_cms'\n * packageNameToSchema('@company/spfn-auth') // 'company_spfn_auth'\n * packageNameToSchema('spfn-storage') // 'spfn_storage'\n * ```\n */\nexport function packageNameToSchema(packageName: string): string\n{\n // Remove @ and replace / and - with _\n return packageName\n .replace('@', '')\n .replace('/', '_')\n .replace(/-/g, '_');\n}\n\n/**\n * Get recommended schema name for a package\n *\n * @param packageName - NPM package name\n * @returns Object with schema name and whether it's scoped\n *\n * @example\n * ```typescript\n * getSchemaInfo('@spfn/cms')\n * // { schemaName: 'spfn_cms', isScoped: true, scope: 'spfn' }\n *\n * getSchemaInfo('spfn-auth')\n * // { schemaName: 'spfn_auth', isScoped: false, scope: null }\n * ```\n */\nexport function getSchemaInfo(packageName: string)\n{\n const isScoped = packageName.startsWith('@');\n const scope = isScoped ? packageName.split('/')[0].substring(1) : null;\n const schemaName = packageNameToSchema(packageName);\n\n return {\n schemaName,\n isScoped,\n scope,\n };\n}","/**\n * AsyncLocalStorage-based Transaction Context\n *\n * Uses Node.js AsyncLocalStorage to propagate transactions throughout the async call chain.\n *\n * Features:\n * - AsyncLocalStorage-based context management\n * - Type-safe transaction propagation across async chains\n * - Transaction ID tracking for debugging and tracing\n * - Nested transaction detection and logging\n * - Transaction nesting level tracking\n */\nimport { AsyncLocalStorage } from 'async_hooks';\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport { logger } from '../../logger'; // Assuming logger is accessible\n\n/**\n * Transaction database type\n * Uses Record<string, unknown> to accept any schema shape\n */\nexport type TransactionDB = PostgresJsDatabase<Record<string, unknown>>;\n\nconst txLogger = logger.child('transaction');\n\n/**\n * Transaction context stored in AsyncLocalStorage\n */\nexport type TransactionContext = {\n /** The actual Drizzle transaction object */\n tx: TransactionDB;\n /** Unique transaction ID for logging and tracing */\n txId: string; // Add txId to the context\n level: number;\n};\n\n/**\n * Global AsyncLocalStorage instance for transaction context\n */\nexport const asyncContext = new AsyncLocalStorage<TransactionContext>();\n\n/**\n * Get current transaction object and metadata from AsyncLocalStorage\n *\n * @returns TransactionContext if available, null otherwise\n */\nexport function getTransactionContext(): TransactionContext | null\n{\n return asyncContext.getStore() ?? null;\n}\n\n/**\n * Get current transaction from AsyncLocalStorage\n *\n * @returns Transaction if available, null otherwise\n */\nexport function getTransaction(): TransactionDB | null\n{\n const context = getTransactionContext();\n return context?.tx ?? null;\n}\n\n/**\n * Get current transaction ID from AsyncLocalStorage\n *\n * @returns Transaction ID if available, null otherwise\n */\nexport function getTransactionId(): string | null\n{\n const context = getTransactionContext();\n return context?.txId ?? null;\n}\n\n/**\n * Run a function within a transaction context\n *\n * The transaction will be available to all async operations within the callback\n * via getTransaction().\n *\n * @param tx - Drizzle transaction object\n * @param txId - Unique ID for the transaction\n * @param callback - Function to run within transaction context\n * @returns Result of the callback\n */\nexport function runWithTransaction<T>(\n tx: TransactionDB,\n txId: string, // Add txId parameter\n callback: () => Promise<T>\n): Promise<T>\n{\n const existingContext = getTransactionContext();\n\n // Determine the current transaction nesting level\n const newLevel = existingContext ? existingContext.level + 1 : 1;\n\n if (existingContext)\n {\n // Nested transaction detected. This means Drizzle will use a SAVEPOINT.\n txLogger.info('Nested transaction started (SAVEPOINT)', {\n outerTxId: existingContext.txId,\n innerTxId: txId,\n level: newLevel,\n });\n }\n else\n {\n // Root transaction\n txLogger.debug('Root transaction context set', { txId, level: newLevel });\n }\n\n // Store transaction, new ID, and the current nesting level\n return asyncContext.run({ tx, txId, level: newLevel }, callback);\n}","/**\n * Transactional Middleware\n *\n * Wraps route handlers in a database transaction.\n * Auto-commits on success, auto-rolls back on error.\n *\n * Features:\n * - Automatic transaction management (start/commit/rollback)\n * - Transaction propagation via AsyncLocalStorage\n * - Nested transaction detection and logging\n * - Hono Context error detection\n * - Transaction timeout with configurable threshold\n * - Execution time tracking and slow transaction warnings\n * - UUID-based transaction IDs for debugging\n * - PostgreSQL error conversion to custom errors\n */\nimport { randomUUID } from 'crypto';\nimport { logger } from '../../logger';\nimport { createMiddleware } from 'hono/factory';\nimport { getDatabase } from \"../manager\";\nimport { runWithTransaction, type TransactionDB } from './context.js';\nimport { TransactionError } from '../../errors';\nimport { fromPostgresError } from '../postgres-errors.js';\n\n/**\n * Transaction middleware options\n */\nexport interface TransactionalOptions\n{\n /**\n * Slow transaction warning threshold in milliseconds\n * @default 1000 (1 second)\n */\n slowThreshold?: number;\n\n /**\n * Enable transaction logging\n * @default true\n */\n enableLogging?: boolean;\n\n /**\n * Transaction timeout in milliseconds\n *\n * If transaction exceeds this duration, it will be aborted with TransactionError.\n *\n * @default 30000 (30 seconds) or TRANSACTION_TIMEOUT environment variable\n *\n * @example\n * ```typescript\n * // Default timeout (30s or TRANSACTION_TIMEOUT env var)\n * Transactional()\n *\n * // Custom timeout for specific route (60s)\n * Transactional({ timeout: 60000 })\n *\n * // Disable timeout\n * Transactional({ timeout: 0 })\n * ```\n */\n timeout?: number;\n}\n\n/**\n * Transaction middleware for Hono routes\n *\n * Automatically wraps route handlers in a database transaction.\n * Commits on success, rolls back on error.\n *\n * @example\n * ```typescript\n * // In your route file\n * export const middlewares = [Transactional()];\n *\n * export async function POST(c: RouteContext) {\n * // All DB operations run in a transaction\n * const [user] = await db.insert(users).values(body).returning();\n * await db.insert(profiles).values({ userId: user.id });\n * // Auto-commits on success\n * return c.json(user, 201);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With custom options\n * export const middlewares = [\n * Transactional({\n * slowThreshold: 2000, // Warn if transaction takes > 2s\n * enableLogging: false, // Disable logging\n * timeout: 60000, // 60 second timeout for long operations\n * })\n * ];\n * ```\n *\n * 🔄 Transaction behavior:\n * - Success: Auto-commit\n * - Error: Auto-rollback\n * - Detects context.error to trigger rollback\n *\n * 📊 Transaction logging:\n * - Auto-logs transaction start/commit/rollback\n * - Measures and records execution time\n * - Warns about slow transactions (default: > 1s)\n */\nexport function Transactional(options: TransactionalOptions = {})\n{\n // Get default timeout from environment variable (default: 30 seconds)\n const defaultTimeout = parseInt(process.env.TRANSACTION_TIMEOUT || '30000', 10);\n\n const {\n slowThreshold = 1000,\n enableLogging = true,\n timeout = defaultTimeout,\n } = options;\n\n const txLogger = logger.child('transaction');\n\n return createMiddleware(async (c, next) =>\n {\n // Generate transaction ID for debugging (using crypto.randomUUID for better uniqueness)\n const txId = `tx_${randomUUID()}`;\n const startTime = Date.now();\n const route = `${c.req.method} ${c.req.path}`;\n\n if (enableLogging)\n {\n txLogger.debug('Transaction started', { txId, route });\n }\n\n try\n {\n // Get write database instance\n const writeDb = getDatabase('write');\n if (!writeDb)\n {\n throw new TransactionError(\n 'Database not initialized. Cannot start transaction.',\n 500,\n { txId, route }\n );\n }\n\n // Create transaction promise\n const transactionPromise = writeDb.transaction(async (tx: TransactionDB) =>\n {\n // Store transaction in AsyncLocalStorage\n await runWithTransaction(tx, txId, async () =>\n {\n // Execute handler\n await next();\n\n // Detect if Hono caught an error and stored it in context.error\n // Context type doesn't officially define error property, so we extend it\n type ContextWithError = typeof c & { error?: Error };\n const contextWithError = c as ContextWithError;\n if (contextWithError.error)\n {\n // Throw to rollback transaction\n throw contextWithError.error;\n }\n\n // Auto-commit on success (handled by Drizzle)\n });\n });\n\n // Apply timeout if enabled (timeout > 0)\n if (timeout > 0)\n {\n const timeoutPromise = new Promise<never>((_, reject) =>\n {\n setTimeout(() =>\n {\n reject(\n new TransactionError(\n `Transaction timeout after ${timeout}ms`,\n 500,\n {\n txId,\n route,\n timeout: `${timeout}ms`,\n }\n )\n );\n }, timeout);\n });\n\n // Race between transaction and timeout\n await Promise.race([transactionPromise, timeoutPromise]);\n }\n else\n {\n // No timeout - just await transaction\n await transactionPromise;\n }\n\n // Transaction successful (committed)\n const duration = Date.now() - startTime;\n\n if (enableLogging)\n {\n if (duration >= slowThreshold)\n {\n txLogger.warn('Slow transaction committed', {\n txId,\n route,\n duration: `${duration}ms`,\n threshold: `${slowThreshold}ms`,\n });\n }\n else\n {\n txLogger.debug('Transaction committed', {\n txId,\n route,\n duration: `${duration}ms`,\n });\n }\n }\n }\n catch (error)\n {\n // Transaction failed (rolled back)\n const duration = Date.now() - startTime;\n\n // Convert PostgreSQL error to custom error (unless it's already TransactionError)\n const customError = error instanceof TransactionError\n ? error\n : fromPostgresError(error);\n\n if (enableLogging)\n {\n txLogger.error('Transaction rolled back', {\n txId,\n route,\n duration: `${duration}ms`,\n error: customError.message,\n errorType: customError.name,\n });\n }\n\n // Re-throw for Hono's error handler\n throw customError;\n }\n });\n}","/**\n * Transaction Module\n *\n * Database transaction management with AsyncLocalStorage-based propagation\n */\n\n// AsyncLocalStorage utilities\nexport { getTransaction, runWithTransaction, getTransactionContext } from './context.js';\nexport type { TransactionContext, TransactionDB } from './context.js';\n\n// Transaction middleware\nexport { Transactional } from './middleware.js';\nexport type { TransactionalOptions } from './middleware.js';","/**\n * Database Helper Functions\n *\n * Type-safe helper functions for common database operations.\n * Automatically handles:\n * - Transaction context detection\n * - Read/Write database separation\n * - Type inference from table schema\n *\n * @example\n * ```typescript\n * // Simple object-based where\n * const user = await findOne(users, { id: 1 });\n * const labels = await findMany(cmsLabels, { section: 'hero' });\n *\n * // Complex SQL-based where\n * const user = await findOne(users, and(eq(users.id, 1), gt(users.age, 18)));\n * const labels = await findMany(cmsLabels, {\n * where: or(like(cmsLabels.key, 'hero.%'), eq(cmsLabels.section, 'footer')),\n * limit: 10\n * });\n * ```\n */\n\nimport type { SQL } from 'drizzle-orm';\nimport { eq, and } from 'drizzle-orm';\nimport type { PgTable, PgColumn } from 'drizzle-orm/pg-core';\nimport { getDatabase } from './manager';\n\n/**\n * Infer SELECT model from PgTable\n */\ntype InferSelectModel<T extends PgTable> = T['$inferSelect'];\n\n/**\n * Infer INSERT model from PgTable\n */\ntype InferInsertModel<T extends PgTable> = T['$inferInsert'];\n\n/**\n * Object-based where condition (AND only, equality only)\n */\ntype WhereObject<T> = {\n [K in keyof T]?: T[K];\n};\n\n/**\n * Check if value is SQL wrapper\n */\nfunction isSQLWrapper(value: any): value is SQL\n{\n return value && typeof value === 'object' && 'queryChunks' in value;\n}\n\n/**\n * Build SQL WHERE clause from object\n */\nfunction buildWhereFromObject<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>>\n): SQL | undefined\n{\n const entries = Object.entries(where).filter(([_, value]) => value !== undefined);\n if (entries.length === 0) return undefined;\n\n const conditions = entries.map(([key, value]) =>\n eq((table as any)[key], value)\n );\n\n return conditions.length === 1 ? conditions[0] : and(...conditions);\n}\n\n/**\n * Find a single record\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @returns Single record or null\n *\n * @example\n * ```typescript\n * // Object-based\n * const user = await findOne(users, { id: 1 });\n * const label = await findOne(cmsLabels, { key: 'hero.title', section: 'hero' });\n *\n * // SQL-based\n * const user = await findOne(users, and(eq(users.id, 1), gt(users.age, 18)));\n * ```\n */\nexport async function findOne<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>>\n): Promise<InferSelectModel<T> | null>;\n\nexport async function findOne<T extends PgTable>(\n table: T,\n where: SQL | undefined\n): Promise<InferSelectModel<T> | null>;\n\nexport async function findOne<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined\n): Promise<InferSelectModel<T> | null>\n{\n const db = getDatabase('read');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('findOne requires at least one where condition');\n }\n\n const results = await db.select().from(table as PgTable).where(whereClause).limit(1);\n return (results[0] as InferSelectModel<T>) ?? null;\n}\n\n/**\n * Find multiple records\n *\n * @param table - Drizzle table schema\n * @param options - Query options (where, orderBy, limit, offset)\n * @returns Array of records\n *\n * @example\n * ```typescript\n * // Simple object where\n * const labels = await findMany(cmsLabels, { section: 'hero' });\n *\n * // With options\n * const labels = await findMany(cmsLabels, {\n * where: { section: 'hero' },\n * orderBy: desc(cmsLabels.updatedAt),\n * limit: 10,\n * offset: 0\n * });\n *\n * // Complex SQL where\n * const labels = await findMany(cmsLabels, {\n * where: and(\n * like(cmsLabels.key, 'hero.%'),\n * eq(cmsLabels.section, 'hero')\n * ),\n * limit: 10\n * });\n * ```\n */\nexport async function findMany<T extends PgTable>(\n table: T,\n options?: {\n where?: WhereObject<InferSelectModel<T>> | SQL | undefined;\n orderBy?: SQL | SQL[];\n limit?: number;\n offset?: number;\n }\n): Promise<InferSelectModel<T>[]>\n{\n const db = getDatabase('read');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n let query = db.select().from(table as PgTable);\n\n // Apply where\n if (options?.where)\n {\n const whereClause = isSQLWrapper(options.where)\n ? options.where\n : options.where ? buildWhereFromObject(table, options.where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (whereClause)\n {\n query = query.where(whereClause) as any;\n }\n }\n\n // Apply orderBy\n if (options?.orderBy)\n {\n const orderByArray = Array.isArray(options.orderBy) ? options.orderBy : [options.orderBy];\n query = query.orderBy(...orderByArray) as any;\n }\n\n // Apply limit\n if (options?.limit)\n {\n query = query.limit(options.limit) as any;\n }\n\n // Apply offset\n if (options?.offset)\n {\n query = query.offset(options.offset) as any;\n }\n\n return query as Promise<InferSelectModel<T>[]>;\n}\n\n/**\n * Create a new record\n *\n * @param table - Drizzle table schema\n * @param data - Insert data\n * @returns Created record\n *\n * @example\n * ```typescript\n * const user = await create(users, {\n * email: 'test@example.com',\n * name: 'Test User'\n * });\n * ```\n */\nexport async function create<T extends PgTable>(\n table: T,\n data: InferInsertModel<T>\n): Promise<InferSelectModel<T>>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const [result] = await db.insert(table).values(data).returning();\n return result as InferSelectModel<T>;\n}\n\n/**\n * Create multiple records\n *\n * @param table - Drizzle table schema\n * @param data - Array of insert data\n * @returns Array of created records\n *\n * @example\n * ```typescript\n * const users = await createMany(users, [\n * { email: 'user1@example.com', name: 'User 1' },\n * { email: 'user2@example.com', name: 'User 2' }\n * ]);\n * ```\n */\nexport async function createMany<T extends PgTable>(\n table: T,\n data: InferInsertModel<T>[]\n): Promise<InferSelectModel<T>[]>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const results = await db.insert(table).values(data).returning();\n return results as InferSelectModel<T>[];\n}\n\n/**\n * Upsert a record (INSERT or UPDATE on conflict)\n *\n * @param table - Drizzle table schema\n * @param data - Insert data\n * @param options - Conflict resolution options\n * @returns Upserted record\n *\n * @example\n * ```typescript\n * // Basic upsert\n * const cache = await upsert(cmsPublishedCache, {\n * section: 'home',\n * locale: 'ko',\n * content: {...}\n * }, {\n * target: [cmsPublishedCache.section, cmsPublishedCache.locale],\n * set: {\n * content: data.content,\n * updatedAt: new Date()\n * }\n * });\n *\n * // With SQL expression\n * const cache = await upsert(cmsPublishedCache, data, {\n * target: [cmsPublishedCache.section, cmsPublishedCache.locale],\n * set: {\n * content: data.content,\n * version: sql`${cmsPublishedCache.version} + 1`\n * }\n * });\n * ```\n */\nexport async function upsert<T extends PgTable>(\n table: T,\n data: InferInsertModel<T>,\n options: {\n target: PgColumn[];\n set?: Partial<InferInsertModel<T>> | Record<string, SQL | any>;\n }\n): Promise<InferSelectModel<T>>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const [result] = await db\n .insert(table)\n .values(data)\n .onConflictDoUpdate({\n target: options.target,\n set: options.set || data,\n })\n .returning();\n\n return result as InferSelectModel<T>;\n}\n\n/**\n * Update a single record\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @param data - Update data\n * @returns Updated record or null\n *\n * @example\n * ```typescript\n * // Object-based where\n * const user = await updateOne(users, { id: 1 }, { name: 'Updated Name' });\n *\n * // SQL-based where\n * const user = await updateOne(users, eq(users.id, 1), { name: 'Updated Name' });\n * ```\n */\nexport async function updateOne<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined,\n data: Partial<InferInsertModel<T>>\n): Promise<InferSelectModel<T> | null>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('updateOne requires at least one where condition');\n }\n\n const [result] = await db.update(table).set(data).where(whereClause).returning();\n return (result as InferSelectModel<T>) ?? null;\n}\n\n/**\n * Update multiple records\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @param data - Update data\n * @returns Array of updated records\n *\n * @example\n * ```typescript\n * const users = await updateMany(users,\n * { role: 'user' },\n * { verified: true }\n * );\n * ```\n */\nexport async function updateMany<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined,\n data: Partial<InferInsertModel<T>>\n): Promise<InferSelectModel<T>[]>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('updateMany requires at least one where condition');\n }\n\n const results = await db.update(table).set(data).where(whereClause).returning();\n return results as InferSelectModel<T>[];\n}\n\n/**\n * Delete a single record\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @returns Deleted record or null\n *\n * @example\n * ```typescript\n * // Object-based where\n * const user = await deleteOne(users, { id: 1 });\n *\n * // SQL-based where\n * const user = await deleteOne(users, eq(users.id, 1));\n * ```\n */\nexport async function deleteOne<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined\n): Promise<InferSelectModel<T> | null>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('deleteOne requires at least one where condition');\n }\n\n const [result] = await db.delete(table).where(whereClause).returning();\n return (result as InferSelectModel<T>) ?? null;\n}\n\n/**\n * Delete multiple records\n *\n * @param table - Drizzle table schema\n * @param where - Object or SQL condition\n * @returns Array of deleted records\n *\n * @example\n * ```typescript\n * const users = await deleteMany(users, { verified: false });\n * ```\n */\nexport async function deleteMany<T extends PgTable>(\n table: T,\n where: WhereObject<InferSelectModel<T>> | SQL | undefined\n): Promise<InferSelectModel<T>[]>\n{\n const db = getDatabase('write');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (!whereClause)\n {\n throw new Error('deleteMany requires at least one where condition');\n }\n\n const results = await db.delete(table).where(whereClause).returning();\n return results as InferSelectModel<T>[];\n}\n\n/**\n * Count records\n *\n * @param table - Drizzle table schema\n * @param where - Optional object or SQL condition\n * @returns Number of records\n *\n * @example\n * ```typescript\n * const total = await count(users);\n * const activeUsers = await count(users, { active: true });\n * const adults = await count(users, gt(users.age, 18));\n * ```\n */\nexport async function count<T extends PgTable>(\n table: T,\n where?: WhereObject<InferSelectModel<T>> | SQL | undefined\n): Promise<number>\n{\n const db = getDatabase('read');\n if (!db)\n {\n throw new Error('Database not initialized. Call initDatabase() first.');\n }\n\n let query = db.select().from(table as PgTable);\n\n if (where)\n {\n const whereClause = isSQLWrapper(where)\n ? where\n : where ? buildWhereFromObject(table, where as WhereObject<InferSelectModel<T>>) : undefined;\n\n if (whereClause)\n {\n query = query.where(whereClause) as any;\n }\n }\n\n const results = await query;\n return results.length;\n}\n","/**\n * Database Module Exports\n *\n * Entry point for DB module (Pure re-export only)\n */\n\n// Manager (DB Instance, Factory, Connection)\nexport {\n createDatabaseFromEnv,\n initDatabase,\n getDatabase,\n setDatabase,\n closeDatabase,\n getDatabaseInfo,\n createDatabaseConnection,\n checkConnection,\n} from './manager';\n\nexport type {\n DatabaseClients,\n PoolConfig,\n RetryConfig,\n} from './manager';\n\n// Drizzle Config Generator\nexport { getDrizzleConfig, detectDialect, generateDrizzleConfigFile } from './manager/config-generator.js';\nexport type { DrizzleConfigOptions } from './manager/config-generator.js';\n\n// Schema Helpers\nexport { id, timestamps, foreignKey, optionalForeignKey } from './schema';\nexport { createFunctionSchema, packageNameToSchema, getSchemaInfo } from './schema-helper.js';\n\n// Transaction\nexport { Transactional, getTransaction, runWithTransaction } from './transaction';\nexport type { TransactionContext, TransactionDB, TransactionalOptions } from './transaction';\n\n// PostgreSQL Error Utilities\nexport { fromPostgresError } from './postgres-errors.js';\n\n// Helper Functions\nexport {\n findOne,\n findMany,\n create,\n createMany,\n upsert,\n updateOne,\n updateMany,\n deleteOne,\n deleteMany,\n count,\n} from './helpers.js';","/**\n * Cache factory with automatic environment variable detection\n * Supports Valkey and Redis with multiple deployment patterns\n *\n * Valkey is a Redis fork (7.2.4 base) with 100% protocol compatibility\n * https://valkey.io\n */\n\nimport type { Redis, Cluster, RedisOptions, ClusterOptions } from 'ioredis';\nimport { logger } from '../logger';\n\nconst cacheLogger = logger.child('cache');\n\nexport interface CacheClients {\n /** Primary cache for writes (or both read/write if no replica) */\n write?: Redis | Cluster;\n /** Replica cache for reads (optional, falls back to write) */\n read?: Redis | Cluster;\n}\n\n/**\n * Check if any cache configuration exists in environment\n *\n * Priority:\n * 1. VALKEY_* / CACHE_* (modern)\n * 2. REDIS_* (backward compatibility)\n */\nfunction hasCacheConfig(): boolean\n{\n return !!(\n // Modern (Valkey/Cache)\n process.env.VALKEY_URL ||\n process.env.CACHE_URL ||\n process.env.VALKEY_WRITE_URL ||\n process.env.VALKEY_READ_URL ||\n process.env.CACHE_WRITE_URL ||\n process.env.CACHE_READ_URL ||\n process.env.VALKEY_SENTINEL_HOSTS ||\n process.env.VALKEY_CLUSTER_NODES ||\n // Legacy (Redis - backward compatibility)\n process.env.REDIS_URL ||\n process.env.REDIS_WRITE_URL ||\n process.env.REDIS_READ_URL ||\n process.env.REDIS_SENTINEL_HOSTS ||\n process.env.REDIS_CLUSTER_NODES\n );\n}\n\n/**\n * Get environment variable with priority fallback\n * Valkey/Cache takes precedence over Redis (legacy)\n */\nfunction getEnv(valkeyKey: string, cacheKey: string, redisKey: string): string | undefined\n{\n return process.env[valkeyKey] || process.env[cacheKey] || process.env[redisKey];\n}\n\n/**\n * Create cache client with TLS support\n * Supports both valkey:// and redis:// protocols\n */\nfunction createClient(\n RedisClient: new (url: string, options?: RedisOptions) => Redis,\n url: string\n): Redis\n{\n const options: RedisOptions = {};\n\n // TLS support for secure connections\n if (url.startsWith('rediss://') || url.startsWith('valkeys://'))\n {\n const rejectUnauthorized = getEnv(\n 'VALKEY_TLS_REJECT_UNAUTHORIZED',\n 'CACHE_TLS_REJECT_UNAUTHORIZED',\n 'REDIS_TLS_REJECT_UNAUTHORIZED'\n );\n\n options.tls = {\n rejectUnauthorized: rejectUnauthorized !== 'false',\n };\n }\n\n return new RedisClient(url, options);\n}\n\n/**\n * Create cache client(s) from environment variables\n *\n * Supported patterns (priority order):\n * 1. Single instance: VALKEY_URL or CACHE_URL or REDIS_URL\n * 2. Master-Replica: VALKEY_WRITE_URL + VALKEY_READ_URL (or CACHE_*, REDIS_*)\n * 3. Sentinel: VALKEY_SENTINEL_HOSTS + VALKEY_MASTER_NAME (or REDIS_*)\n * 4. Cluster: VALKEY_CLUSTER_NODES (or REDIS_*)\n *\n * @returns Cache client(s) or undefined if no configuration found\n *\n * @example\n * ```bash\n * # Single (most common)\n * VALKEY_URL=valkey://localhost:6379\n * CACHE_URL=redis://localhost:6379\n *\n * # Legacy (still supported)\n * REDIS_URL=redis://localhost:6379\n * REDIS_URL=rediss://secure.redis.com:6380 # TLS\n *\n * # Master-Replica\n * VALKEY_WRITE_URL=valkey://master:6379\n * VALKEY_READ_URL=valkey://replica:6379\n *\n * # Sentinel\n * VALKEY_SENTINEL_HOSTS=sentinel1:26379,sentinel2:26379\n * VALKEY_MASTER_NAME=mymaster\n * VALKEY_PASSWORD=secret\n *\n * # Cluster\n * VALKEY_CLUSTER_NODES=node1:6379,node2:6379,node3:6379\n * VALKEY_PASSWORD=secret\n * ```\n */\nexport async function createCacheFromEnv(): Promise<CacheClients>\n{\n // Quick exit if no cache config\n if (!hasCacheConfig())\n {\n cacheLogger.info('No cache configuration found - running without cache');\n return { write: undefined, read: undefined };\n }\n\n try\n {\n // Dynamic import to avoid bundling if not used\n const ioredis = await import('ioredis');\n const RedisClient = ioredis.default;\n\n // Get URLs with priority fallback\n const singleUrl = getEnv('VALKEY_URL', 'CACHE_URL', 'REDIS_URL');\n const writeUrl = getEnv('VALKEY_WRITE_URL', 'CACHE_WRITE_URL', 'REDIS_WRITE_URL');\n const readUrl = getEnv('VALKEY_READ_URL', 'CACHE_READ_URL', 'REDIS_READ_URL');\n const clusterNodes = getEnv('VALKEY_CLUSTER_NODES', 'CACHE_CLUSTER_NODES', 'REDIS_CLUSTER_NODES');\n const sentinelHosts = getEnv('VALKEY_SENTINEL_HOSTS', 'CACHE_SENTINEL_HOSTS', 'REDIS_SENTINEL_HOSTS');\n const masterName = getEnv('VALKEY_MASTER_NAME', 'CACHE_MASTER_NAME', 'REDIS_MASTER_NAME');\n const password = getEnv('VALKEY_PASSWORD', 'CACHE_PASSWORD', 'REDIS_PASSWORD');\n\n // 1. Single instance (most common - highest priority)\n if (singleUrl && !writeUrl && !readUrl && !clusterNodes)\n {\n const client = createClient(RedisClient, singleUrl);\n cacheLogger.debug('Created single cache instance', { url: singleUrl.replace(/:[^:@]+@/, ':***@') });\n return { write: client, read: client };\n }\n\n // 2. Master-Replica pattern (both URLs required)\n if (writeUrl && readUrl)\n {\n const write = createClient(RedisClient, writeUrl);\n const read = createClient(RedisClient, readUrl);\n cacheLogger.debug('Created master-replica cache instances');\n return { write, read };\n }\n\n // 3. Sentinel pattern\n if (sentinelHosts && masterName)\n {\n const sentinels = sentinelHosts.split(',').map((host) =>\n {\n const [hostname, port] = host.trim().split(':');\n return { host: hostname, port: Number(port) || 26379 };\n });\n\n const options: RedisOptions = {\n sentinels,\n name: masterName,\n password,\n };\n\n const client = new RedisClient(options);\n cacheLogger.debug('Created sentinel cache instance', { masterName, sentinels: sentinels.length });\n return { write: client, read: client };\n }\n\n // 4. Cluster pattern\n if (clusterNodes)\n {\n const nodes = clusterNodes.split(',').map((node) =>\n {\n const [host, port] = node.trim().split(':');\n return { host, port: Number(port) || 6379 };\n });\n\n const clusterOptions: ClusterOptions = {\n redisOptions: {\n password,\n },\n };\n\n const cluster = new RedisClient.Cluster(nodes, clusterOptions);\n cacheLogger.debug('Created cluster cache instance', { nodes: nodes.length });\n return { write: cluster, read: cluster };\n }\n\n // 5. Fallback: Single URL with other configs present\n if (singleUrl)\n {\n const client = createClient(RedisClient, singleUrl);\n cacheLogger.debug('Created cache instance (fallback)', { url: singleUrl.replace(/:[^:@]+@/, ':***@') });\n return { write: client, read: client };\n }\n\n // No valid configuration\n cacheLogger.info('No valid cache configuration found - running without cache');\n return { write: undefined, read: undefined };\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n // Check if it's a missing dependency error\n if (error.message.includes('Cannot find module'))\n {\n cacheLogger.warn(\n 'Cache client library not installed',\n error,\n {\n suggestion: 'Install ioredis to enable cache: pnpm install ioredis',\n mode: 'disabled'\n }\n );\n }\n else\n {\n cacheLogger.warn(\n 'Failed to create cache client',\n error,\n { mode: 'disabled' }\n );\n }\n }\n else\n {\n cacheLogger.warn(\n 'Failed to create cache client',\n { error: String(error), mode: 'disabled' }\n );\n }\n return { write: undefined, read: undefined };\n }\n}\n\n/**\n * Create single cache client (backward compatibility)\n * Only returns write instance\n */\nexport async function createSingleCacheFromEnv(): Promise<Redis | Cluster | undefined>\n{\n const { write } = await createCacheFromEnv();\n return write;\n}","/**\n * Global cache instance manager\n * Provides singleton access to cache (Valkey/Redis) across all modules\n * Supports Master-Replica pattern with separate read/write instances\n *\n * When cache is unavailable, falls back to disabled mode gracefully\n */\n\nimport type { Redis, Cluster } from 'ioredis';\n\nimport { createCacheFromEnv } from './cache-factory.js';\nimport { logger } from '../logger';\n\nconst cacheLogger = logger.child('cache');\n\nlet writeInstance: Redis | Cluster | undefined;\nlet readInstance: Redis | Cluster | undefined;\nlet isDisabled = false;\n\n/**\n * Get global cache write instance\n *\n * @returns Cache write instance or undefined if disabled/not initialized\n *\n * @example\n * ```typescript\n * import { getCache } from '@spfn/core/cache';\n *\n * const cache = getCache();\n * if (cache) {\n * await cache.set('key', 'value');\n * } else {\n * // Cache disabled - handle gracefully\n * console.log('Cache unavailable, skipping...');\n * }\n * ```\n */\nexport function getCache(): Redis | Cluster | undefined\n{\n return writeInstance;\n}\n\n/**\n * Get global cache read instance (falls back to write if no replica)\n *\n * @returns Cache read instance or write instance as fallback, undefined if disabled\n *\n * @example\n * ```typescript\n * import { getCacheRead } from '@spfn/core/cache';\n *\n * const cache = getCacheRead();\n * if (cache) {\n * const value = await cache.get('key');\n * }\n * ```\n */\nexport function getCacheRead(): Redis | Cluster | undefined\n{\n return readInstance ?? writeInstance;\n}\n\n/**\n * Check if cache is disabled (connection failed or not configured)\n *\n * @example\n * ```typescript\n * import { isCacheDisabled } from '@spfn/core/cache';\n *\n * if (isCacheDisabled()) {\n * // Use alternative strategy (e.g., in-memory cache, database)\n * return await fetchFromDatabase();\n * }\n * ```\n */\nexport function isCacheDisabled(): boolean\n{\n return isDisabled;\n}\n\n/**\n * Set global cache instances (for testing or manual configuration)\n *\n * @param write - Cache write instance\n * @param read - Cache read instance (optional, defaults to write)\n *\n * @example\n * ```typescript\n * import { setCache } from '@spfn/core/cache';\n * import Redis from 'ioredis';\n *\n * const write = new Redis('redis://master:6379');\n * const read = new Redis('redis://replica:6379');\n * setCache(write, read);\n * ```\n */\nexport function setCache(\n write: Redis | Cluster | undefined,\n read?: Redis | Cluster | undefined\n): void\n{\n writeInstance = write;\n readInstance = read ?? write;\n isDisabled = !write;\n}\n\n/**\n * Initialize cache from environment variables\n * Automatically called by startServer()\n *\n * Supported environment variables (priority order):\n * - VALKEY_URL / CACHE_URL (single instance)\n * - VALKEY_WRITE_URL + VALKEY_READ_URL (master-replica)\n * - VALKEY_SENTINEL_HOSTS + VALKEY_MASTER_NAME (sentinel)\n * - VALKEY_CLUSTER_NODES (cluster)\n * - VALKEY_TLS_REJECT_UNAUTHORIZED (TLS config)\n * - Legacy: REDIS_* (backward compatibility)\n *\n * @returns Object with write and read instances, or undefined if disabled\n *\n * @example\n * ```typescript\n * import { initCache } from '@spfn/core/cache';\n *\n * // Manual initialization (not needed if using startServer)\n * const { write, read, disabled } = await initCache();\n * if (!disabled) {\n * console.log('Cache available');\n * }\n * ```\n */\nexport async function initCache(): Promise<{\n write?: Redis | Cluster;\n read?: Redis | Cluster;\n disabled: boolean;\n}>\n{\n // Already initialized\n if (writeInstance)\n {\n return { write: writeInstance, read: readInstance, disabled: isDisabled };\n }\n\n // Auto-detect from environment\n const { write, read } = await createCacheFromEnv();\n\n if (write)\n {\n try\n {\n // Test connection\n await write.ping();\n\n // Test read instance if different\n if (read && read !== write)\n {\n await read.ping();\n }\n\n writeInstance = write;\n readInstance = read;\n isDisabled = false;\n\n const hasReplica = read && read !== write;\n cacheLogger.info(\n hasReplica\n ? 'Cache connected (Master-Replica)'\n : 'Cache connected',\n { mode: 'enabled' }\n );\n\n return { write: writeInstance, read: readInstance, disabled: false };\n }\n catch (error)\n {\n cacheLogger.error(\n 'Cache connection failed - running in disabled mode',\n error instanceof Error ? error : new Error(String(error)),\n { mode: 'disabled' }\n );\n\n // Clean up failed connections\n try\n {\n await write.quit();\n if (read && read !== write)\n {\n await read.quit();\n }\n }\n catch\n {\n // Ignore cleanup errors\n }\n\n isDisabled = true;\n return { write: undefined, read: undefined, disabled: true };\n }\n }\n\n // No configuration or library not installed\n isDisabled = true;\n cacheLogger.info('Cache disabled - no configuration or library not installed', { mode: 'disabled' });\n return { write: undefined, read: undefined, disabled: true };\n}\n\n/**\n * Close all cache connections and cleanup\n *\n * @example\n * ```typescript\n * import { closeCache } from '@spfn/core/cache';\n *\n * // During graceful shutdown\n * await closeCache();\n * ```\n */\nexport async function closeCache(): Promise<void>\n{\n if (isDisabled)\n {\n cacheLogger.debug('Cache already disabled, nothing to close');\n return;\n }\n\n const closePromises: Promise<unknown>[] = [];\n\n if (writeInstance)\n {\n closePromises.push(\n writeInstance.quit().catch((err: Error) =>\n {\n cacheLogger.error('Error closing cache write instance', err);\n })\n );\n }\n\n if (readInstance && readInstance !== writeInstance)\n {\n closePromises.push(\n readInstance.quit().catch((err: Error) =>\n {\n cacheLogger.error('Error closing cache read instance', err);\n })\n );\n }\n\n await Promise.all(closePromises);\n\n writeInstance = undefined;\n readInstance = undefined;\n isDisabled = true;\n\n cacheLogger.info('Cache connections closed', { mode: 'disabled' });\n}\n\n/**\n * Get cache connection info (for debugging)\n *\n * @example\n * ```typescript\n * import { getCacheInfo } from '@spfn/core/cache';\n *\n * const info = getCacheInfo();\n * console.log(info);\n * // {\n * // hasWrite: true,\n * // hasRead: true,\n * // isReplica: true,\n * // disabled: false\n * // }\n * ```\n */\nexport function getCacheInfo(): {\n hasWrite: boolean;\n hasRead: boolean;\n isReplica: boolean;\n disabled: boolean;\n}\n{\n return {\n hasWrite: !!writeInstance,\n hasRead: !!readInstance,\n isReplica: !!(readInstance && readInstance !== writeInstance),\n disabled: isDisabled,\n };\n}\n\n// Legacy exports (backward compatibility)\n/** @deprecated Use getCache() instead */\nexport const getRedis = getCache;\n\n/** @deprecated Use getCacheRead() instead */\nexport const getRedisRead = getCacheRead;\n\n/** @deprecated Use setCache() instead */\nexport const setRedis = setCache;\n\n/** @deprecated Use initCache() instead */\nexport const initRedis = initCache;\n\n/** @deprecated Use closeCache() instead */\nexport const closeRedis = closeCache;\n\n/** @deprecated Use getCacheInfo() instead */\nexport const getRedisInfo = getCacheInfo;","/**\n * Cache infrastructure (Valkey/Redis)\n * Provides singleton cache instance management for all SPFN modules\n * Supports Master-Replica pattern with separate read/write instances\n *\n * Valkey is a Redis fork (7.2.4 base) with 100% protocol compatibility\n * https://valkey.io\n */\n\n// Modern exports (cache)\nexport {\n createCacheFromEnv,\n createSingleCacheFromEnv,\n} from './cache-factory.js';\n\nexport {\n getCache,\n getCacheRead,\n isCacheDisabled,\n setCache,\n initCache,\n closeCache,\n getCacheInfo,\n} from './cache-manager.js';\n\nexport type { CacheClients } from './cache-factory.js';\n\n// Legacy exports (backward compatibility)\n// Manager functions - re-exported from cache-manager.js\nexport {\n getRedis,\n getRedisRead,\n setRedis,\n initRedis,\n closeRedis,\n getRedisInfo,\n} from './cache-manager.js';\n\n// Factory functions - re-exported from cache-factory.js\nexport {\n createCacheFromEnv as createRedisFromEnv,\n createSingleCacheFromEnv as createSingleRedisFromEnv,\n} from './cache-factory.js';\n\nexport type { CacheClients as RedisClients } from './cache-factory.js';","import { readdir, stat } from 'fs/promises';\nimport { join, relative } from 'path';\nimport { Hono } from 'hono';\nimport type { MiddlewareHandler } from 'hono';\nimport { logger } from '../logger';\n\nconst routeLogger = logger.child('route');\n\ndeclare module 'hono'\n{\n interface ContextVariableMap\n {\n _skipMiddlewares?: string[];\n }\n}\n\n/**\n * AutoRouteLoader: Simplified File-based Routing System\n *\n * Features:\n * - Auto-discovery: Scans routes directory and auto-registers\n * - Dynamic routes: [id] → :id, [...slug] → *\n * - Statistics: Route registration stats for dashboard\n * - Grouping: Natural grouping by directory structure\n */\n\nexport type RouteInfo = {\n path: string;\n file: string;\n meta?: {\n description?: string;\n tags?: string[];\n auth?: boolean;\n [key: string]: unknown;\n };\n priority: number;\n};\n\nexport type RouteStats = {\n total: number;\n byPriority: {\n static: number;\n dynamic: number;\n catchAll: number;\n };\n byTag: Record<string, number>;\n routes: RouteInfo[];\n};\n\ntype RouteModule = {\n default: Hono & {\n _contractMetas?: Map<string, any>;\n };\n meta?: {\n description?: string;\n tags?: string[];\n skipMiddlewares?: string[];\n [key: string]: unknown;\n };\n};\n\nexport class AutoRouteLoader\n{\n private routes: RouteInfo[] = [];\n private readonly debug: boolean;\n private readonly middlewares: Array<{ name: string; handler: MiddlewareHandler }>;\n\n constructor(\n private routesDir: string,\n debug = false,\n middlewares: Array<{ name: string; handler: MiddlewareHandler }> = []\n ) {\n this.debug = debug;\n this.middlewares = middlewares;\n }\n\n async load(app: Hono): Promise<RouteStats>\n {\n const startTime = Date.now();\n\n const files = await this.scanFiles(this.routesDir);\n\n if (files.length === 0)\n {\n routeLogger.warn('No route files found');\n return this.getStats();\n }\n\n let successCount = 0;\n let failureCount = 0;\n\n for (const file of files)\n {\n const success = await this.loadRoute(app, file);\n if (success)\n {\n successCount++;\n }\n else\n {\n failureCount++;\n }\n }\n\n const elapsed = Date.now() - startTime;\n const stats = this.getStats();\n\n if (this.debug)\n {\n this.logStats(stats, elapsed);\n }\n\n if (failureCount > 0)\n {\n routeLogger.warn('Some routes failed to load', { failureCount });\n }\n\n return stats;\n }\n\n /**\n * Load routes from an external directory (e.g., from SPFN function packages)\n * Reads package.json spfn.prefix and mounts routes under that prefix\n *\n * @param app - Hono app instance\n * @param routesDir - Directory containing route handlers\n * @param packageName - Name of the package (for logging)\n * @param prefix - Optional prefix to mount routes under (from package.json spfn.prefix)\n * @returns Route statistics\n */\n async loadExternalRoutes(app: Hono, routesDir: string, packageName: string, prefix?: string): Promise<RouteStats>\n {\n const startTime = Date.now();\n const tempRoutesDir = this.routesDir;\n this.routesDir = routesDir;\n\n const files = await this.scanFiles(routesDir);\n\n if (files.length === 0)\n {\n routeLogger.warn('No route files found', { dir: routesDir, package: packageName });\n this.routesDir = tempRoutesDir;\n return this.getStats();\n }\n\n let successCount = 0;\n let failureCount = 0;\n\n // Load routes with prefix if provided (from package.json spfn.prefix)\n for (const file of files)\n {\n const success = await this.loadRoute(app, file, prefix);\n if (success)\n {\n successCount++;\n }\n else\n {\n failureCount++;\n }\n }\n\n const elapsed = Date.now() - startTime;\n\n if (this.debug)\n {\n routeLogger.info('External routes loaded', {\n package: packageName,\n prefix: prefix || '/',\n total: successCount,\n failed: failureCount,\n elapsed: `${elapsed}ms`,\n });\n }\n\n this.routesDir = tempRoutesDir;\n return this.getStats();\n }\n\n getStats(): RouteStats\n {\n const stats: RouteStats = {\n total: this.routes.length,\n byPriority: { static: 0, dynamic: 0, catchAll: 0 },\n byTag: {},\n routes: this.routes,\n };\n\n for (const route of this.routes)\n {\n if (route.priority === 1) stats.byPriority.static++;\n else if (route.priority === 2) stats.byPriority.dynamic++;\n else if (route.priority === 3) stats.byPriority.catchAll++;\n\n if (route.meta?.tags)\n {\n for (const tag of route.meta.tags)\n {\n stats.byTag[tag] = (stats.byTag[tag] || 0) + 1;\n }\n }\n }\n\n return stats;\n }\n\n private async scanFiles(dir: string, files: string[] = []): Promise<string[]>\n {\n const entries = await readdir(dir);\n\n for (const entry of entries)\n {\n const fullPath = join(dir, entry);\n const fileStat = await stat(fullPath);\n\n if (fileStat.isDirectory())\n {\n await this.scanFiles(fullPath, files);\n }\n else if (this.isValidRouteFile(entry))\n {\n files.push(fullPath);\n }\n }\n\n return files;\n }\n\n private isValidRouteFile(fileName: string): boolean\n {\n // Strict convention: Only index.ts, index.js, or index.mjs files are route handlers\n // This prevents accidental loading of utility files, helpers, types, etc.\n return fileName === 'index.ts' || fileName === 'index.js' || fileName === 'index.mjs';\n }\n\n private async loadRoute(app: Hono, absolutePath: string, prefix?: string): Promise<boolean>\n {\n const relativePath = relative(this.routesDir, absolutePath);\n\n try\n {\n const module = await import(absolutePath) as RouteModule;\n\n if (!this.validateModule(module, relativePath))\n {\n return false;\n }\n\n // Contract-based routing: Use contract paths directly\n const hasContractMetas = module.default._contractMetas && module.default._contractMetas.size > 0;\n\n if (!hasContractMetas)\n {\n routeLogger.error('Route must use contract-based routing', {\n file: relativePath,\n hint: 'Export contracts using satisfies RouteContract and use app.bind()'\n });\n return false;\n }\n\n // Extract paths from contract metas for logging and stats\n const contractPaths = this.extractContractPaths(module);\n\n // Validate contract paths against prefix (if prefix is provided)\n if (prefix)\n {\n const invalidPaths = contractPaths.filter(path => !path.startsWith(prefix));\n if (invalidPaths.length > 0)\n {\n routeLogger.error('Contract paths must include the package prefix', {\n file: relativePath,\n prefix,\n invalidPaths,\n hint: `Contract paths should start with \"${prefix}\". Example: path: \"${prefix}/labels\"`\n });\n return false;\n }\n }\n\n // Register contract-based middlewares\n this.registerContractBasedMiddlewares(app, contractPaths, module);\n\n // Mount directly (contracts already include full path with prefix)\n app.route('/', module.default);\n\n // Track routes for stats\n contractPaths.forEach(path => {\n this.routes.push({\n path: path, // Use contract path as-is (already includes prefix)\n file: relativePath,\n meta: module.meta,\n priority: this.calculateContractPriority(path),\n });\n\n if (this.debug)\n {\n const icon = path.includes('*') ? '⭐' : path.includes(':') ? '🔸' : '🔹';\n routeLogger.debug(`Registered route: ${path}`, { icon, file: relativePath });\n }\n });\n\n return true;\n }\n catch (error)\n {\n this.categorizeAndLogError(error as Error, relativePath);\n return false;\n }\n }\n\n private extractContractPaths(module: RouteModule): string[]\n {\n const paths = new Set<string>();\n\n if (module.default._contractMetas)\n {\n for (const key of module.default._contractMetas.keys())\n {\n // key format: \"GET /teams/:id\"\n const path = key.split(' ')[1];\n if (path)\n {\n paths.add(path);\n }\n }\n }\n\n return Array.from(paths);\n }\n\n private calculateContractPriority(path: string): number\n {\n if (path.includes('*')) return 3; // Catch-all\n if (path.includes(':')) return 2; // Dynamic\n return 1; // Static\n }\n\n private validateModule(module: RouteModule, relativePath: string): boolean\n {\n if (!module.default)\n {\n routeLogger.error('Route must export Hono instance as default', { file: relativePath });\n return false;\n }\n\n if (typeof module.default.route !== 'function')\n {\n routeLogger.error('Default export is not a Hono instance', { file: relativePath });\n return false;\n }\n\n return true;\n }\n\n private registerContractBasedMiddlewares(app: Hono, contractPaths: string[], module: RouteModule): void\n {\n // Register middleware checker for all contract paths\n app.use('*', (c, next) =>\n {\n const method = c.req.method;\n const requestPath = new URL(c.req.url).pathname;\n\n const key = `${method} ${requestPath}`;\n const meta = module.default._contractMetas?.get(key);\n\n if (meta?.skipMiddlewares)\n {\n c.set('_skipMiddlewares', meta.skipMiddlewares);\n }\n\n return next();\n });\n\n // Register middlewares for each contract path\n for (const contractPath of contractPaths)\n {\n const middlewarePath = contractPath === '/' ? '/*' : `${contractPath}/*`;\n\n for (const middleware of this.middlewares)\n {\n app.use(middlewarePath, async (c, next) =>\n {\n const skipList = c.get('_skipMiddlewares') || [];\n\n if (skipList.includes(middleware.name))\n {\n return next();\n }\n\n return middleware.handler(c, next);\n });\n }\n }\n }\n\n private categorizeAndLogError(error: Error, relativePath: string): void\n {\n const message = error.message;\n const stack = error.stack;\n\n if (message.includes('Cannot find module') || message.includes('MODULE_NOT_FOUND'))\n {\n routeLogger.error('Missing dependency', {\n file: relativePath,\n error: message,\n hint: 'Run: npm install',\n });\n }\n else if (message.includes('SyntaxError') || stack?.includes('SyntaxError'))\n {\n routeLogger.error('Syntax error', {\n file: relativePath,\n error: message,\n ...(this.debug && stack && {\n stack: stack.split('\\n').slice(0, 5).join('\\n')\n }),\n });\n }\n else if (message.includes('Unexpected token'))\n {\n routeLogger.error('Parse error', {\n file: relativePath,\n error: message,\n hint: 'Check for syntax errors or invalid TypeScript',\n });\n }\n else\n {\n routeLogger.error('Route loading failed', {\n file: relativePath,\n error: message,\n ...(this.debug && stack && { stack }),\n });\n }\n }\n\n private logStats(stats: RouteStats, elapsed: number): void\n {\n const tagCounts = Object.entries(stats.byTag)\n .map(([tag, count]) => `${tag}(${count})`)\n .join(', ');\n\n routeLogger.info('Routes loaded successfully', {\n total: stats.total,\n priority: {\n static: stats.byPriority.static,\n dynamic: stats.byPriority.dynamic,\n catchAll: stats.byPriority.catchAll,\n },\n ...(tagCounts && { tags: tagCounts }),\n elapsed: `${elapsed}ms`,\n });\n }\n}\n\nexport async function loadRoutes(\n app: Hono,\n options?: {\n routesDir?: string;\n debug?: boolean;\n middlewares?: Array<{ name: string; handler: MiddlewareHandler }>;\n includeFunctionRoutes?: boolean;\n }\n): Promise<RouteStats>\n{\n const routesDir = options?.routesDir ?? join(process.cwd(), 'src', 'server', 'routes');\n const debug = options?.debug ?? false;\n const middlewares = options?.middlewares ?? [];\n const includeFunctionRoutes = options?.includeFunctionRoutes ?? true; // Default: true\n\n const loader = new AutoRouteLoader(routesDir, debug, middlewares);\n const stats = await loader.load(app);\n\n // Load function routes if enabled\n if (includeFunctionRoutes)\n {\n const { discoverFunctionRoutes } = await import('./function-routes.js');\n const functionRoutes = discoverFunctionRoutes();\n\n if (functionRoutes.length > 0)\n {\n routeLogger.info('Loading function routes', { count: functionRoutes.length });\n\n for (const func of functionRoutes)\n {\n try\n {\n await loader.loadExternalRoutes(app, func.routesDir, func.packageName, func.prefix);\n routeLogger.info('Function routes loaded', {\n package: func.packageName,\n routesDir: func.routesDir,\n prefix: func.prefix || '/',\n });\n }\n catch (error)\n {\n routeLogger.error('Failed to load function routes', {\n package: func.packageName,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n }\n }\n\n return stats;\n}","import type { Context } from 'hono';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { Value } from '@sinclair/typebox/value';\nimport type { RouteContract, RouteContext, InferContract } from './types.js';\nimport { ValidationError } from '../errors';\nimport type { ApiSuccessResponse } from './api-response.js';\n\n/**\n * Contract-based Route Handler Wrapper\n *\n * Binds a contract to a route handler, providing automatic validation\n * and type-safe context creation.\n *\n * Features:\n * - Automatic params/query/body validation using TypeBox\n * - Type-safe RouteContext with contract-based inference\n * - Clean separation: bind() for validation, Hono for middleware\n */\nexport function bind<TContract extends RouteContract>(\n contract: TContract,\n handler: (c: RouteContext<TContract>) => Response | Promise<Response>\n) {\n return async (rawContext: Context) =>\n {\n let params = rawContext.req.param();\n if (contract.params)\n {\n // Convert types (e.g., string \"123\" -> number 123)\n params = Value.Convert(contract.params, params) as typeof params;\n\n // Then validate\n const errors = [...Value.Errors(contract.params, params)];\n if (errors.length > 0)\n {\n throw new ValidationError(\n 'Invalid path parameters',\n {\n fields: errors.map(e => ({\n path: e.path,\n message: e.message,\n value: e.value,\n }))\n }\n );\n }\n }\n\n const url = new URL(rawContext.req.url);\n let query: Record<string, string | string[]> = {};\n url.searchParams.forEach((v, k) =>\n {\n const existing = query[k];\n if (existing)\n {\n query[k] = Array.isArray(existing) ? [...existing, v] : [existing, v];\n }\n else\n {\n query[k] = v;\n }\n });\n\n if (contract.query)\n {\n // Convert types (e.g., string \"123\" -> number 123, \"true\" -> boㅇolean true)\n query = Value.Convert(contract.query, query) as typeof query;\n\n // Then validate\n const errors = [...Value.Errors(contract.query, query)];\n if (errors.length > 0)\n {\n throw new ValidationError(\n 'Invalid query parameters',\n {\n fields: errors.map(e => ({\n path: e.path,\n message: e.message,\n value: e.value,\n }))\n }\n );\n }\n }\n\n const routeContext: RouteContext<TContract> =\n {\n params: params as InferContract<TContract>['params'],\n query: query as InferContract<TContract>['query'],\n\n data: async () =>\n {\n let body = await rawContext.req.json();\n if (contract.body)\n {\n // Convert types (e.g., handle nested objects, arrays, etc.)\n body = Value.Convert(contract.body, body) as any;\n\n // Then validate\n const errors = [...Value.Errors(contract.body, body)];\n if (errors.length > 0)\n {\n throw new ValidationError(\n 'Invalid request body',\n {\n fields: errors.map(e => ({\n path: e.path,\n message: e.message,\n value: e.value,\n }))\n }\n );\n }\n }\n\n return body as InferContract<TContract>['body'];\n },\n\n json: (data, status, headers) =>\n {\n // Warn if ErrorHandler is enabled but response doesn't follow standard format\n const errorHandlerEnabled = rawContext.get('errorHandlerEnabled');\n if (errorHandlerEnabled && process.env.NODE_ENV !== 'production')\n {\n const hasSuccessField = data && typeof data === 'object' && 'success' in data;\n if (!hasSuccessField)\n {\n console.warn(\n '[SPFN] Warning: ErrorHandler is enabled but c.json() is being used with non-standard response format.\\n' +\n 'Consider using c.success() for consistent API responses, or disable ErrorHandler if you prefer custom formats.'\n );\n }\n }\n\n return rawContext.json(data, status, headers);\n },\n\n success: <T>(data: T, meta?: ApiSuccessResponse<T>['meta'], status: ContentfulStatusCode | undefined = 200) =>\n {\n const response: ApiSuccessResponse<T> = {\n success: true,\n data,\n };\n\n if (meta)\n {\n response.meta = meta;\n }\n\n return rawContext.json(response, status);\n },\n\n paginated: <T>(data: T[], page: number, limit: number, total: number) =>\n {\n const response: ApiSuccessResponse<T[]> = {\n success: true,\n data,\n meta: {\n pagination: {\n page,\n limit,\n total,\n totalPages: Math.ceil(total / limit),\n },\n },\n };\n\n return rawContext.json(response, 200 as ContentfulStatusCode);\n },\n\n raw: rawContext,\n };\n\n return handler(routeContext);\n };\n}","/**\n * Error Handler Middleware\n *\n * Generic middleware that converts errors with statusCode to HTTP responses\n */\nimport type { Context } from 'hono';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { logger } from '../logger';\nimport type { ErrorResponse } from '../types/api-response.js';\n\nconst errorLogger = logger.child('error-handler');\n\nexport interface ErrorHandlerOptions\n{\n /**\n * Include stack trace in response\n * @default process.env.NODE_ENV !== 'production'\n */\n includeStack?: boolean;\n\n /**\n * Enable error logging\n * @default true\n */\n enableLogging?: boolean;\n}\n\ninterface ErrorWithStatusCode extends Error\n{\n statusCode?: number;\n details?: any;\n}\n\n/**\n * Standard error response format\n *\n * Re-exported from @spfn/core/types for convenience\n */\nexport type { ErrorResponse } from '../types/api-response.js';\n\n/**\n * Error handler middleware\n *\n * Used in Hono's onError hook\n */\nexport function ErrorHandler(options: ErrorHandlerOptions = {}): (err: Error, c: Context) => Response | Promise<Response>\n{\n const {\n includeStack = process.env.NODE_ENV !== 'production',\n enableLogging = true,\n } = options;\n\n return (err: Error, c: Context) =>\n {\n const errorWithCode = err as ErrorWithStatusCode;\n const statusCode = errorWithCode.statusCode || 500;\n const errorType = err.name || 'Error';\n\n if (enableLogging)\n {\n const logLevel = statusCode >= 500 ? 'error' : 'warn';\n\n const logData: Record<string, any> = {\n type: errorType,\n message: err.message,\n statusCode,\n path: c.req.path,\n method: c.req.method,\n };\n\n // Include details if available\n if (errorWithCode.details)\n {\n logData.details = errorWithCode.details;\n }\n\n // Include stack trace for 500 errors in development\n if (statusCode >= 500 && includeStack)\n {\n logData.stack = err.stack;\n }\n\n errorLogger[logLevel]('Error occurred', logData);\n }\n\n const response: ErrorResponse = {\n success: false,\n error: {\n message: err.message || 'Internal Server Error',\n type: errorType,\n statusCode,\n },\n };\n\n if (errorWithCode.details)\n {\n response.error.details = errorWithCode.details;\n }\n\n if (includeStack)\n {\n response.error.stack = err.stack;\n }\n\n return c.json(response, statusCode as ContentfulStatusCode);\n };\n}\n","/**\n * Request Logger Middleware\n *\n * Automatic API request/response logging with performance monitoring\n */\nimport type { Context, Next } from 'hono';\nimport { randomBytes } from 'crypto';\nimport { logger } from '../logger';\n\nexport interface RequestLoggerConfig\n{\n /**\n * Paths to exclude from logging (health checks, etc.)\n */\n excludePaths?: string[];\n\n /**\n * Field names to mask for sensitive data\n */\n sensitiveFields?: string[];\n\n /**\n * Slow request threshold (ms)\n */\n slowRequestThreshold?: number;\n}\n\nconst DEFAULT_CONFIG: Required<RequestLoggerConfig> = {\n excludePaths: ['/health', '/ping', '/favicon.ico'],\n sensitiveFields: ['password', 'token', 'apiKey', 'secret', 'authorization'],\n slowRequestThreshold: 1000,\n};\n\n/**\n * Generate cryptographically secure request ID\n */\nfunction generateRequestId(): string\n{\n const timestamp = Date.now();\n const randomPart = randomBytes(6).toString('hex');\n return `req_${timestamp}_${randomPart}`;\n}\n\n/**\n * Mask sensitive data with circular reference handling\n */\nexport function maskSensitiveData(\n obj: any,\n sensitiveFields: string[],\n seen = new WeakSet()\n): any\n{\n if (!obj || typeof obj !== 'object') return obj;\n\n if (seen.has(obj)) return '[Circular]';\n seen.add(obj);\n\n const lowerFields = sensitiveFields.map(f => f.toLowerCase());\n const masked = Array.isArray(obj) ? [...obj] : { ...obj };\n\n for (const key in masked)\n {\n const lowerKey = key.toLowerCase();\n\n if (lowerFields.some(field => lowerKey.includes(field)))\n {\n masked[key] = '***MASKED***';\n }\n else if (typeof masked[key] === 'object' && masked[key] !== null)\n {\n masked[key] = maskSensitiveData(masked[key], sensitiveFields, seen);\n }\n }\n\n return masked;\n}\n\n/**\n * Request Logger middleware\n */\nexport function RequestLogger(config?: RequestLoggerConfig)\n{\n const cfg = { ...DEFAULT_CONFIG, ...config };\n const apiLogger = logger.child('api');\n\n return async (c: Context, next: Next) =>\n {\n const path = new URL(c.req.url).pathname;\n\n if (cfg.excludePaths.includes(path))\n {\n return next();\n }\n\n const requestId = generateRequestId();\n c.set('requestId', requestId);\n\n const method = c.req.method;\n const userAgent = c.req.header('user-agent');\n const ip = c.req.header('x-forwarded-for') || c.req.header('x-real-ip') || 'unknown';\n\n const startTime = Date.now();\n\n apiLogger.info('Request received', {\n requestId,\n method,\n path,\n ip,\n userAgent,\n });\n\n try\n {\n await next();\n\n const duration = Date.now() - startTime;\n const status = c.res.status;\n\n const logData: Record<string, any> = {\n requestId,\n method,\n path,\n status,\n duration,\n };\n\n const isSlowRequest = duration >= cfg.slowRequestThreshold;\n if (isSlowRequest)\n {\n logData.slow = true;\n }\n\n // Add detailed error information for 4xx/5xx responses\n if (status >= 400)\n {\n try\n {\n // Clone response to read body without consuming it\n const responseBody = await c.res.clone().json();\n logData.response = responseBody;\n }\n catch\n {\n // Response is not JSON or already consumed - ignore\n }\n\n // Add request body for POST/PUT/PATCH to see what data caused the error\n if (['POST', 'PUT', 'PATCH'].includes(method))\n {\n try\n {\n // Try to get the already parsed body from context\n const requestBody = await c.req.json();\n logData.request = maskSensitiveData(requestBody, cfg.sensitiveFields);\n }\n catch\n {\n // Body is not JSON or already consumed - ignore\n }\n }\n }\n\n const logLevel = status >= 500 ? 'error' : status >= 400 ? 'warn' : 'info';\n apiLogger[logLevel]('Request completed', logData);\n }\n catch (error)\n {\n const duration = Date.now() - startTime;\n\n apiLogger.error('Request failed', error as Error, {\n requestId,\n method,\n path,\n duration,\n });\n\n throw error;\n }\n };\n}","import type { Context } from 'hono';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport type { TSchema, Static } from '@sinclair/typebox';\nimport type { ApiSuccessResponse } from './api-response.js';\n\n/**\n * File-based Routing System Type Definitions\n */\n\nexport type HeaderRecord = Record<string, string | string[]>;\n\nexport type RouteMeta = {\n public?: boolean;\n skipMiddlewares?: string[];\n tags?: string[];\n description?: string;\n deprecated?: boolean;\n};\n\n/**\n * Route Contract: TypeBox-based type-safe route definition\n *\n * Defines the shape of request/response for a route endpoint\n */\nexport type RouteContract = {\n method: HttpMethod;\n path: string;\n params?: TSchema;\n query?: TSchema;\n body?: TSchema;\n response: TSchema;\n meta?: RouteMeta;\n};\n\n/**\n * Infer types from RouteContract\n *\n * Extracts TypeScript types from TypeBox schemas\n */\nexport type InferContract<TContract extends RouteContract> = {\n params: TContract['params'] extends TSchema\n ? Static<TContract['params']>\n : Record<string, never>;\n query: TContract['query'] extends TSchema\n ? Static<TContract['query']>\n : Record<string, never>;\n body: TContract['body'] extends TSchema\n ? Static<TContract['body']>\n : Record<string, never>;\n response: TContract['response'] extends TSchema\n ? Static<TContract['response']>\n : unknown;\n};\n\n/**\n * RouteContext: Route Handler Dedicated Context\n *\n * Generic version with contract-based type inference\n */\nexport type RouteContext<TContract extends RouteContract = any> = {\n params: InferContract<TContract>['params'];\n query: InferContract<TContract>['query'];\n data(): Promise<InferContract<TContract>['body']>;\n json(\n data: InferContract<TContract>['response'],\n status?: ContentfulStatusCode,\n headers?: HeaderRecord\n ): Response;\n success<T>(\n data: T,\n meta?: ApiSuccessResponse<T>['meta'],\n status?: number\n ): Response;\n paginated<T>(\n data: T[],\n page: number,\n limit: number,\n total: number\n ): Response;\n raw: Context;\n};\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\nexport type RouteHandler<TContract extends RouteContract = any> =\n (c: RouteContext<TContract>) => Response | Promise<Response>;\n\nexport function isHttpMethod(value: unknown): value is HttpMethod\n{\n return (\n typeof value === 'string' &&\n ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(value)\n );\n}","/**\n * Create Hono Server\n *\n * Creates and configures a Hono application instance.\n */\n\nimport { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\n\nimport { loadRoutes } from '../route';\nimport { ErrorHandler, RequestLogger } from '../middleware';\nimport { logger } from '../logger';\nimport { createHealthCheckHandler } from './helpers.js';\n\nimport type { ServerConfig, AppFactory } from './types.js';\n\n// Extend Hono context with error handler flag\ndeclare module 'hono'\n{\n interface ContextVariableMap\n {\n errorHandlerEnabled?: boolean;\n }\n}\n\nconst serverLogger = logger.child('server');\n\n/**\n * Create Hono app with automatic configuration\n *\n * Levels:\n * 1. No app.ts -> Full auto config\n * 2. server.config.ts -> Partial customization\n * 3. app.ts -> Full control (no auto config)\n */\nexport async function createServer(config?: ServerConfig): Promise<Hono>\n{\n const cwd = process.cwd();\n const appPath = join(cwd, 'src', 'server', 'app.ts');\n const appJsPath = join(cwd, 'src', 'server', 'app.js');\n\n // Level 3: Full control with app.ts\n if (existsSync(appPath) || existsSync(appJsPath))\n {\n return await loadCustomApp(appPath, appJsPath, config);\n }\n\n // Level 1 & 2: Auto config\n return await createAutoConfiguredApp(config);\n}\n\nasync function loadCustomApp(\n appPath: string,\n appJsPath: string,\n config?: ServerConfig\n): Promise<Hono>\n{\n const appModule = await import(existsSync(appPath) ? appPath : appJsPath);\n const appFactory: AppFactory = appModule.default;\n\n if (!appFactory)\n {\n throw new Error('app.ts must export a default function that returns a Hono app');\n }\n\n const app = await appFactory();\n\n // Only load routes, everything else is user's responsibility\n const debug = config?.debug ?? process.env.NODE_ENV === 'development';\n await loadRoutes(app, { routesDir: config?.routesPath, debug });\n\n return app;\n}\n\nasync function createAutoConfiguredApp(config?: ServerConfig): Promise<Hono>\n{\n const app = new Hono();\n\n const middlewareConfig = config?.middleware ?? {};\n const enableLogger = middlewareConfig.logger !== false;\n const enableCors = middlewareConfig.cors !== false;\n const enableErrorHandler = middlewareConfig.errorHandler !== false;\n\n // 1. Set error handler flag in context\n if (enableErrorHandler)\n {\n app.use('*', async (c, next) =>\n {\n c.set('errorHandlerEnabled', true);\n await next();\n });\n }\n\n // 2. Default middleware\n applyDefaultMiddleware(app, config, enableLogger, enableCors);\n\n // 3. Custom middleware\n config?.use?.forEach(mw => app.use('*', mw));\n\n // 4. Health check endpoint\n registerHealthCheckEndpoint(app, config);\n\n // 5. beforeRoutes hook\n await executeBeforeRoutesHook(app, config);\n\n // 6. Load routes\n await loadAppRoutes(app, config);\n\n // 7. afterRoutes hook\n await executeAfterRoutesHook(app, config);\n\n // 8. Error handler\n if (enableErrorHandler)\n {\n app.onError(ErrorHandler());\n }\n\n return app;\n}\n\nfunction applyDefaultMiddleware(\n app: Hono,\n config: ServerConfig | undefined,\n enableLogger: boolean,\n enableCors: boolean\n): void\n{\n if (enableLogger)\n {\n app.use('*', RequestLogger());\n }\n\n if (enableCors && config?.cors !== false)\n {\n app.use('*', cors(config?.cors));\n }\n}\n\nfunction registerHealthCheckEndpoint(app: Hono, config?: ServerConfig): void\n{\n const healthCheckConfig = config?.healthCheck ?? {};\n const healthCheckEnabled = healthCheckConfig.enabled !== false;\n const healthCheckPath = healthCheckConfig.path ?? '/health';\n const healthCheckDetailed = healthCheckConfig.detailed\n ?? process.env.NODE_ENV === 'development';\n\n if (healthCheckEnabled)\n {\n app.get(healthCheckPath, createHealthCheckHandler(healthCheckDetailed));\n serverLogger.debug(`Health check endpoint enabled at ${healthCheckPath}`);\n }\n}\n\nasync function executeBeforeRoutesHook(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (!config?.lifecycle?.beforeRoutes)\n {\n return;\n }\n\n try\n {\n await config.lifecycle.beforeRoutes(app);\n }\n catch (error)\n {\n serverLogger.error('beforeRoutes hook failed', error as Error);\n throw new Error('Server initialization failed in beforeRoutes hook');\n }\n}\n\nasync function loadAppRoutes(app: Hono, config?: ServerConfig): Promise<void>\n{\n const debug = config?.debug ?? process.env.NODE_ENV === 'development';\n await loadRoutes(app, {\n routesDir: config?.routesPath,\n debug,\n middlewares: config?.middlewares\n });\n}\n\nasync function executeAfterRoutesHook(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (!config?.lifecycle?.afterRoutes)\n {\n return;\n }\n\n try\n {\n await config.lifecycle.afterRoutes(app);\n }\n catch (error)\n {\n serverLogger.error('afterRoutes hook failed', error as Error);\n throw new Error('Server initialization failed in afterRoutes hook');\n }\n}\n","import type { Hono, Handler } from 'hono';\nimport type { Server } from 'http';\n\nexport function createHealthCheckHandler(detailed: boolean): Handler\n{\n return async (c) =>\n {\n const response: any = {\n status: 'ok',\n timestamp: new Date().toISOString(),\n };\n\n if (detailed)\n {\n const { getDatabase } = await import('../db/index.js');\n const { getRedis } = await import('../cache/index.js');\n\n const db = getDatabase();\n let dbStatus = 'disconnected';\n let dbError: string | undefined;\n if (db)\n {\n try\n {\n await db.execute('SELECT 1');\n dbStatus = 'connected';\n }\n catch (error)\n {\n dbStatus = 'error';\n dbError = error instanceof Error ? error.message : String(error);\n }\n }\n\n const redis = getRedis();\n let redisStatus = 'disconnected';\n let redisError: string | undefined;\n if (redis)\n {\n try\n {\n await redis.ping();\n redisStatus = 'connected';\n }\n catch (error)\n {\n redisStatus = 'error';\n redisError = error instanceof Error ? error.message : String(error);\n }\n }\n\n response.services = {\n database: {\n status: dbStatus,\n ...(dbError && { error: dbError }),\n },\n redis: {\n status: redisStatus,\n ...(redisError && { error: redisError }),\n },\n };\n\n const hasErrors = dbStatus === 'error' || redisStatus === 'error';\n response.status = hasErrors ? 'degraded' : 'ok';\n }\n\n const statusCode = response.status === 'ok' ? 200 : 503;\n return c.json(response, statusCode);\n };\n}\n\nexport function applyServerTimeouts(\n server: Server,\n timeouts: {\n request: number;\n keepAlive: number;\n headers: number;\n }\n): void\n{\n if ('timeout' in server)\n {\n server.timeout = timeouts.request;\n server.keepAliveTimeout = timeouts.keepAlive;\n server.headersTimeout = timeouts.headers;\n }\n}\n\nexport function getTimeoutConfig(config?: {\n request?: number;\n keepAlive?: number;\n headers?: number;\n}): {\n request: number;\n keepAlive: number;\n headers: number;\n}\n{\n return {\n request: config?.request ?? (parseInt(process.env.SERVER_TIMEOUT || '', 10) || 120000),\n keepAlive: config?.keepAlive ?? (parseInt(process.env.SERVER_KEEPALIVE_TIMEOUT || '', 10) || 65000),\n headers: config?.headers ?? (parseInt(process.env.SERVER_HEADERS_TIMEOUT || '', 10) || 60000),\n };\n}\n\nexport function getShutdownTimeout(config?: { timeout?: number }): number\n{\n return config?.timeout ?? (parseInt(process.env.SHUTDOWN_TIMEOUT || '', 10) || 30000);\n}\n\nexport function buildMiddlewareOrder(config: {\n middleware?: {\n logger?: boolean;\n cors?: boolean;\n errorHandler?: boolean;\n };\n use?: any[];\n beforeRoutes?: (app: Hono) => void | Promise<void>;\n afterRoutes?: (app: Hono) => void | Promise<void>;\n}): string[]\n{\n const order: string[] = [];\n const middlewareConfig = config.middleware ?? {};\n const enableLogger = middlewareConfig.logger !== false;\n const enableCors = middlewareConfig.cors !== false;\n const enableErrorHandler = middlewareConfig.errorHandler !== false;\n\n if (enableLogger) order.push('RequestLogger');\n if (enableCors) order.push('CORS');\n config.use?.forEach((_, i) => order.push(`Custom[${i}]`));\n if (config.beforeRoutes) order.push('beforeRoutes hook');\n order.push('Routes');\n if (config.afterRoutes) order.push('afterRoutes hook');\n if (enableErrorHandler) order.push('ErrorHandler');\n\n return order;\n}\n\nexport function buildStartupConfig(\n config: {\n middleware?: {\n logger?: boolean;\n cors?: boolean;\n errorHandler?: boolean;\n };\n use?: any[];\n healthCheck?: {\n enabled?: boolean;\n path?: string;\n detailed?: boolean;\n };\n beforeRoutes?: (app: Hono) => void | Promise<void>;\n afterRoutes?: (app: Hono) => void | Promise<void>;\n shutdown?: {\n timeout?: number;\n };\n },\n timeouts: {\n request: number;\n keepAlive: number;\n headers: number;\n }\n): any\n{\n const middlewareConfig = config.middleware ?? {};\n const healthCheckConfig = config.healthCheck ?? {};\n const healthCheckEnabled = healthCheckConfig.enabled !== false;\n const healthCheckPath = healthCheckConfig.path ?? '/health';\n const healthCheckDetailed = healthCheckConfig.detailed ?? (process.env.NODE_ENV === 'development');\n\n return {\n middleware: {\n logger: middlewareConfig.logger !== false,\n cors: middlewareConfig.cors !== false,\n errorHandler: middlewareConfig.errorHandler !== false,\n custom: config.use?.length ?? 0,\n },\n healthCheck: healthCheckEnabled ? {\n enabled: true,\n path: healthCheckPath,\n detailed: healthCheckDetailed,\n } : { enabled: false },\n hooks: {\n beforeRoutes: !!config.beforeRoutes,\n afterRoutes: !!config.afterRoutes,\n },\n timeout: {\n request: `${timeouts.request}ms`,\n keepAlive: `${timeouts.keepAlive}ms`,\n headers: `${timeouts.headers}ms`,\n },\n shutdown: {\n timeout: `${config.shutdown?.timeout ?? 30000}ms`,\n },\n };\n}\n","/**\n * Start SPFN Server\n *\n * Starts and configures the SPFN HTTP server with graceful shutdown.\n */\n\nimport { serve } from '@hono/node-server';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport type { Server } from 'http';\n\nimport { initRedis, closeRedis } from '../cache';\nimport { initDatabase, closeDatabase } from '../db';\nimport { logger } from '../logger';\nimport { printBanner } from './banner.js';\nimport { validateServerConfig } from './validation.js';\nimport { createServer } from './create-server.js';\nimport {\n applyServerTimeouts,\n getTimeoutConfig,\n getShutdownTimeout,\n buildMiddlewareOrder,\n buildStartupConfig,\n} from './helpers.js';\n\nimport type { ServerConfig, ServerInstance } from './types.js';\n\nconst serverLogger = logger.child('server');\n\n/**\n * Start SPFN server\n *\n * Automatically loads server.config.ts if exists\n * Automatically initializes Database and Redis from environment\n * Sets up graceful shutdown handlers for SIGTERM and SIGINT\n *\n * @returns ServerInstance with server, app, config, and close() method\n */\nexport async function startServer(config?: ServerConfig): Promise<ServerInstance>\n{\n const finalConfig = await loadAndMergeConfig(config);\n const { host, port, debug } = finalConfig;\n\n validateServerConfig(finalConfig);\n\n if (debug)\n {\n logMiddlewareOrder(finalConfig);\n }\n\n try\n {\n await initializeInfrastructure(finalConfig);\n\n const app = await createServer(finalConfig);\n const server = startHttpServer(app, host!, port!);\n\n const timeouts = getTimeoutConfig(finalConfig.timeout);\n applyServerTimeouts(server as Server, timeouts);\n\n logServerTimeouts(timeouts);\n printBanner({\n mode: debug ? 'Development' : 'Production',\n host: host!,\n port: port!,\n });\n\n logServerStarted(debug, host!, port!, finalConfig, timeouts);\n\n const shutdownServer = createShutdownHandler(server as Server, finalConfig);\n const shutdown = createGracefulShutdown(shutdownServer, finalConfig);\n\n registerShutdownHandlers(shutdown);\n\n const serverInstance: ServerInstance = {\n server: server as Server,\n app,\n config: finalConfig,\n close: async () =>\n {\n serverLogger.info('Manual server shutdown requested');\n await shutdownServer();\n },\n };\n\n // Execute afterStart hook\n if (finalConfig.lifecycle?.afterStart)\n {\n serverLogger.debug('Executing afterStart hook...');\n try\n {\n await finalConfig.lifecycle.afterStart(serverInstance);\n }\n catch (error)\n {\n serverLogger.error('afterStart hook failed', error as Error);\n // Don't throw - server is already running\n // Just log the error and continue\n }\n }\n\n return serverInstance;\n }\n catch (error)\n {\n const err = error as Error;\n serverLogger.error('Server initialization failed', err);\n\n await cleanupOnFailure(finalConfig);\n\n throw error;\n }\n}\n\nasync function loadAndMergeConfig(config?: ServerConfig): Promise<ServerConfig>\n{\n const cwd = process.cwd();\n const configPath = join(cwd, 'src', 'server', 'server.config.ts');\n const configJsPath = join(cwd, 'src', 'server', 'server.config.js');\n const builtConfigMjsPath = join(cwd, '.spfn', 'server', 'server.config.mjs');\n const builtConfigPath = join(cwd, '.spfn', 'server', 'server.config.js');\n\n let fileConfig: ServerConfig = {};\n\n // Check in order: .spfn/server (built .mjs), .spfn/server (built .js), src/server (.js), src/server (.ts)\n if (existsSync(builtConfigMjsPath))\n {\n const configModule = await import(builtConfigMjsPath);\n fileConfig = configModule.default ?? {};\n }\n else if (existsSync(builtConfigPath))\n {\n const configModule = await import(builtConfigPath);\n fileConfig = configModule.default ?? {};\n }\n else if (existsSync(configJsPath))\n {\n const configModule = await import(configJsPath);\n fileConfig = configModule.default ?? {};\n }\n else if (existsSync(configPath))\n {\n const configModule = await import(configPath);\n fileConfig = configModule.default ?? {};\n }\n\n return {\n ...fileConfig,\n ...config,\n port: config?.port ?? fileConfig?.port ?? (parseInt(process.env.PORT || '', 10) || 4000),\n host: config?.host ?? fileConfig?.host ?? (process.env.HOST || 'localhost'),\n };\n}\n\nfunction logMiddlewareOrder(config: ServerConfig): void\n{\n const middlewareOrder = buildMiddlewareOrder(config);\n serverLogger.debug('Middleware execution order', {\n order: middlewareOrder,\n });\n}\n\nasync function initializeInfrastructure(config: ServerConfig): Promise<void>\n{\n // Execute beforeInfrastructure hook\n if (config.lifecycle?.beforeInfrastructure)\n {\n serverLogger.debug('Executing beforeInfrastructure hook...');\n try\n {\n await config.lifecycle.beforeInfrastructure(config);\n }\n catch (error)\n {\n serverLogger.error('beforeInfrastructure hook failed', error as Error);\n throw new Error('Server initialization failed in beforeInfrastructure hook');\n }\n }\n\n // Initialize database if not explicitly disabled\n const shouldInitDatabase = config.infrastructure?.database !== false;\n if (shouldInitDatabase)\n {\n serverLogger.debug('Initializing database...');\n await initDatabase(config.database);\n }\n else\n {\n serverLogger.debug('Database initialization disabled');\n }\n\n // Initialize Redis if not explicitly disabled\n const shouldInitRedis = config.infrastructure?.redis !== false;\n if (shouldInitRedis)\n {\n serverLogger.debug('Initializing Redis...');\n await initRedis();\n }\n else\n {\n serverLogger.debug('Redis initialization disabled');\n }\n\n // Execute afterInfrastructure hook\n if (config.lifecycle?.afterInfrastructure)\n {\n serverLogger.debug('Executing afterInfrastructure hook...');\n try\n {\n await config.lifecycle.afterInfrastructure();\n }\n catch (error)\n {\n serverLogger.error('afterInfrastructure hook failed', error as Error);\n throw new Error('Server initialization failed in afterInfrastructure hook');\n }\n }\n}\n\nfunction startHttpServer(app: any, host: string, port: number): any\n{\n serverLogger.debug(`Starting server on ${host}:${port}...`);\n\n const server = serve({\n fetch: app.fetch,\n port,\n hostname: host,\n });\n\n return server;\n}\n\nfunction logServerTimeouts(timeouts: {\n request: number;\n keepAlive: number;\n headers: number;\n}): void\n{\n serverLogger.info('Server timeouts configured', {\n request: `${timeouts.request}ms`,\n keepAlive: `${timeouts.keepAlive}ms`,\n headers: `${timeouts.headers}ms`,\n });\n}\n\nfunction logServerStarted(\n debug: boolean | undefined,\n host: string,\n port: number,\n config: ServerConfig,\n timeouts: { request: number; keepAlive: number; headers: number }\n): void\n{\n const startupConfig = buildStartupConfig(config, timeouts);\n\n serverLogger.info('Server started successfully', {\n mode: debug ? 'development' : 'production',\n host,\n port,\n config: startupConfig,\n });\n}\n\nfunction createShutdownHandler(server: Server, config: ServerConfig): () => Promise<void>\n{\n return async () =>\n {\n serverLogger.debug('Closing HTTP server...');\n await new Promise<void>((resolve) =>\n {\n server.close(() =>\n {\n serverLogger.info('HTTP server closed');\n resolve();\n });\n });\n\n // Execute beforeShutdown hook\n if (config.lifecycle?.beforeShutdown)\n {\n serverLogger.debug('Executing beforeShutdown hook...');\n try\n {\n await config.lifecycle.beforeShutdown();\n }\n catch (error)\n {\n serverLogger.error('beforeShutdown hook failed', error as Error);\n // Continue with shutdown even if hook fails\n }\n }\n\n // Only close resources that were enabled for initialization\n const shouldCloseDatabase = config.infrastructure?.database !== false;\n const shouldCloseRedis = config.infrastructure?.redis !== false;\n\n if (shouldCloseDatabase)\n {\n serverLogger.debug('Closing database connections...');\n await closeDatabase();\n }\n\n if (shouldCloseRedis)\n {\n serverLogger.debug('Closing Redis connections...');\n await closeRedis();\n }\n\n serverLogger.info('Server shutdown completed');\n };\n}\n\nfunction createGracefulShutdown(\n shutdownServer: () => Promise<void>,\n config: ServerConfig\n): (signal: string) => Promise<void>\n{\n return async (signal: string) =>\n {\n serverLogger.info(`${signal} received, starting graceful shutdown...`);\n\n const shutdownTimeout = getShutdownTimeout(config.shutdown);\n\n const timeoutPromise = new Promise<never>((_, reject) =>\n {\n setTimeout(() =>\n {\n reject(new Error(`Graceful shutdown timeout after ${shutdownTimeout}ms`));\n }, shutdownTimeout);\n });\n\n try\n {\n await Promise.race([\n shutdownServer(),\n timeoutPromise,\n ]);\n\n serverLogger.info('Graceful shutdown completed successfully');\n process.exit(0);\n }\n catch (error)\n {\n const err = error as Error;\n\n if (err.message && err.message.includes('timeout'))\n {\n serverLogger.error('Graceful shutdown timeout, forcing exit', err);\n }\n else\n {\n serverLogger.error('Error during graceful shutdown', err);\n }\n\n process.exit(1);\n }\n };\n}\n\nfunction registerShutdownHandlers(shutdown: (signal: string) => Promise<void>): void\n{\n // Increase max listeners to prevent warnings in development with hot reload\n process.setMaxListeners(15);\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n\n process.on('uncaughtException', (error) =>\n {\n // Enhanced logging for EADDRINUSE errors\n if (error.message?.includes('EADDRINUSE'))\n {\n serverLogger.error('Port conflict detected - detailed trace:', {\n error: error.message,\n stack: error.stack,\n code: (error as any).code,\n port: (error as any).port,\n address: (error as any).address,\n syscall: (error as any).syscall,\n });\n }\n else\n {\n serverLogger.error('Uncaught exception', error);\n }\n shutdown('UNCAUGHT_EXCEPTION');\n });\n\n process.on('unhandledRejection', (reason, promise) =>\n {\n serverLogger.error('Unhandled promise rejection', {\n reason,\n promise,\n });\n shutdown('UNHANDLED_REJECTION');\n });\n}\n\nasync function cleanupOnFailure(config: ServerConfig): Promise<void>\n{\n try\n {\n serverLogger.debug('Cleaning up after initialization failure...');\n\n // Only cleanup resources that were enabled for initialization\n const shouldCleanupDatabase = config.infrastructure?.database !== false;\n const shouldCleanupRedis = config.infrastructure?.redis !== false;\n\n if (shouldCleanupDatabase)\n {\n await closeDatabase();\n }\n\n if (shouldCleanupRedis)\n {\n await closeRedis();\n }\n\n serverLogger.debug('Cleanup completed');\n }\n catch (cleanupError)\n {\n serverLogger.error('Cleanup failed', cleanupError as Error);\n }\n}","/**\n * Server Startup Banner\n *\n * Displays SPFN logo and server information at startup.\n */\n\nimport { networkInterfaces } from 'os';\n\n/**\n * Get local network IP address\n */\nfunction getNetworkAddress(): string | null\n{\n const nets = networkInterfaces();\n\n for (const name of Object.keys(nets))\n {\n const netGroup = nets[name];\n if (!netGroup) continue;\n\n for (const net of netGroup)\n {\n // IPv4, non-internal address\n if (net.family === 'IPv4' && !net.internal)\n {\n return net.address;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Print server startup banner\n */\nexport function printBanner(options: {\n mode: string;\n host: string;\n port: number;\n}): void\n{\n const { mode, host, port } = options;\n\n console.log('');\n console.log(' _____ ____ ______ _ _');\n console.log(' / ____| _ \\\\| ____| \\\\ | |');\n console.log(' | (___ | |_) | |__ | \\\\| |');\n console.log(' \\\\___ \\\\| __/| __| | . ` |');\n console.log(' ____) | | | | | |\\\\ |');\n console.log(' |_____/|_| |_| |_| \\\\_|');\n console.log('');\n console.log(` Mode: ${mode}`);\n\n // Show Local and Network addresses like Next.js\n if (host === '0.0.0.0')\n {\n const networkIP = getNetworkAddress();\n console.log(` ▲ Local: http://localhost:${port}`);\n if (networkIP)\n {\n console.log(` ▲ Network: http://${networkIP}:${port}`);\n }\n }\n else\n {\n console.log(` ▲ Local: http://${host}:${port}`);\n }\n\n console.log('');\n}\n","/**\n * Server Configuration Validation\n *\n * Validates server configuration to catch errors early with clear messages.\n */\n\nimport type { ServerConfig } from './types.js';\n\n/**\n * Validate server configuration\n * Throws descriptive errors for invalid configurations\n */\nexport function validateServerConfig(config: ServerConfig): void\n{\n // Port validation\n if (config.port !== undefined)\n {\n if (!Number.isInteger(config.port) || config.port < 0 || config.port > 65535)\n {\n throw new Error(\n `Invalid port: ${config.port}. Port must be an integer between 0 and 65535.`\n );\n }\n }\n\n // Timeout validation\n if (config.timeout)\n {\n const { request, keepAlive, headers } = config.timeout;\n\n if (request !== undefined && (request < 0 || !Number.isFinite(request)))\n {\n throw new Error(`Invalid timeout.request: ${request}. Must be a positive number.`);\n }\n\n if (keepAlive !== undefined && (keepAlive < 0 || !Number.isFinite(keepAlive)))\n {\n throw new Error(`Invalid timeout.keepAlive: ${keepAlive}. Must be a positive number.`);\n }\n\n if (headers !== undefined && (headers < 0 || !Number.isFinite(headers)))\n {\n throw new Error(`Invalid timeout.headers: ${headers}. Must be a positive number.`);\n }\n\n // Logical validation\n if (headers && request && headers > request)\n {\n throw new Error(\n `Invalid timeout configuration: headers timeout (${headers}ms) cannot exceed request timeout (${request}ms).`\n );\n }\n }\n\n // Shutdown timeout validation\n if (config.shutdown?.timeout !== undefined)\n {\n const timeout = config.shutdown.timeout;\n if (timeout < 0 || !Number.isFinite(timeout))\n {\n throw new Error(`Invalid shutdown.timeout: ${timeout}. Must be a positive number.`);\n }\n }\n\n // Health check path validation\n if (config.healthCheck?.path)\n {\n if (!config.healthCheck.path.startsWith('/'))\n {\n throw new Error(\n `Invalid healthCheck.path: \"${config.healthCheck.path}\". Must start with \"/\".`\n );\n }\n }\n}"]}
|