@spfn/core 0.1.0-alpha.7 → 0.1.0-alpha.72

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.
Files changed (59) hide show
  1. package/README.md +168 -195
  2. package/dist/auto-loader-JFaZ9gON.d.ts +80 -0
  3. package/dist/cache/index.d.ts +211 -0
  4. package/dist/cache/index.js +992 -0
  5. package/dist/cache/index.js.map +1 -0
  6. package/dist/client/index.d.ts +92 -92
  7. package/dist/client/index.js +80 -85
  8. package/dist/client/index.js.map +1 -1
  9. package/dist/codegen/generators/index.d.ts +19 -0
  10. package/dist/codegen/generators/index.js +1491 -0
  11. package/dist/codegen/generators/index.js.map +1 -0
  12. package/dist/codegen/index.d.ts +76 -60
  13. package/dist/codegen/index.js +1479 -736
  14. package/dist/codegen/index.js.map +1 -1
  15. package/dist/database-errors-BNNmLTJE.d.ts +86 -0
  16. package/dist/db/index.d.ts +844 -44
  17. package/dist/db/index.js +1262 -1309
  18. package/dist/db/index.js.map +1 -1
  19. package/dist/env/index.d.ts +508 -0
  20. package/dist/env/index.js +1106 -0
  21. package/dist/env/index.js.map +1 -0
  22. package/dist/error-handler-wjLL3v-a.d.ts +44 -0
  23. package/dist/errors/index.d.ts +136 -0
  24. package/dist/errors/index.js +172 -0
  25. package/dist/errors/index.js.map +1 -0
  26. package/dist/index-DHiAqhKv.d.ts +101 -0
  27. package/dist/index.d.ts +3 -374
  28. package/dist/index.js +2394 -2176
  29. package/dist/index.js.map +1 -1
  30. package/dist/logger/index.d.ts +94 -0
  31. package/dist/logger/index.js +774 -0
  32. package/dist/logger/index.js.map +1 -0
  33. package/dist/middleware/index.d.ts +33 -0
  34. package/dist/middleware/index.js +890 -0
  35. package/dist/middleware/index.js.map +1 -0
  36. package/dist/route/index.d.ts +21 -53
  37. package/dist/route/index.js +1234 -219
  38. package/dist/route/index.js.map +1 -1
  39. package/dist/server/index.d.ts +18 -0
  40. package/dist/server/index.js +2390 -2058
  41. package/dist/server/index.js.map +1 -1
  42. package/dist/types-Dzggq1Yb.d.ts +170 -0
  43. package/package.json +59 -15
  44. package/dist/auto-loader-C44TcLmM.d.ts +0 -125
  45. package/dist/bind-pssq1NRT.d.ts +0 -34
  46. package/dist/postgres-errors-CY_Es8EJ.d.ts +0 -1703
  47. package/dist/scripts/index.d.ts +0 -24
  48. package/dist/scripts/index.js +0 -1201
  49. package/dist/scripts/index.js.map +0 -1
  50. package/dist/scripts/templates/api-index.template.txt +0 -10
  51. package/dist/scripts/templates/api-tag.template.txt +0 -11
  52. package/dist/scripts/templates/contract.template.txt +0 -87
  53. package/dist/scripts/templates/entity-type.template.txt +0 -31
  54. package/dist/scripts/templates/entity.template.txt +0 -19
  55. package/dist/scripts/templates/index.template.txt +0 -10
  56. package/dist/scripts/templates/repository.template.txt +0 -37
  57. package/dist/scripts/templates/routes-id.template.txt +0 -59
  58. package/dist/scripts/templates/routes-index.template.txt +0 -44
  59. package/dist/types-SlzTr8ZO.d.ts +0 -143
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/errors/database-errors.ts","../../src/logger/adapters/pino.ts","../../src/logger/logger.ts","../../src/logger/types.ts","../../src/logger/formatters.ts","../../src/logger/transports/console.ts","../../src/logger/transports/file.ts","../../src/logger/config.ts","../../src/logger/adapters/custom.ts","../../src/logger/adapter-factory.ts","../../src/logger/index.ts","../../src/cache/redis-factory.ts","../../src/cache/redis-manager.ts","../../src/cache/index.ts","../../src/errors/http-errors.ts","../../src/errors/error-utils.ts","../../src/errors/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/manager.ts","../../src/db/manager/instance.ts","../../src/db/transaction/context.ts","../../src/db/transaction/middleware.ts","../../src/db/transaction/index.ts","../../src/db/repository/filters.ts","../../src/db/repository/query-builder.ts","../../src/db/repository/repository.ts","../../src/db/repository/factory.ts","../../src/db/repository/request-scope.ts","../../src/db/repository/relation-registry.ts","../../src/db/repository/index.ts","../../src/db/manager/wrapped-db.ts","../../src/db/manager/context.ts","../../src/db/manager/index.ts","../../src/db/manager/config-generator.ts","../../src/db/schema/helpers.ts","../../src/db/schema/index.ts","../../src/db/index.ts","../../src/route/auto-loader.ts","../../src/route/bind.ts","../../src/middleware/error-handler.ts","../../src/middleware/request-logger.ts","../../src/server/server.ts"],"names":["config","timestamp","join","init_logger","cacheLogger","init_config","writeClient","readClient","db","dbLogger","readInstance","writeInstance","init_manager","id","eq","init_factory","getCacheKey","AsyncLocalStorage","init_repository","init_context","relativePath","existsSync","app","debug","Hono","getDatabase","getRedis"],"mappings":"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","file":"index.js","sourcesContent":["/**\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 * Not Found Error (404 Not Found)\n *\n * Requested resource does not exist\n */\nexport class NotFoundError 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 = 'NotFoundError';\n }\n}\n\n/**\n * Validation Error (400 Bad Request)\n *\n * Input data validation failure\n */\nexport class ValidationError extends QueryError\n{\n constructor(message: string, details?: Record<string, any>)\n {\n super(message, 400, details);\n this.name = 'ValidationError';\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 * Pino Logger Adapter\n *\n * Pino를 사용하는 Logger Adapter 구현\n *\n * ✅ 구현 완료:\n * - Pino 기반 로깅\n * - Child logger 지원\n * - Error 객체 처리 (err 필드)\n * - Context 병합\n * - 환경별 설정 (pretty print)\n * - 파일 로깅 with Rotation (자체 구축용)\n *\n * 💡 배포 시나리오:\n * - K8s: Stdout만 (로그 수집기가 처리)\n * - 자체 구축: Stdout + File with Rotation\n *\n * 💡 특징:\n * - 고성능 (Winston보다 5-10배 빠름)\n * - JSON 기본 포맷\n * - 프로덕션 검증됨 (Netflix, Elastic 사용)\n *\n * 🔗 관련 파일:\n * - src/logger/adapters/types.ts (인터페이스)\n * - src/logger/index.ts (Adapter 선택)\n * - src/logger/config.ts (설정)\n */\n\nimport pino from 'pino';\nimport type { LoggerAdapter, AdapterConfig, LogLevel } from './types';\n\n/**\n * Pino Logger Adapter\n */\nexport class PinoAdapter implements LoggerAdapter\n{\n private logger: pino.Logger;\n\n constructor(config: AdapterConfig)\n {\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n const fileLoggingEnabled = process.env.LOGGER_FILE_ENABLED === 'true';\n\n // Transport 설정\n const targets: pino.TransportTargetOptions[] = [];\n\n // 1. Stdout Transport (항상)\n if (!isProduction && isDevelopment)\n {\n // 개발: Pretty Print\n targets.push({\n target: 'pino-pretty',\n level: 'debug',\n options: {\n colorize: true,\n translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l',\n ignore: 'pid,hostname',\n },\n });\n }\n else\n {\n // 프로덕션: JSON (기본 stdout)\n // targets가 비어있으면 자동으로 stdout JSON 사용\n }\n\n // 2. File Transport (자체 구축 시)\n if (fileLoggingEnabled && isProduction)\n {\n const logDir = process.env.LOG_DIR || './logs';\n const maxFileSize = process.env.LOG_MAX_FILE_SIZE || '10M';\n const maxFiles = parseInt(process.env.LOG_MAX_FILES || '10', 10);\n\n targets.push({\n target: 'pino-roll',\n level: 'info',\n options: {\n file: `${logDir}/app.log`,\n frequency: 'daily',\n size: maxFileSize,\n limit: { count: maxFiles },\n mkdir: true,\n },\n });\n }\n\n this.logger = pino({\n level: config.level,\n\n // Transport 설정 (targets가 있으면 사용, 없으면 기본 stdout)\n transport: targets.length > 0 ? { targets } : undefined,\n\n // 기본 필드\n base: config.module ? { module: config.module } : undefined,\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const childLogger = new PinoAdapter({ level: this.logger.level as LogLevel, module });\n childLogger.logger = this.logger.child({ module });\n return childLogger;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(context || {}, message);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(context || {}, message);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.warn(errorOrContext || {}, message);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.error(errorOrContext || {}, message);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.fatal(errorOrContext || {}, message);\n }\n }\n\n async close(): Promise<void>\n {\n // Pino는 자동으로 flush됨\n // 필요시 pino.final() 사용 가능\n }\n}","/**\n * Logger Class\n *\n * Main logger class\n *\n * ✅ Implemented:\n * - 5 log level methods (debug, info, warn, error, fatal)\n * - Child logger creation (per module)\n * - Multiple Transport support\n * - Context object support\n * - Automatic Error object handling\n *\n * 💡 Future considerations:\n * - Log sampling (limit high-frequency logs)\n * - Async batch processing\n * - Memory usage monitoring\n *\n * 🔗 Related files:\n * - src/logger/types.ts (Type definitions)\n * - src/logger/transports/ (Transport implementations)\n * - src/logger/adapter-factory.ts (Singleton instance)\n */\n\nimport type { LogLevel, LogMetadata, LoggerConfig, Transport } from './types';\n\n/**\n * Logger class\n */\nexport class Logger\n{\n private config: LoggerConfig;\n private 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 const metadata: LogMetadata = {\n timestamp: new Date(),\n level,\n message,\n module: this.module,\n error,\n context,\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 * 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 * 로그 포맷팅 유틸리티\n *\n * ✅ 구현 완료:\n * - 컬러 포맷터 (콘솔 출력용)\n * - JSON 포맷터 (파일/전송용)\n * - 타임스탬프 포맷터\n * - 에러 스택 트레이스 포맷팅\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (타입 정의)\n * - src/logger/transports/ (Transport 구현체)\n */\n\nimport type { LogLevel, LogMetadata } from './types';\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 // 로그 레벨\n if (colorize)\n {\n parts.push(colorizeLevel(metadata.level));\n }\n else\n {\n parts.push(metadata.level.toUpperCase().padEnd(5));\n }\n\n // 모듈명\n if (metadata.module)\n {\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${metadata.module}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${metadata.module}]`);\n }\n }\n\n // 메시지\n parts.push(metadata.message);\n\n let output = parts.join(' ');\n\n // Context 추가\n if (metadata.context && Object.keys(metadata.context).length > 0)\n {\n output += '\\n' + formatContext(metadata.context);\n }\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 * 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 * 파일 출력 Transport\n *\n * ✅ 구현 완료:\n * - 날짜별 로그 파일 생성\n * - JSON 포맷 저장\n * - 로그 디렉토리 자동 생성\n * - 비동기 쓰기 (createWriteStream)\n * - 날짜 변경 시 자동 스트림 교체\n *\n * ⚠️ 개선 필요:\n * - 파일 크기 기반 로테이션\n * - 오래된 파일 자동 삭제\n *\n * 💡 향후 고려사항:\n * - 압축된 로그 아카이빙\n * - 외부 스토리지 전송 (S3 등)\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (Transport 인터페이스)\n * - src/logger/formatters.ts (포맷터)\n * - src/logger/config.ts (설정)\n */\n\nimport { createWriteStream, existsSync, mkdirSync } 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 logDir: string;\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\n // TODO: 향후 파일 로테이션 구현 시 사용\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 }\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 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 * Logger configuration by environment\n *\n * ✅ Implemented:\n * - Environment-specific log level configuration\n * - Console Transport configuration\n * - File Transport configuration (for self-hosted)\n * - File rotation configuration\n * - Slack Transport configuration (environment variable based)\n * - Email Transport configuration (environment variable based)\n *\n * 💡 Deployment scenarios:\n * - K8s: Disable file logging (Stdout only)\n * - Self-hosted: LOGGER_FILE_ENABLED=true\n *\n * 🔗 Related files:\n * - src/logger/types.ts (Type definitions)\n * - src/logger/index.ts (Main export)\n * - .env.local (Environment variables)\n */\n\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 * Custom Logger Adapter\n *\n * 자체 구현한 Logger를 사용하는 Adapter\n *\n * ✅ 구현 완료:\n * - 기존 Logger 클래스 래핑\n * - Transport 시스템 (Console, File)\n * - Child logger 지원\n *\n * 💡 용도:\n * - Pino 의존성 제거 필요시\n * - 커스텀 Transport 필요시\n * - 완전한 제어가 필요한 경우\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현)\n * - src/logger/adapters/types.ts (인터페이스)\n */\n\nimport { Logger } from '../logger';\nimport { ConsoleTransport } from '../transports/console';\nimport { FileTransport } from '../transports/file';\nimport { getConsoleConfig, getFileConfig } from '../config';\nimport type { LoggerAdapter, AdapterConfig } from './types';\nimport type { Transport } from '../types';\n\n/**\n * Transport 초기화\n */\nfunction initializeTransports(): Transport[]\n{\n const transports: Transport[] = [];\n\n // Console Transport (항상 활성화)\n const consoleConfig = getConsoleConfig();\n transports.push(new ConsoleTransport(consoleConfig));\n\n // File Transport (프로덕션에서만 활성화)\n const fileConfig = getFileConfig();\n if (fileConfig.enabled)\n {\n transports.push(new FileTransport(fileConfig));\n }\n\n return transports;\n}\n\n/**\n * Custom Logger Adapter\n */\nexport class CustomAdapter implements LoggerAdapter\n{\n private logger: Logger;\n\n constructor(config: AdapterConfig)\n {\n this.logger = new Logger({\n level: config.level,\n module: config.module,\n transports: initializeTransports(),\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const adapter = new CustomAdapter({ level: this.logger.level, module });\n adapter.logger = this.logger.child(module);\n return adapter;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(message, context);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn(message, errorOrContext, context);\n }\n else\n {\n this.logger.warn(message, errorOrContext);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error(message, errorOrContext, context);\n }\n else\n {\n this.logger.error(message, errorOrContext);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal(message, errorOrContext, context);\n }\n else\n {\n this.logger.fatal(message, errorOrContext);\n }\n }\n\n async close(): Promise<void>\n {\n await this.logger.close();\n }\n}","/**\n * Logger Adapter Factory\n *\n * Adapter creation and initialization logic\n */\n\nimport { PinoAdapter } from './adapters/pino.js';\nimport { CustomAdapter } from './adapters/custom.js';\nimport { getDefaultLogLevel } from './config.js';\nimport type { LoggerAdapter } from './adapters/types.js';\n\n/**\n * Adapter type\n */\ntype AdapterType = 'pino' | 'custom';\n\n/**\n * Create adapter instance\n */\nfunction createAdapter(type: AdapterType): LoggerAdapter\n{\n const level = getDefaultLogLevel();\n\n switch (type)\n {\n case 'pino':\n return new PinoAdapter({ level });\n\n case 'custom':\n return new CustomAdapter({ level });\n\n default:\n return new PinoAdapter({ level });\n }\n}\n\n/**\n * Read adapter type from environment variable\n */\nfunction getAdapterType(): AdapterType\n{\n const adapterEnv = process.env.LOGGER_ADAPTER as AdapterType;\n\n if (adapterEnv === 'custom' || adapterEnv === 'pino')\n {\n return adapterEnv;\n }\n\n // Default: pino\n return 'pino';\n}\n\n/**\n * Singleton Logger instance\n */\nexport const logger: LoggerAdapter = createAdapter(getAdapterType());","/**\n * Logger Module Exports\n *\n * Entry point for logger module (Pure re-export only)\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 * 💡 Adapter switching:\n * - Environment variable: LOGGER_ADAPTER=pino (default) or custom\n * - Pino: High performance, production-proven\n * - Custom: Full control, no Pino dependency\n */\n\n// Logger Instance\nexport { logger } from './adapter-factory.js';\n\n// Types\nexport type { LogLevel, LoggerAdapter } from './adapters/types.js';\n","/**\n * Redis factory with automatic environment variable detection\n * Supports: Single, Master-Replica, Sentinel, Cluster\n */\n\nimport type { Redis, Cluster, RedisOptions, ClusterOptions } from 'ioredis';\nimport { logger } from '../logger';\n\nconst cacheLogger = logger.child('cache');\n\nexport interface RedisClients {\n /** Primary Redis for writes (or both read/write if no replica) */\n write?: Redis | Cluster;\n /** Replica Redis for reads (optional, falls back to write) */\n read?: Redis | Cluster;\n}\n\n/**\n * Check if any Redis configuration exists in environment\n */\nfunction hasRedisConfig(): boolean\n{\n return !!(\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 * Create Redis client with TLS support\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 rediss://\n if (url.startsWith('rediss://'))\n {\n options.tls = {\n rejectUnauthorized: process.env.REDIS_TLS_REJECT_UNAUTHORIZED !== 'false',\n };\n }\n\n return new RedisClient(url, options);\n}\n\n/**\n * Create Redis client(s) from environment variables\n *\n * Supported patterns (priority order):\n * 1. Single instance: REDIS_URL\n * 2. Master-Replica: REDIS_WRITE_URL + REDIS_READ_URL\n * 3. Sentinel: REDIS_SENTINEL_HOSTS + REDIS_MASTER_NAME\n * 4. Cluster: REDIS_CLUSTER_NODES\n *\n * @returns Redis client(s) or undefined if no configuration found\n *\n * @example\n * ```bash\n * # Single (most common)\n * REDIS_URL=redis://localhost:6379\n * REDIS_URL=rediss://secure.redis.com:6380 # TLS\n *\n * # Master-Replica\n * REDIS_WRITE_URL=redis://master:6379\n * REDIS_READ_URL=redis://replica:6379\n *\n * # Sentinel\n * REDIS_SENTINEL_HOSTS=sentinel1:26379,sentinel2:26379\n * REDIS_MASTER_NAME=mymaster\n * REDIS_PASSWORD=secret\n *\n * # Cluster\n * REDIS_CLUSTER_NODES=node1:6379,node2:6379,node3:6379\n * REDIS_PASSWORD=secret\n * ```\n */\nexport async function createRedisFromEnv(): Promise<RedisClients>\n{\n // Quick exit if no Redis config\n if (!hasRedisConfig())\n {\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 // 1. Single instance (most common - highest priority)\n if (\n process.env.REDIS_URL &&\n !process.env.REDIS_WRITE_URL &&\n !process.env.REDIS_READ_URL &&\n !process.env.REDIS_CLUSTER_NODES\n )\n {\n const client = createClient(RedisClient, process.env.REDIS_URL);\n return { write: client, read: client };\n }\n\n // 2. Master-Replica pattern (both URLs required)\n if (process.env.REDIS_WRITE_URL && process.env.REDIS_READ_URL)\n {\n const write = createClient(RedisClient, process.env.REDIS_WRITE_URL);\n const read = createClient(RedisClient, process.env.REDIS_READ_URL);\n return { write, read };\n }\n\n // 3. Sentinel pattern\n if (process.env.REDIS_SENTINEL_HOSTS && process.env.REDIS_MASTER_NAME)\n {\n const sentinels = process.env.REDIS_SENTINEL_HOSTS.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: process.env.REDIS_MASTER_NAME,\n password: process.env.REDIS_PASSWORD,\n };\n\n const client = new RedisClient(options);\n return { write: client, read: client };\n }\n\n // 4. Cluster pattern\n if (process.env.REDIS_CLUSTER_NODES)\n {\n const nodes = process.env.REDIS_CLUSTER_NODES.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: process.env.REDIS_PASSWORD,\n },\n };\n\n const cluster = new RedisClient.Cluster(nodes, clusterOptions);\n return { write: cluster, read: cluster };\n }\n\n // 5. Fallback: Single URL with other configs present\n if (process.env.REDIS_URL)\n {\n const client = createClient(RedisClient, process.env.REDIS_URL);\n return { write: client, read: client };\n }\n\n // No valid configuration\n return { write: undefined, read: undefined };\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n cacheLogger.warn(\n 'Failed to create Redis client',\n error,\n { suggestion: 'Using memory-only cache. Install ioredis: npm install ioredis' }\n );\n }\n else\n {\n cacheLogger.warn(\n 'Failed to create Redis client',\n { error: String(error), suggestion: 'Using memory-only cache. Install ioredis: npm install ioredis' }\n );\n }\n return { write: undefined, read: undefined };\n }\n}\n\n/**\n * Create single Redis client (backward compatibility)\n * Only returns write instance\n */\nexport async function createSingleRedisFromEnv(): Promise<Redis | Cluster | undefined>\n{\n const { write } = await createRedisFromEnv();\n return write;\n}","/**\n * Global Redis instance manager\n * Provides singleton access to Redis across all modules\n * Supports Master-Replica pattern with separate read/write instances\n */\n\nimport type { Redis, Cluster } from 'ioredis';\n\nimport { createRedisFromEnv } from './redis-factory.js';\nimport { logger } from '../logger';\n\nconst cacheLogger = logger.child('cache');\n\nlet writeInstance: Redis | Cluster | undefined;\nlet readInstance: Redis | Cluster | undefined;\n\n/**\n * Get global Redis write instance\n *\n * @returns Redis write instance or undefined if not initialized\n *\n * @example\n * ```typescript\n * import { getRedis } from '@spfn/core/cache';\n *\n * const redis = getRedis();\n * if (redis) {\n * await redis.set('key', 'value');\n * }\n * ```\n */\nexport function getRedis(): Redis | Cluster | undefined\n{\n return writeInstance;\n}\n\n/**\n * Get global Redis read instance (falls back to write if no replica)\n *\n * @returns Redis read instance or write instance as fallback\n *\n * @example\n * ```typescript\n * import { getRedisRead } from '@spfn/core/cache';\n *\n * const redis = getRedisRead();\n * if (redis) {\n * const value = await redis.get('key');\n * }\n * ```\n */\nexport function getRedisRead(): Redis | Cluster | undefined\n{\n return readInstance ?? writeInstance;\n}\n\n/**\n * Set global Redis instances (for testing or manual configuration)\n *\n * @param write - Redis write instance\n * @param read - Redis read instance (optional, defaults to write)\n *\n * @example\n * ```typescript\n * import { setRedis } 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 * setRedis(write, read);\n * ```\n */\nexport function setRedis(\n write: Redis | Cluster | undefined,\n read?: Redis | Cluster | undefined\n): void\n{\n writeInstance = write;\n readInstance = read ?? write;\n}\n\n/**\n * Initialize Redis from environment variables\n * Automatically called by startServer()\n *\n * Supported environment variables:\n * - REDIS_URL (single instance)\n * - REDIS_WRITE_URL + REDIS_READ_URL (master-replica)\n * - REDIS_SENTINEL_HOSTS + REDIS_MASTER_NAME (sentinel)\n * - REDIS_CLUSTER_NODES (cluster)\n * - REDIS_TLS_REJECT_UNAUTHORIZED (TLS config)\n *\n * @returns Object with write and read instances\n *\n * @example\n * ```typescript\n * import { initRedis } from '@spfn/core/cache';\n *\n * // Manual initialization (not needed if using startServer)\n * const { write, read } = await initRedis();\n * ```\n */\nexport async function initRedis(): Promise<{ write?: Redis | Cluster; read?: Redis | Cluster }>\n{\n // Already initialized\n if (writeInstance)\n {\n return { write: writeInstance, read: readInstance };\n }\n\n // Auto-detect from environment\n const { write, read } = await createRedisFromEnv();\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\n const hasReplica = read && read !== write;\n cacheLogger.info(\n hasReplica\n ? 'Redis connected (Master-Replica)'\n : 'Redis connected'\n );\n }\n catch (error)\n {\n cacheLogger.error(\n 'Redis connection failed',\n error instanceof Error ? error : new Error(String(error))\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 return { write: undefined, read: undefined };\n }\n }\n\n return { write: writeInstance, read: readInstance };\n}\n\n/**\n * Close all Redis connections and cleanup\n *\n * @example\n * ```typescript\n * import { closeRedis } from '@spfn/core/cache';\n *\n * // During graceful shutdown\n * await closeRedis();\n * ```\n */\nexport async function closeRedis(): Promise<void>\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 Redis 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 Redis read instance', err);\n })\n );\n }\n\n await Promise.all(closePromises);\n\n writeInstance = undefined;\n readInstance = undefined;\n\n cacheLogger.info('Redis connections closed');\n}\n\n/**\n * Get Redis connection info (for debugging)\n */\nexport function getRedisInfo(): {\n hasWrite: boolean;\n hasRead: boolean;\n isReplica: boolean;\n}\n{\n return {\n hasWrite: !!writeInstance,\n hasRead: !!readInstance,\n isReplica: !!(readInstance && readInstance !== writeInstance),\n };\n}","/**\n * Redis cache infrastructure\n * Provides singleton Redis instance management for all SPFN modules\n * Supports Master-Replica pattern with separate read/write instances\n */\n\nexport { createRedisFromEnv, createSingleRedisFromEnv } from './redis-factory.js';\nexport { getRedis, getRedisRead, setRedis, initRedis, closeRedis, getRedisInfo } from './redis-manager.js';\nexport type { RedisClients } from './redis-factory.js';","/**\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 * 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 * 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 * 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 NotFoundError,\n ValidationError,\n TransactionError,\n DeadlockError,\n DuplicateEntryError,\n} from './database-errors.js';\n\n// HTTP Error Classes\nexport {\n HttpError,\n BadRequestError,\n UnauthorizedError,\n ForbiddenError,\n ConflictError,\n TooManyRequestsError,\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 * 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 ValidationError,\n QueryError,\n TransactionError,\n} from '../errors/database-errors.js';\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 ValidationError(message, { code, constraint: 'integrity' });\n\n case '23502': // not_null_violation\n return new ValidationError(message, { code, constraint: 'not_null' });\n\n case '23503': // foreign_key_violation\n return new ValidationError(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 ValidationError(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}","/**\n * Database Connection Logic\n *\n * DB 연결 생성 및 재시도 로직\n *\n * ✅ 구현 완료:\n * - Exponential Backoff 재시도 로직\n * - 연결 테스트 쿼리\n * - 상세한 에러 로깅\n * - 연결 성공/실패 로깅\n * - Logger 적용 (console.log 대체)\n *\n * ⚠️ 개선 필요:\n * - 에러 타입별 처리 (네트워크 vs 인증)\n * - Graceful Shutdown 로직\n *\n * 💡 향후 고려사항:\n * - 연결 풀 이벤트 리스너\n * - 연결 상태 메트릭 수집\n * - 연결 풀 동적 조정\n *\n * 🔗 관련 파일:\n * - src/server/core/db/config.ts (설정)\n * - src/server/core/db/index.ts (메인 export)\n * - src/server/core/logger/ (Logger)\n *\n * 📝 TODO: improvements.md 참고\n * - #7: Connection Pool 모니터링 (Pool 이벤트 리스너, 활성/유휴 연결 추적)\n * - #9: Slow Query 로깅 (쿼리 실행 시간 측정 및 임계값 로깅)\n * - #10: Graceful Shutdown (SIGTERM 처리, 진행 중인 쿼리 완료 대기)\n * - #11: Read Replica 지원 (읽기/쓰기 분리)\n */\nimport type { Sql } from 'postgres';\nimport postgres 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{\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 */\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 * 환경별 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 const isProduction = process.env.NODE_ENV === 'production';\n\n // Priority: options > env > default\n const max = options?.max\n ?? (parseInt(process.env.DB_POOL_MAX || '', 10) || (isProduction ? 20 : 10));\n\n const idleTimeout = options?.idleTimeout\n ?? (parseInt(process.env.DB_POOL_IDLE_TIMEOUT || '', 10) || (isProduction ? 30 : 20));\n\n return { max, idleTimeout };\n}\n\n/**\n * 환경별 재시도 설정\n */\nexport function getRetryConfig(): RetryConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n maxRetries: isProduction ? 5 : 3, // 프로덕션: 5회, 개발: 3회\n initialDelay: 1000, // 1초\n maxDelay: 16000, // 16초\n factor: 2, // 2배씩 증가 (1s → 2s → 4s → 8s → 16s)\n };\n}","/**\n * Database factory with automatic environment variable detection\n * Supports: Single primary, Primary + Replica\n */\n\nimport { config } from 'dotenv';\nimport { drizzle } from 'drizzle-orm/postgres-js';\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport type { Sql } from 'postgres';\n\nimport { createDatabaseConnection } from './connection.js';\nimport { getPoolConfig, getRetryConfig, type PoolConfig } from './config.js';\nimport { logger } from '../../logger';\n\nconst dbLogger = logger.child('database');\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 * 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 * 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 * 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 .env.local if needed\n if (!hasDatabaseConfig())\n {\n config({ path: '.env.local' });\n }\n\n // Quick exit if no database config\n if (!hasDatabaseConfig())\n {\n return { write: undefined, read: undefined };\n }\n\n try\n {\n const poolConfig = getPoolConfig(options?.pool);\n const retryConfig = getRetryConfig();\n\n // 1. Primary + Replica pattern (explicit separation)\n if (process.env.DATABASE_WRITE_URL && process.env.DATABASE_READ_URL)\n {\n const writeClient = await createDatabaseConnection(\n process.env.DATABASE_WRITE_URL,\n poolConfig,\n retryConfig\n );\n\n const readClient = await createDatabaseConnection(\n process.env.DATABASE_READ_URL,\n poolConfig,\n retryConfig\n );\n\n return {\n write: drizzle(writeClient),\n read: drizzle(readClient),\n writeClient,\n readClient,\n };\n }\n\n // 2. Legacy replica pattern (backward compatibility)\n if (process.env.DATABASE_URL && process.env.DATABASE_REPLICA_URL)\n {\n const writeClient = await createDatabaseConnection(\n process.env.DATABASE_URL,\n poolConfig,\n retryConfig\n );\n\n const readClient = await createDatabaseConnection(\n process.env.DATABASE_REPLICA_URL,\n poolConfig,\n retryConfig\n );\n\n return {\n write: drizzle(writeClient),\n read: drizzle(readClient),\n writeClient,\n readClient,\n };\n }\n\n // 3. Single primary (most common)\n if (process.env.DATABASE_URL)\n {\n const client = await createDatabaseConnection(\n process.env.DATABASE_URL,\n poolConfig,\n retryConfig\n );\n\n const db = drizzle(client);\n return {\n write: db,\n read: db,\n writeClient: client,\n readClient: client,\n };\n }\n\n // 4. DATABASE_WRITE_URL only (no read replica)\n if (process.env.DATABASE_WRITE_URL)\n {\n const client = await createDatabaseConnection(\n process.env.DATABASE_WRITE_URL,\n poolConfig,\n retryConfig\n );\n\n const db = drizzle(client);\n return {\n write: db,\n read: db,\n writeClient: client,\n readClient: client,\n };\n }\n\n // No valid configuration\n return { write: undefined, read: undefined };\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 return { write: undefined, read: undefined };\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';\nimport type { Sql } from 'postgres';\n\nimport { createDatabaseFromEnv, type DatabaseOptions, type HealthCheckConfig, type MonitoringConfig } from './factory.js';\nimport { logger } from '../../logger';\n\nconst dbLogger = logger.child('database');\n\nlet writeInstance: PostgresJsDatabase | undefined;\nlet readInstance: PostgresJsDatabase | undefined;\nlet writeClient: Sql | undefined;\nlet readClient: Sql | undefined;\nlet healthCheckInterval: NodeJS.Timeout | undefined;\nlet monitoringConfig: MonitoringConfig | undefined;\n\n/**\n * DB connection type\n */\nexport type DbConnectionType = 'read' | 'write';\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 | undefined\n{\n if (type === 'read')\n {\n return readInstance ?? writeInstance;\n }\n return writeInstance;\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 | undefined,\n read?: PostgresJsDatabase | undefined\n): void\n{\n writeInstance = write;\n readInstance = read ?? write;\n}\n\n/**\n * Get health check configuration with priority resolution\n *\n * Priority: options > env > defaults\n */\nfunction getHealthCheckConfig(options?: Partial<HealthCheckConfig>): HealthCheckConfig\n{\n const parseBoolean = (value: string | undefined, defaultValue: boolean): boolean =>\n {\n if (value === undefined) return defaultValue;\n return value.toLowerCase() === 'true';\n };\n\n return {\n enabled: options?.enabled\n ?? parseBoolean(process.env.DB_HEALTH_CHECK_ENABLED, true),\n interval: options?.interval\n ?? (parseInt(process.env.DB_HEALTH_CHECK_INTERVAL || '', 10) || 60000),\n reconnect: options?.reconnect\n ?? parseBoolean(process.env.DB_HEALTH_CHECK_RECONNECT, true),\n maxRetries: options?.maxRetries\n ?? (parseInt(process.env.DB_HEALTH_CHECK_MAX_RETRIES || '', 10) || 3),\n retryInterval: options?.retryInterval\n ?? (parseInt(process.env.DB_HEALTH_CHECK_RETRY_INTERVAL || '', 10) || 5000),\n };\n}\n\n/**\n * Get monitoring configuration with priority resolution\n *\n * Priority: options > env > defaults\n */\nfunction getMonitoringConfig(options?: Partial<MonitoringConfig>): MonitoringConfig\n{\n const isDevelopment = process.env.NODE_ENV !== 'production';\n const parseBoolean = (value: string | undefined, defaultValue: boolean): boolean =>\n {\n if (value === undefined) return defaultValue;\n return value.toLowerCase() === 'true';\n };\n\n return {\n enabled: options?.enabled\n ?? parseBoolean(process.env.DB_MONITORING_ENABLED, isDevelopment),\n slowThreshold: options?.slowThreshold\n ?? (parseInt(process.env.DB_MONITORING_SLOW_THRESHOLD || '', 10) || 1000),\n logQueries: options?.logQueries\n ?? parseBoolean(process.env.DB_MONITORING_LOG_QUERIES, false),\n };\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 *\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;\n read?: PostgresJsDatabase;\n}>\n{\n // Already initialized\n if (writeInstance)\n {\n dbLogger.debug('Database already initialized');\n return { write: writeInstance, read: readInstance };\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\n writeInstance = result.write;\n readInstance = result.read;\n writeClient = result.writeClient;\n readClient = 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 = getHealthCheckConfig(options?.healthCheck);\n if (healthCheckConfig.enabled)\n {\n startHealthCheck(healthCheckConfig);\n }\n\n // Initialize monitoring configuration\n monitoringConfig = getMonitoringConfig(options?.monitoring);\n if (monitoringConfig.enabled)\n {\n dbLogger.info('Database query monitoring enabled', {\n slowThreshold: `${monitoringConfig.slowThreshold}ms`,\n logQueries: monitoringConfig.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 return { write: undefined, read: undefined };\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: writeInstance, read: readInstance };\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 if (!writeInstance && !readInstance)\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 if (writeClient)\n {\n dbLogger.debug('Closing write connection...');\n closePromises.push(\n writeClient.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 if (readClient && readClient !== writeClient)\n {\n dbLogger.debug('Closing read connection...');\n closePromises.push(\n readClient.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 writeInstance = undefined;\n readInstance = undefined;\n writeClient = undefined;\n readClient = undefined;\n monitoringConfig = 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 return {\n hasWrite: !!writeInstance,\n hasRead: !!readInstance,\n isReplica: !!(readInstance && readInstance !== writeInstance),\n };\n}\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 *\n * @example\n * ```typescript\n * import { startHealthCheck } from '@spfn/core/db';\n *\n * startHealthCheck({\n * enabled: true,\n * interval: 30000, // 30 seconds\n * reconnect: true,\n * maxRetries: 5,\n * retryInterval: 10000, // 10 seconds\n * });\n * ```\n */\nexport function startHealthCheck(config: HealthCheckConfig): void\n{\n if (healthCheckInterval)\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 healthCheckInterval = 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 dbLogger.debug('Database health check passed');\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);\n }\n }\n }, config.interval);\n}\n\n/**\n * Attempt database reconnection with retry logic\n *\n * @param config - Health check configuration\n */\nasync function attemptReconnection(config: HealthCheckConfig): 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();\n\n if (result.write)\n {\n // Test connection\n await result.write.execute('SELECT 1');\n\n // Store instances\n writeInstance = result.write;\n readInstance = result.read;\n writeClient = result.writeClient;\n readClient = 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';\n *\n * stopHealthCheck();\n * ```\n */\nexport function stopHealthCheck(): void\n{\n if (healthCheckInterval)\n {\n clearInterval(healthCheckInterval);\n healthCheckInterval = undefined;\n dbLogger.info('Database health check stopped');\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 monitoringConfig;\n}","/**\n * Database Instance (Backward Compatibility Layer)\n *\n * PostgreSQL + Drizzle ORM connection - now using lazy initialization\n *\n * ✅ Implemented:\n * - Lazy initialization (no top-level await)\n * - Automatic environment variable loading\n * - Read Replica support (read/write separation)\n * - Singleton pattern via db-manager\n * - Backward compatibility with existing code\n *\n * ⚠️ Migration Note:\n * This file now wraps db-manager for backward compatibility.\n * New code should use:\n * - initDatabase() from db-manager\n * - getDatabase() from db-manager\n *\n * 🔗 Related files:\n * - src/db/db-factory.ts (Environment detection)\n * - src/db/db-manager.ts (Singleton management)\n * - src/db/db-context.ts (Transaction-aware access)\n */\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nimport { getDatabase, type DbConnectionType } from './manager.js';\n\n/**\n * Default DB instance (Primary - for writes)\n *\n * ⚠️ IMPORTANT: This is a lazy getter. On first access, it will:\n * 1. Auto-initialize database from environment variables\n * 2. Throw error if DATABASE_URL is not set\n *\n * For better error handling, use initDatabase() explicitly:\n * ```typescript\n * import { initDatabase } from '@spfn/core/db';\n * const { write } = await initDatabase();\n * if (!write) throw new Error('Database not configured');\n * ```\n *\n * @example\n * ```typescript\n * import { db } from '@spfn/core/db';\n * const users = await db.select().from(usersTable);\n * ```\n */\nexport const db = new Proxy({} as PostgresJsDatabase, {\n get(_target, prop)\n {\n const instance = getDatabase('write');\n if (!instance)\n {\n throw new Error(\n 'Database not initialized. ' +\n 'Set DATABASE_URL environment variable or call initDatabase() first.'\n );\n }\n return (instance as Record<string | symbol, any>)[prop];\n },\n});\n\n/**\n * Get raw Drizzle DB instance (direct use without transaction)\n *\n * ⚠️ Warning: This function bypasses AsyncLocalStorage transaction context.\n * For normal cases, use `getDb()` from './db-context.js'.\n *\n * @param type - 'read' (Replica) or 'write' (Primary)\n * @returns Raw Drizzle DB instance\n *\n * @example\n * ```typescript\n * // Read-only query (uses Replica)\n * const users = await getRawDb('read').select().from(usersTable);\n *\n * // Write query (uses Primary)\n * await getRawDb('write').insert(usersTable).values({ email: 'test@example.com' });\n * ```\n */\nexport function getRawDb(type: DbConnectionType = 'write'): PostgresJsDatabase\n{\n const instance = getDatabase(type);\n if (!instance)\n {\n throw new Error(\n 'Database not initialized. ' +\n 'Set DATABASE_URL environment variable or call initDatabase() first.'\n );\n }\n return instance;\n}\n\n// Re-export type for backward compatibility\nexport type { DbConnectionType };\n","/**\n * AsyncLocalStorage-based Transaction Context\n *\n * Uses Node.js AsyncLocalStorage to propagate transactions throughout the async call chain.\n *\n * ✅ Implemented:\n * - AsyncLocalStorage-based context management\n * - Transaction storage/retrieval functions\n * - Type-safe transaction propagation\n * - Transaction propagation across async chains\n *\n * ⚠️ Needs improvement:\n * - Nested transaction handling (currently ignores outer transaction)\n * - Transaction timeout detection\n *\n * 💡 Future considerations:\n * - Add transaction ID (for debugging/tracing)\n * - Track transaction start time (for performance monitoring)\n * - Store transaction metadata (route info, user info, etc.)\n * - Savepoint support (nested transactions)\n * - Transaction isolation level configuration\n *\n * 🔗 Related files:\n * - src/utils/transaction.ts (Transactional middleware)\n * - src/db/db-context.ts (getDb helper)\n */\nimport { AsyncLocalStorage } from 'async_hooks';\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\n/**\n * Transaction database type\n * Record<string, never> represents an empty schema; actual schema is determined at runtime\n */\nexport type TransactionDB = PostgresJsDatabase;\n\n/**\n * Transaction context stored in AsyncLocalStorage\n */\nexport type TransactionContext = {\n tx: TransactionDB;\n};\n\n/**\n * Global AsyncLocalStorage instance for transaction context\n */\nexport const asyncContext = new AsyncLocalStorage<TransactionContext>();\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 = asyncContext.getStore();\n return context?.tx ?? 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 callback - Function to run within transaction context\n * @returns Result of the callback\n */\nexport function runWithTransaction<T>(\n tx: TransactionDB,\n callback: () => Promise<T>\n): Promise<T>\n{\n return asyncContext.run({ tx }, 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 * ✅ Implemented:\n * - Automatic transaction start/commit/rollback\n * - Transaction propagation via AsyncLocalStorage\n * - Hono Context error detection\n * - Integration with getDb() helper\n * - Type safety improvements (TransactionDB type, no @ts-ignore)\n * - Transaction logging (start/commit/rollback)\n * - Execution time measurement and slow transaction warnings\n * - Transaction ID tracking (for debugging)\n * - Transaction timeout configuration (with TRANSACTION_TIMEOUT env var support)\n *\n * ⚠️ Needs improvement:\n * - Detect and warn about nested transactions\n *\n * 💡 Future considerations:\n * - Transaction isolation level configuration option\n * - Read-only transaction mode\n * - Transaction retry logic (on deadlock)\n * - Transaction event hooks (beforeCommit, afterCommit, onRollback)\n *\n * 🔗 Related files:\n * - src/utils/async-context.ts (AsyncLocalStorage)\n * - src/db/db-context.ts (getDb helper)\n * - src/utils/__tests__/transaction.test.ts (tests)\n *\n * 📝 Future improvements:\n * - Transaction isolation level setting (withTransaction({ isolationLevel: 'SERIALIZABLE' }))\n * - Nested transaction savepoint support\n */\nimport { createMiddleware } from 'hono/factory';\nimport { db } from '../index.js';\nimport { runWithTransaction, type TransactionDB } from './context.js';\nimport { logger } from '../../logger';\nimport { TransactionError } from '../../errors';\nimport { fromPostgresError } from '../postgres-errors';\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\n const txId = `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\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 // Create transaction promise\n const transactionPromise = db.transaction(async (tx) =>\n {\n // Store transaction in AsyncLocalStorage\n await runWithTransaction(tx as TransactionDB, 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 } 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 * Repository Filter Utilities\n *\n * Utilities for building Drizzle ORM WHERE, ORDER BY, and pagination conditions.\n * Moved from deprecated query module for Repository pattern usage.\n *\n * @module db/repository/filters\n */\n\nimport { and, eq, ne, gt, gte, lt, lte, like, inArray, notInArray, isNull, isNotNull, or, asc, desc, sql, SQL } from 'drizzle-orm';\n\nimport type { PgColumn, PgTable } from 'drizzle-orm/pg-core';\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Filter operators\n */\nexport type FilterOperator =\n | 'eq' // equals\n | 'ne' // not equals\n | 'gt' // greater than\n | 'gte' // greater than or equal\n | 'lt' // less than\n | 'lte' // less than or equal\n | 'like' // LIKE (partial match)\n | 'in' // IN (array)\n | 'nin' // NOT IN (array)\n | 'is'; // IS NULL / IS NOT NULL\n\n/**\n * Filter value type\n */\nexport type FilterValue = string | number | boolean | null | (string | number)[];\n\n/**\n * Filter condition\n *\n * @example { email: { eq: 'john@example.com' } }\n * @example { age: { gte: 18, lte: 65 } }\n */\nexport type FilterCondition = {\n [operator in FilterOperator]?: FilterValue;\n};\n\n/**\n * Complete filters\n *\n * @example { email: { eq: 'john@example.com' }, role: { in: ['admin', 'user'] } }\n */\nexport type Filters = {\n [field: string]: FilterCondition;\n};\n\n/**\n * Filter builder result type\n */\nexport type FilterResult = SQL<unknown> | undefined;\n\n/**\n * Sort direction\n */\nexport type SortDirection = 'asc' | 'desc';\n\n/**\n * Sort condition\n *\n * @example [{ field: 'createdAt', direction: 'desc' }, { field: 'name', direction: 'asc' }]\n */\nexport type SortCondition = {\n field: string;\n direction: SortDirection;\n};\n\n/**\n * Sort builder result type\n */\nexport type SortResult = SQL<unknown>[];\n\n/**\n * Pagination parameters\n */\nexport type PaginationParams = {\n page: number;\n limit: number;\n};\n\n/**\n * Pagination metadata\n */\nexport type PaginationMeta = {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n hasNext: boolean;\n hasPrev: boolean;\n};\n\n/**\n * Drizzle table type (generic)\n */\nexport type DrizzleTable = PgTable<any> & Record<string, PgColumn>;\n\n// ============================================================================\n// Filter Builder\n// ============================================================================\n\n/**\n * Convert filter conditions to Drizzle SQL WHERE conditions\n *\n * @param filters - Parsed filter object\n * @param table - Drizzle table schema\n * @returns SQL WHERE condition (undefined if no filters)\n *\n * @example\n * const filters = { email: { eq: 'john@example.com' }, age: { gte: 18 } };\n * const condition = buildFilters(filters, users);\n * const data = await db.select().from(users).where(condition);\n */\nexport function buildFilters(\n filters: Filters,\n table: DrizzleTable\n): FilterResult\n{\n const conditions: SQL<unknown>[] = [];\n\n for (const [field, filterCondition] of Object.entries(filters))\n {\n const column = table[field] as PgColumn;\n\n if (!column)\n {\n console.warn(`[buildFilters] Unknown field: ${field}`);\n continue;\n }\n\n // Build condition for each operator\n for (const [operator, value] of Object.entries(filterCondition))\n {\n const condition = buildCondition(column, operator as FilterOperator, value);\n if (condition)\n {\n conditions.push(condition);\n }\n }\n }\n\n // Combine all conditions with AND\n return conditions.length > 0 ? and(...conditions) : undefined;\n}\n\n/**\n * Convert single filter condition to SQL condition\n */\nfunction buildCondition(\n column: PgColumn,\n operator: FilterOperator,\n value: FilterValue\n): SQL<unknown> | undefined\n{\n switch (operator)\n {\n case 'eq':\n return eq(column, value as string | number);\n\n case 'ne':\n return ne(column, value as string | number);\n\n case 'gt':\n return gt(column, value as string | number);\n\n case 'gte':\n return gte(column, value as string | number);\n\n case 'lt':\n return lt(column, value as string | number);\n\n case 'lte':\n return lte(column, value as string | number);\n\n case 'like':\n return like(column, `%${value}%`);\n\n case 'in':\n if (Array.isArray(value))\n {\n return inArray(column, value);\n }\n console.warn(`[buildCondition] 'in' operator requires array value`);\n return undefined;\n\n case 'nin':\n if (Array.isArray(value))\n {\n return notInArray(column, value);\n }\n console.warn(`[buildCondition] 'nin' operator requires array value`);\n return undefined;\n\n case 'is':\n if (value === 'null') return isNull(column);\n if (value === 'notnull') return isNotNull(column);\n console.warn(`[buildCondition] 'is' operator requires 'null' or 'notnull'`);\n return undefined;\n\n default:\n console.warn(`[buildCondition] Unknown operator: ${operator}`);\n return undefined;\n }\n}\n\n/**\n * Combine conditions with OR\n *\n * @example\n * const conditions = [\n * buildFilters({ status: { eq: 'active' } }, users),\n * buildFilters({ role: { eq: 'admin' } }, users)\n * ];\n * const orCondition = orFilters(...conditions);\n */\nexport function orFilters(...conditions: (FilterResult)[]): FilterResult\n{\n const validConditions = conditions.filter(c => c !== undefined) as SQL<unknown>[];\n return validConditions.length > 0 ? or(...validConditions) : undefined;\n}\n\n// ============================================================================\n// Sort Builder\n// ============================================================================\n\n/**\n * Convert sort conditions to Drizzle SQL ORDER BY conditions\n *\n * @param sortConditions - Sort condition array\n * @param table - Drizzle table schema\n * @returns SQL ORDER BY condition array\n *\n * @example\n * const sort = [\n * { field: 'createdAt', direction: 'desc' },\n * { field: 'name', direction: 'asc' }\n * ];\n * const orderBy = buildSort(sort, users);\n * const data = await db.select().from(users).orderBy(...orderBy);\n */\nexport function buildSort(\n sortConditions: SortCondition[],\n table: DrizzleTable\n): SortResult\n{\n const orderByClauses: SQL<unknown>[] = [];\n\n for (const { field, direction } of sortConditions)\n {\n const column = table[field] as PgColumn;\n\n if (!column)\n {\n console.warn(`[buildSort] Unknown field: ${field}`);\n continue;\n }\n\n const clause = direction === 'desc' ? desc(column) : asc(column);\n orderByClauses.push(clause);\n }\n\n return orderByClauses;\n}\n\n// ============================================================================\n// Pagination Utilities\n// ============================================================================\n\n/**\n * Apply pagination to Drizzle query\n *\n * @param pagination - Pagination parameters\n * @returns { offset, limit } object\n *\n * @example\n * const { offset, limit } = applyPagination({ page: 2, limit: 20 });\n * const data = await db.select().from(users).limit(limit).offset(offset);\n */\nexport function applyPagination(pagination: PaginationParams)\n{\n const { page, limit } = pagination;\n const offset = (page - 1) * limit;\n\n return { offset, limit };\n}\n\n/**\n * Create pagination metadata\n *\n * @param pagination - Pagination parameters\n * @param total - Total count\n * @returns Pagination metadata\n *\n * @example\n * const meta = createPaginationMeta({ page: 2, limit: 20 }, 156);\n * // { page: 2, limit: 20, total: 156, totalPages: 8, hasNext: true, hasPrev: true }\n */\nexport function createPaginationMeta(\n pagination: PaginationParams,\n total: number\n): PaginationMeta\n{\n const { page, limit } = pagination;\n const totalPages = Math.ceil(total / limit);\n\n return {\n page,\n limit,\n total,\n totalPages,\n hasNext: page < totalPages,\n hasPrev: page > 1,\n };\n}\n\n/**\n * Count total records (count query)\n *\n * @param db - Drizzle DB instance\n * @param table - Table schema\n * @param whereCondition - WHERE condition (optional)\n * @returns Total count\n *\n * @example\n * const total = await countTotal(db, users);\n * const total = await countTotal(db, users, eq(users.status, 'active'));\n */\nexport async function countTotal(\n db: PostgresJsDatabase<Record<string, never>>,\n table: DrizzleTable,\n whereCondition?: any\n): Promise<number>\n{\n const query = db\n .select({ count: sql<number>`count(*)::int` })\n .from(table);\n\n if (whereCondition)\n {\n query.where(whereCondition);\n }\n\n const [result] = await query;\n return result?.count || 0;\n}","/**\n * Query Builder (Fluent Interface)\n *\n * Chainable query builder for Repository pattern.\n * Provides a fluent API for building complex queries.\n *\n * @example\n * ```typescript\n * const users = await userRepo\n * .query()\n * .where({ status: 'active' })\n * .where({ role: 'admin' })\n * .orderBy('createdAt', 'desc')\n * .limit(10)\n * .findMany();\n * ```\n */\n\nimport type { PgTable } from 'drizzle-orm/pg-core';\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nimport type { Filters, SortCondition } from './filters.js';\n\nimport { buildFilters, buildSort } from './filters.js';\n\n/**\n * Query Builder class for chainable queries\n *\n * Supports method chaining for building complex queries in a fluent style.\n */\nexport class QueryBuilder<\n TTable extends PgTable,\n TSelect = TTable['$inferSelect']\n>\n{\n private db: PostgresJsDatabase<any>;\n private table: TTable;\n private filterConditions: Filters[] = [];\n private sortConditions: SortCondition[] = [];\n private limitValue?: number;\n private offsetValue?: number;\n\n constructor(db: PostgresJsDatabase<any>, table: TTable)\n {\n this.db = db;\n this.table = table;\n }\n\n /**\n * Add WHERE conditions\n *\n * Multiple where() calls are combined with AND logic.\n *\n * @param filters - Filter conditions\n * @returns QueryBuilder for chaining\n *\n * @example\n * ```typescript\n * query\n * .where({ status: 'active' })\n * .where({ role: 'admin' }) // AND condition\n * ```\n */\n where(filters: Filters): this\n {\n this.filterConditions.push(filters);\n return this;\n }\n\n /**\n * Add ORDER BY clause\n *\n * Multiple orderBy() calls create multi-column sorting.\n *\n * @param field - Field name to sort by\n * @param direction - Sort direction ('asc' or 'desc')\n * @returns QueryBuilder for chaining\n *\n * @example\n * ```typescript\n * query\n * .orderBy('isPremium', 'desc')\n * .orderBy('createdAt', 'desc')\n * ```\n */\n orderBy(field: string, direction: 'asc' | 'desc' = 'asc'): this\n {\n this.sortConditions.push({ field, direction });\n return this;\n }\n\n /**\n * Set LIMIT clause\n *\n * @param limit - Maximum number of records to return\n * @returns QueryBuilder for chaining\n *\n * @example\n * ```typescript\n * query.limit(10)\n * ```\n */\n limit(limit: number): this\n {\n this.limitValue = limit;\n return this;\n }\n\n /**\n * Set OFFSET clause\n *\n * @param offset - Number of records to skip\n * @returns QueryBuilder for chaining\n *\n * @example\n * ```typescript\n * query.offset(20)\n * ```\n */\n offset(offset: number): this\n {\n this.offsetValue = offset;\n return this;\n }\n\n /**\n * Execute query and return multiple records\n *\n * @returns Array of records\n *\n * @example\n * ```typescript\n * const users = await query\n * .where({ status: 'active' })\n * .orderBy('createdAt', 'desc')\n * .limit(10)\n * .findMany();\n * ```\n */\n async findMany(): Promise<TSelect[]>\n {\n // Merge all filter conditions with AND\n const mergedFilters = this.mergeFilters();\n const whereCondition = buildFilters(mergedFilters, this.table as any);\n const orderBy = buildSort(this.sortConditions, this.table as any);\n\n let query = this.db\n .select()\n .from(this.table as any)\n .where(whereCondition)\n .orderBy(...orderBy);\n\n if (this.limitValue !== undefined)\n {\n query = query.limit(this.limitValue) as any;\n }\n\n if (this.offsetValue !== undefined)\n {\n query = query.offset(this.offsetValue) as any;\n }\n\n return query as Promise<TSelect[]>;\n }\n\n /**\n * Execute query and return first record\n *\n * @returns First matching record or null\n *\n * @example\n * ```typescript\n * const user = await query\n * .where({ email: 'john@example.com' })\n * .findOne();\n * ```\n */\n async findOne(): Promise<TSelect | null>\n {\n const results = await this.limit(1).findMany();\n return results[0] ?? null;\n }\n\n /**\n * Execute query and return count\n *\n * @returns Number of matching records\n *\n * @example\n * ```typescript\n * const count = await query\n * .where({ status: 'active' })\n * .count();\n * ```\n */\n async count(): Promise<number>\n {\n const mergedFilters = this.mergeFilters();\n const whereCondition = buildFilters(mergedFilters, this.table as any);\n\n const { count } = await import('drizzle-orm');\n const result = await this.db\n .select({ count: count() })\n .from(this.table as any)\n .where(whereCondition);\n\n return Number(result[0]?.count ?? 0);\n }\n\n /**\n * Merge multiple filter conditions into single object\n *\n * Combines all where() calls into one filter object.\n */\n private mergeFilters(): Filters\n {\n if (this.filterConditions.length === 0)\n {\n return {};\n }\n\n // Merge all filter objects\n return this.filterConditions.reduce((merged, current) => {\n return { ...merged, ...current };\n }, {});\n }\n}","/**\n * Repository Pattern (JPA Style)\n *\n * Spring JPA-inspired Repository pattern for TypeScript/Drizzle ORM\n *\n * ✅ Features:\n * - Auto Read/Write Replica routing (read methods use Replica, write methods use Primary)\n * - Type-safe CRUD operations (findById, findWhere, save, update, delete, etc.)\n * - Advanced filtering with operators (eq, gt, like, in, etc.)\n * - Pagination with metadata (findPage)\n * - Batch operations (saveMany, updateWhere, deleteWhere)\n * - Transaction-aware (automatic participation in Transactional middleware)\n */\n\nimport type { SQL } from 'drizzle-orm';\nimport type { PgTable } from 'drizzle-orm/pg-core';\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nimport type { Filters, SortCondition, PaginationParams, PaginationMeta } from './filters.js';\n\nimport { buildFilters, buildSort, applyPagination, createPaginationMeta, countTotal } from './filters.js';\nimport { getRawDb, getDatabaseMonitoringConfig } from '../manager';\nimport { getTransaction } from '../transaction';\nimport { QueryError } from '../../errors';\nimport { QueryBuilder } from './query-builder.js';\nimport { logger } from '../../logger';\n\n/**\n * Pageable interface (Spring Pageable style)\n */\nexport type Pageable = {\n filters?: Filters;\n sort?: SortCondition[];\n pagination?: PaginationParams;\n};\n\n/**\n * Page result (Spring Page style)\n */\nexport type Page<T> = {\n data: T[];\n meta: PaginationMeta;\n};\n\n/**\n * Repository class\n *\n * Provides JPA Repository-style CRUD methods with automatic transaction support\n *\n * ✅ Automatic Transaction Detection:\n * - Automatically participates in active Transactional() middleware context\n * - No need to pass transaction explicitly - uses AsyncLocalStorage\n * - All operations within a transaction use the same transaction DB\n *\n * ✅ Auto Read/Write Replica routing (when NOT in transaction):\n * - Read methods (findAll, findById, findOne, findPage, count) → Uses Read Replica\n * - Write methods (save, update, delete) → Uses Primary DB\n *\n * ✅ DB Priority:\n * 1. Explicit DB (if provided in constructor)\n * 2. Transaction context (if inside Transactional middleware)\n * 3. Read Replica or Primary DB (based on operation type)\n *\n * @example\n * ```typescript\n * // Simple usage - automatically detects transaction\n * class UserService {\n * private get repo() {\n * return new Repository(users); // Auto-detects transaction\n * }\n * }\n *\n * // Route with transaction\n * app.bind(contract, Transactional(), async (c) => {\n * const service = new UserService();\n * await service.createUser(data);\n * // Automatic rollback on error!\n * });\n * ```\n */\nexport class Repository<\n TTable extends PgTable,\n TSelect = TTable['$inferSelect']\n>\n{\n protected db: PostgresJsDatabase<any>;\n protected table: TTable;\n protected useReplica: boolean;\n protected explicitDb?: PostgresJsDatabase<any>; // Track if db was explicitly provided\n protected autoUpdateField?: string; // Field name to auto-update (e.g., 'updatedAt', 'modifiedAt')\n\n constructor(\n dbOrTable: PostgresJsDatabase<any> | TTable,\n tableOrUseReplica?: TTable | boolean,\n useReplica: boolean = true\n ) {\n // Overload 1: new Repository(table) - db auto-resolved\n if ('name' in dbOrTable && typeof dbOrTable.name === 'string') {\n this.db = getRawDb('write');\n this.table = dbOrTable as TTable;\n this.useReplica = typeof tableOrUseReplica === 'boolean' ? tableOrUseReplica : true;\n this.explicitDb = undefined; // No explicit db provided\n }\n // Overload 2: new Repository(db, table, useReplica?) - explicit db provided\n else {\n this.db = dbOrTable as PostgresJsDatabase<any>;\n this.table = tableOrUseReplica as TTable;\n this.useReplica = useReplica;\n this.explicitDb = this.db; // Save explicit db\n }\n\n // Detect auto-update timestamp field from schema\n this.autoUpdateField = this.detectAutoUpdateField();\n }\n\n /**\n * Detect which field (if any) should be auto-updated\n *\n * Checks all table columns for __autoUpdate metadata flag.\n * Set by autoUpdateTimestamp() or timestamps({ autoUpdate: true }) helpers.\n *\n * @returns Field name to auto-update, or undefined if none found\n */\n private detectAutoUpdateField(): string | undefined\n {\n // Guard against undefined/null table\n if (!this.table || typeof this.table !== 'object')\n {\n return undefined;\n }\n\n const tableColumns = this.table as Record<string, any>;\n\n for (const [fieldName, column] of Object.entries(tableColumns))\n {\n // Skip non-column properties (like '_', '$inferSelect', etc.)\n if (fieldName.startsWith('_') || fieldName.startsWith('$'))\n {\n continue;\n }\n\n // Check if column has __autoUpdate flag\n if (column && typeof column === 'object' && column.__autoUpdate === true)\n {\n return fieldName;\n }\n }\n\n return undefined;\n }\n\n /**\n * Inject auto-update timestamp if configured\n *\n * Only injects if:\n * 1. Table has an auto-update field configured (via autoUpdateTimestamp() or timestamps({ autoUpdate: true }))\n * 2. The field is not already explicitly provided in the data\n *\n * @param data - Update data object\n * @returns Data with auto-update timestamp injected (if applicable)\n */\n private injectAutoUpdateTimestamp(data: any): any\n {\n // No auto-update field configured\n if (!this.autoUpdateField)\n {\n return data;\n }\n\n // Field already explicitly provided, don't override\n if (data && this.autoUpdateField in data)\n {\n return data;\n }\n\n // Inject current timestamp\n return {\n ...data,\n [this.autoUpdateField]: new Date(),\n };\n }\n\n /**\n * Get id column from table\n *\n * Helper method to reduce code duplication across methods that need id column.\n *\n * @returns The id column object\n * @throws {QueryError} If table does not have an id column\n */\n private getIdColumn()\n {\n const idColumn = (this.table as Record<string, any>).id;\n\n if (!idColumn)\n {\n throw new QueryError('Table does not have an id column');\n }\n\n return idColumn;\n }\n\n /**\n * Get read-only DB\n *\n * Automatically detects and uses transaction context if available.\n * When in transaction, uses transaction DB to ensure read consistency.\n * Priority: explicitDb > transaction > replica/primary DB\n */\n private getReadDb(): PostgresJsDatabase<any>\n {\n // If db was explicitly provided, always use it\n if (this.explicitDb) {\n return this.explicitDb;\n }\n\n // Check if we're inside a transaction context\n // Use transaction for reads too to ensure consistency\n const tx = getTransaction();\n if (tx) {\n return tx;\n }\n\n // Otherwise use getRawDb for replica routing\n return this.useReplica ? getRawDb('read') : this.db;\n }\n\n /**\n * Get write-only DB\n *\n * Automatically detects and uses transaction context if available.\n * Priority: explicitDb > transaction > primary DB\n */\n private getWriteDb(): PostgresJsDatabase<any>\n {\n // If db was explicitly provided, always use it\n if (this.explicitDb) {\n return this.explicitDb;\n }\n\n // Check if we're inside a transaction context\n const tx = getTransaction();\n if (tx) {\n return tx;\n }\n\n // Otherwise use getRawDb for write operations\n return getRawDb('write');\n }\n\n /**\n * Execute operation with performance monitoring\n *\n * Wraps database operations with timing and logging for slow queries.\n * Only logs if monitoring is enabled and query exceeds threshold.\n *\n * @param operation - Name of the operation (for logging)\n * @param fn - Async function to execute\n * @returns Result of the operation\n */\n private async executeWithMonitoring<T>(\n operation: string,\n fn: () => Promise<T>\n ): Promise<T>\n {\n const config = getDatabaseMonitoringConfig();\n\n // If monitoring is disabled, just execute the operation\n if (!config?.enabled)\n {\n return fn();\n }\n\n const startTime = performance.now();\n\n try\n {\n const result = await fn();\n const duration = performance.now() - startTime;\n\n // Log slow queries\n if (duration >= config.slowThreshold)\n {\n const dbLogger = logger.child('database');\n const logData: any = {\n operation,\n table: this.table._.name,\n duration: `${duration.toFixed(2)}ms`,\n threshold: `${config.slowThreshold}ms`,\n };\n\n dbLogger.warn('Slow query detected', logData);\n }\n\n return result;\n }\n catch (error)\n {\n const duration = performance.now() - startTime;\n const dbLogger = logger.child('database');\n const message = error instanceof Error ? error.message : 'Unknown error';\n\n dbLogger.error('Query failed', {\n operation,\n table: this.table._.name,\n duration: `${duration.toFixed(2)}ms`,\n error: message,\n });\n\n throw error;\n }\n }\n\n /**\n * Find all records (uses Replica)\n *\n * @example\n * const users = await userRepo.findAll();\n */\n async findAll(): Promise<TSelect[]>\n {\n return this.executeWithMonitoring('findAll', async () =>\n {\n const readDb = this.getReadDb();\n // Type assertion needed: Drizzle's from() expects specific table signature\n return readDb.select().from(this.table as any) as Promise<TSelect[]>;\n });\n }\n\n /**\n * Find with pagination (uses Replica)\n *\n * @example\n * const result = await userRepo.findPage({\n * filters: { email: { like: 'john' } },\n * sort: [{ field: 'createdAt', direction: 'desc' }],\n * pagination: { page: 1, limit: 20 }\n * });\n */\n async findPage(pageable: Pageable): Promise<Page<TSelect>>\n {\n return this.executeWithMonitoring('findPage', async () =>\n {\n const { filters = {}, sort = [], pagination = { page: 1, limit: 20 } } = pageable;\n\n // Type assertions needed: Helper functions expect DrizzleTable type\n const whereCondition = buildFilters(filters, this.table as any);\n const orderBy = buildSort(sort, this.table as any);\n const { offset, limit } = applyPagination(pagination);\n\n // Fetch data from Replica\n const readDb = this.getReadDb();\n const data = await readDb\n .select()\n .from(this.table as any)\n .where(whereCondition)\n .orderBy(...orderBy)\n .limit(limit)\n .offset(offset) as TSelect[];\n\n // Count total (uses Replica)\n const total = await countTotal(readDb, this.table as any, whereCondition);\n const meta = createPaginationMeta(pagination, total);\n\n return { data, meta };\n });\n }\n\n /**\n * Find one record by ID (uses Replica)\n *\n * @example\n * const user = await userRepo.findById(1);\n */\n async findById(id: number | string): Promise<TSelect | null>\n {\n return this.executeWithMonitoring('findById', async () =>\n {\n const idColumn = this.getIdColumn();\n\n const { eq } = await import('drizzle-orm');\n const readDb = this.getReadDb();\n const [result] = await readDb\n .select()\n .from(this.table as any)\n .where(eq(idColumn, id)) as TSelect[];\n\n return result ?? null;\n });\n }\n\n /**\n * Find one record by condition (uses Replica)\n *\n * @example\n * const user = await userRepo.findOne(eq(users.email, 'john@example.com'));\n */\n async findOne(where: SQL<unknown>): Promise<TSelect | null>\n {\n return this.executeWithMonitoring('findOne', async () =>\n {\n const readDb = this.getReadDb();\n const [result] = await readDb\n .select()\n .from(this.table as any)\n .where(where) as TSelect[];\n\n return result ?? null;\n });\n }\n\n /**\n * Create a new record (uses Primary)\n *\n * @example\n * const user = await userRepo.save({ email: 'john@example.com', name: 'John' });\n */\n async save(data: any): Promise<TSelect>\n {\n return this.executeWithMonitoring('save', async () =>\n {\n const writeDb = this.getWriteDb();\n const [result] = await writeDb\n .insert(this.table)\n .values(data)\n .returning() as TSelect[];\n\n return result;\n });\n }\n\n /**\n * Update a record (uses Primary)\n *\n * Automatically injects current timestamp if table has auto-update field configured.\n *\n * @example\n * const user = await userRepo.update(1, { name: 'Jane' });\n */\n async update(id: number | string, data: any): Promise<TSelect | null>\n {\n return this.executeWithMonitoring('update', async () =>\n {\n const idColumn = this.getIdColumn();\n\n // Auto-inject timestamp if configured and not explicitly provided\n const updateData = this.injectAutoUpdateTimestamp(data);\n\n const { eq } = await import('drizzle-orm');\n const writeDb = this.getWriteDb();\n const [result] = await writeDb\n .update(this.table)\n .set(updateData)\n .where(eq(idColumn, id))\n .returning() as TSelect[];\n\n return result ?? null;\n });\n }\n\n /**\n * Delete a record (uses Primary)\n *\n * @example\n * const deleted = await userRepo.delete(1);\n */\n async delete(id: number | string): Promise<TSelect | null>\n {\n return this.executeWithMonitoring('delete', async () =>\n {\n const idColumn = this.getIdColumn();\n\n const { eq } = await import('drizzle-orm');\n const writeDb = this.getWriteDb();\n const [result] = await writeDb\n .delete(this.table)\n .where(eq(idColumn, id))\n .returning() as TSelect[];\n\n return result ?? null;\n });\n }\n\n /**\n * Count records (uses Replica)\n *\n * @example\n * const count = await userRepo.count();\n */\n async count(where?: SQL<unknown>): Promise<number>\n {\n return this.executeWithMonitoring('count', async () =>\n {\n const readDb = this.getReadDb();\n return countTotal(readDb, this.table as any, where);\n });\n }\n\n /**\n * Find records by filters (uses Replica)\n *\n * @example\n * const users = await userRepo.findWhere({ email: { like: '@gmail.com' }, status: 'active' });\n */\n async findWhere(filters: Filters): Promise<TSelect[]>\n {\n return this.executeWithMonitoring('findWhere', async () =>\n {\n const whereCondition = buildFilters(filters, this.table as any);\n const readDb = this.getReadDb();\n return readDb\n .select()\n .from(this.table as any)\n .where(whereCondition) as Promise<TSelect[]>;\n });\n }\n\n /**\n * Find one record by filters (uses Replica)\n *\n * @example\n * const user = await userRepo.findOneWhere({ email: 'john@example.com' });\n */\n async findOneWhere(filters: Filters): Promise<TSelect | null>\n {\n return this.executeWithMonitoring('findOneWhere', async () =>\n {\n const whereCondition = buildFilters(filters, this.table as any);\n const readDb = this.getReadDb();\n const [result] = await readDb\n .select()\n .from(this.table as any)\n .where(whereCondition) as TSelect[];\n\n return result ?? null;\n });\n }\n\n /**\n * Check if record exists by ID (uses Replica)\n *\n * @example\n * const exists = await userRepo.exists(1);\n */\n async exists(id: number | string): Promise<boolean>\n {\n return this.executeWithMonitoring('exists', async () =>\n {\n const idColumn = this.getIdColumn();\n\n const { eq } = await import('drizzle-orm');\n const readDb = this.getReadDb();\n const [result] = await readDb\n .select()\n .from(this.table as any)\n .where(eq(idColumn, id))\n .limit(1) as TSelect[];\n\n return !!result;\n });\n }\n\n /**\n * Check if record exists by filters (uses Replica)\n *\n * @example\n * const exists = await userRepo.existsBy({ email: 'john@example.com' });\n */\n async existsBy(filters: Filters): Promise<boolean>\n {\n return this.executeWithMonitoring('existsBy', async () =>\n {\n const whereCondition = buildFilters(filters, this.table as any);\n const readDb = this.getReadDb();\n const [result] = await readDb\n .select()\n .from(this.table as any)\n .where(whereCondition)\n .limit(1) as TSelect[];\n\n return !!result;\n });\n }\n\n /**\n * Count records by filters (uses Replica)\n *\n * @example\n * const count = await userRepo.countBy({ status: 'active' });\n */\n async countBy(filters: Filters): Promise<number>\n {\n return this.executeWithMonitoring('countBy', async () =>\n {\n const whereCondition = buildFilters(filters, this.table as any);\n const readDb = this.getReadDb();\n return countTotal(readDb, this.table as any, whereCondition);\n });\n }\n\n /**\n * Create multiple records (uses Primary)\n *\n * @example\n * const users = await userRepo.saveMany([\n * { email: 'user1@example.com', name: 'User 1' },\n * { email: 'user2@example.com', name: 'User 2' }\n * ]);\n */\n async saveMany(data: any[]): Promise<TSelect[]>\n {\n return this.executeWithMonitoring('saveMany', async () =>\n {\n const writeDb = this.getWriteDb();\n return writeDb\n .insert(this.table)\n .values(data)\n .returning() as Promise<TSelect[]>;\n });\n }\n\n /**\n * Update multiple records by filters (uses Primary)\n *\n * Automatically injects current timestamp if table has auto-update field configured.\n *\n * @example\n * const count = await userRepo.updateWhere({ status: 'inactive' }, { status: 'archived' });\n */\n async updateWhere(filters: Filters, data: any): Promise<number>\n {\n return this.executeWithMonitoring('updateWhere', async () =>\n {\n // Auto-inject timestamp if configured and not explicitly provided\n const updateData = this.injectAutoUpdateTimestamp(data);\n\n const whereCondition = buildFilters(filters, this.table as any);\n const writeDb = this.getWriteDb();\n const results = await writeDb\n .update(this.table)\n .set(updateData)\n .where(whereCondition)\n .returning() as TSelect[];\n\n return results.length;\n });\n }\n\n /**\n * Delete multiple records by filters (uses Primary)\n *\n * @example\n * const count = await userRepo.deleteWhere({ status: 'banned' });\n */\n async deleteWhere(filters: Filters): Promise<number>\n {\n return this.executeWithMonitoring('deleteWhere', async () =>\n {\n const whereCondition = buildFilters(filters, this.table as any);\n const writeDb = this.getWriteDb();\n const results = await writeDb\n .delete(this.table)\n .where(whereCondition)\n .returning() as TSelect[];\n\n return results.length;\n });\n }\n\n // ============================================================\n // Query Builder (Fluent Interface)\n // ============================================================\n\n /**\n * Start a chainable query builder (uses Replica)\n *\n * Returns a QueryBuilder instance for building complex queries with method chaining.\n *\n * @returns QueryBuilder instance for chaining\n *\n * @example\n * ```typescript\n * // Simple chaining\n * const users = await userRepo\n * .query()\n * .where({ status: 'active' })\n * .orderBy('createdAt', 'desc')\n * .limit(10)\n * .findMany();\n *\n * // Multiple conditions\n * const admins = await userRepo\n * .query()\n * .where({ role: 'admin' })\n * .where({ status: 'active' }) // AND condition\n * .findMany();\n *\n * // Reusable query\n * const activeQuery = userRepo.query().where({ status: 'active' });\n * const users = await activeQuery.findMany();\n * const count = await activeQuery.count();\n * ```\n */\n query(): QueryBuilder<TTable, TSelect>\n {\n const readDb = this.getReadDb();\n return new QueryBuilder<TTable, TSelect>(readDb, this.table);\n }\n}","/**\n * Repository Factory\n *\n * Provides singleton instances of Repository classes to prevent unnecessary instantiation\n * and ensure consistent instances across the application.\n *\n * ✅ Features:\n * - Singleton pattern for both base and custom Repository classes\n * - Automatic caching based on table + constructor\n * - Type-safe with full IDE autocomplete\n * - Supports multiple services accessing the same repository\n * - Memory efficient (single instance per table/class combination)\n *\n * @example\n * ```typescript\n * // Base Repository\n * const userRepo = getRepository(users);\n * await userRepo.findById(1);\n *\n * // Custom Repository\n * class UserRepository extends Repository<typeof users> {\n * async findByEmail(email: string) {\n * return this.findOneWhere({ email });\n * }\n * }\n *\n * const userRepo = getRepository(users, UserRepository);\n * await userRepo.findByEmail('john@example.com');\n * ```\n */\n\nimport { Repository } from './repository.js';\nimport type { PgTable } from 'drizzle-orm/pg-core';\n\n/**\n * Repository instance cache\n * Key format: \"tableName:ClassName\"\n */\nconst repositoryCache = new Map<string, Repository<any>>();\n\n/**\n * Generate cache key from table and constructor\n *\n * @param table - Drizzle table definition\n * @param RepositoryClass - Optional custom Repository class\n * @returns Cache key string\n */\nfunction getCacheKey<TTable extends PgTable>(\n table: TTable,\n RepositoryClass?: new (table: TTable) => Repository<TTable>\n): string\n{\n // Get table name from Drizzle's internal symbol or fallback\n const tableName = (table as any)[Symbol.for('drizzle:Name')]\n || (table as any).name\n || table.toString();\n\n const className = RepositoryClass?.name || 'Repository';\n\n return `${tableName}:${className}`;\n}\n\n/**\n * Get or create a Repository singleton instance (Global Singleton Pattern)\n *\n * This function ensures that only one instance of each Repository is created,\n * preventing memory waste and ensuring consistency across the application.\n *\n * ✅ Supports both base Repository and custom Repository classes\n * ✅ Returns the same instance on subsequent calls\n * ✅ Type-safe with full IDE autocomplete\n * ✅ Automatically detects transaction context (via Repository internals)\n *\n * ## ⚠️ Note: Global Singleton Pattern\n *\n * This uses a **global singleton cache** that persists throughout application lifecycle.\n *\n * **Tradeoffs:**\n * - ✅ Simple API, no middleware required\n * - ✅ Maximum memory efficiency\n * - ⚠️ Requires manual `clearRepositoryCache()` in tests\n * - ⚠️ Global state (harder to isolate in testing)\n *\n * **For better test isolation**, consider using **request-scoped repositories**:\n * ```typescript\n * import { getScopedRepository, RepositoryScope } from '@spfn/core/db';\n *\n * // Add middleware (once)\n * app.use(RepositoryScope());\n *\n * // Use getScopedRepository() instead - automatic per-request caching\n * const repo = getScopedRepository(users);\n * ```\n *\n * See: `request-scope.ts` for request-scoped alternative\n *\n * ## 🔄 Transaction Handling\n *\n * Repository instances are cached globally, but they automatically detect\n * and use transaction context via AsyncLocalStorage in each method call.\n * This means:\n * - **Same repository instance** can be used both inside and outside transactions\n * - **No need to create separate repository instances** per transaction\n * - **Transaction safety is guaranteed** by AsyncLocalStorage context\n *\n * The Repository internally calls `getTransaction()` on every database operation,\n * ensuring the correct DB instance (transaction or default) is always used.\n *\n * @param table - Drizzle table definition\n * @param RepositoryClass - Optional custom Repository class extending Repository\n * @returns Repository instance (cached singleton)\n *\n * @example\n * ```typescript\n * // Base Repository - simple CRUD\n * import { getRepository } from '@spfn/core/db';\n * import { users } from './entities';\n *\n * export async function getUser(id: number) {\n * const repo = getRepository(users);\n * return repo.findById(id);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Custom Repository - with custom methods\n * import { Repository, getRepository } from '@spfn/core/db';\n * import { users } from './entities';\n *\n * class UserRepository extends Repository<typeof users> {\n * async findByEmail(email: string) {\n * return this.findOneWhere({ email });\n * }\n *\n * async findActiveUsers() {\n * return this.findWhere({ status: 'active' });\n * }\n * }\n *\n * export async function getUserByEmail(email: string) {\n * const repo = getRepository(users, UserRepository);\n * return repo.findByEmail(email);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Multiple services - same instance\n * // services/users.ts\n * const repo = getRepository(users, UserRepository); // Instance A\n *\n * // services/auth.ts\n * const repo = getRepository(users, UserRepository); // Same Instance A\n * ```\n *\n * @example\n * ```typescript\n * // Transaction handling - same instance works everywhere\n * import { getRepository, Transactional } from '@spfn/core/db';\n * import { users } from './entities';\n *\n * const userRepo = getRepository(users);\n *\n * // Outside transaction - uses default DB\n * await userRepo.findById(1);\n *\n * // Inside Transactional() middleware - uses transaction automatically\n * app.use(Transactional());\n * app.post('/', async (c) => {\n * // Same instance, but now uses transaction DB\n * await userRepo.save({ email: 'test@example.com' });\n * return c.json({ success: true });\n * });\n * ```\n */\nexport function getRepository<\n TTable extends PgTable,\n TRepo extends Repository<TTable> = Repository<TTable>\n>(\n table: TTable,\n RepositoryClass?: new (table: TTable) => TRepo\n): TRepo\n{\n const cacheKey = getCacheKey(table, RepositoryClass as any);\n\n // Check cache\n let repo = repositoryCache.get(cacheKey);\n\n if (!repo)\n {\n // Create new instance\n if (RepositoryClass)\n {\n repo = new RepositoryClass(table);\n }\n else\n {\n repo = new Repository(table);\n }\n\n // Cache it\n repositoryCache.set(cacheKey, repo);\n }\n\n return repo as TRepo;\n}\n\n/**\n * Clear repository cache\n *\n * Removes all cached repository instances. Useful for testing scenarios\n * where you need fresh instances.\n *\n * ⚠️ Warning: Only use this in tests. In production, cached instances\n * should persist throughout the application lifecycle.\n *\n * @example\n * ```typescript\n * import { clearRepositoryCache } from '@spfn/core/db';\n *\n * beforeEach(() => {\n * clearRepositoryCache(); // Fresh instances for each test\n * });\n * ```\n */\nexport function clearRepositoryCache(): void\n{\n repositoryCache.clear();\n}\n\n/**\n * Get cache size (for debugging/monitoring)\n *\n * @returns Number of cached repository instances\n *\n * @example\n * ```typescript\n * const size = getRepositoryCacheSize();\n * console.log(`Cached repositories: ${size}`);\n * ```\n */\nexport function getRepositoryCacheSize(): number\n{\n return repositoryCache.size;\n}","/**\n * Request-Scoped Repository Pattern\n *\n * Provides request-level repository caching using AsyncLocalStorage.\n *\n * ## Benefits:\n * - ✅ **Automatic isolation**: Each request gets its own repository cache\n * - ✅ **Memory efficient**: Cache cleared automatically after request ends\n * - ✅ **Test-friendly**: No global state, tests are fully isolated\n * - ✅ **DI-compatible**: Can inject custom repositories easily\n * - ✅ **Zero overhead**: Uses existing AsyncLocalStorage infrastructure\n *\n * ## vs Global Singleton:\n *\n * | Feature | Global Singleton | Request-Scoped |\n * |---------|-----------------|----------------|\n * | Memory | Permanent cache | Request-only cache |\n * | Test isolation | Manual clearRepositoryCache() | Automatic |\n * | Thread-safety | Shared state | Isolated per request |\n * | DI support | Difficult | Easy |\n *\n * @example\n * ```typescript\n * // 1. Add middleware (routes automatically)\n * import { RepositoryScope } from '@spfn/core/db';\n *\n * app.use(RepositoryScope());\n *\n * // 2. Use in service (same request = same instance)\n * import { getScopedRepository } from '@spfn/core/db';\n *\n * export async function createPost(data) {\n * const repo = getScopedRepository(posts, PostRepository); // First call - creates\n * const existing = await repo.findBySlug(slug);\n * return repo.save(data); // Same instance\n * }\n *\n * // 3. Different request = different cache (automatic)\n * ```\n */\n\nimport { AsyncLocalStorage } from 'async_hooks';\nimport { Repository } from './repository.js';\nimport type { PgTable } from 'drizzle-orm/pg-core';\nimport type { MiddlewareHandler } from 'hono';\n\n/**\n * AsyncLocalStorage for request-scoped repository cache\n * Each request gets its own Map instance\n */\nconst repositoryStorage = new AsyncLocalStorage<Map<string, Repository<any>>>();\n\n/**\n * Generate cache key from table and repository class\n * Same logic as global singleton for consistency\n */\nfunction getCacheKey<TTable extends PgTable>(\n table: TTable,\n RepositoryClass?: new (table: TTable) => Repository<TTable>\n): string\n{\n const tableName = (table as any)[Symbol.for('drizzle:Name')]\n || (table as any).name\n || table.toString();\n\n const className = RepositoryClass?.name || 'Repository';\n\n return `${tableName}:${className}`;\n}\n\n/**\n * Execute function within a repository scope\n *\n * Creates a new request-scoped cache for the duration of the function.\n * Automatically cleaned up after function completes.\n *\n * @param fn - Async function to execute within scope\n * @returns Result of the function\n *\n * @example\n * ```typescript\n * // Middleware\n * app.use(async (c, next) => {\n * return withRepositoryScope(() => next());\n * });\n *\n * // Manual usage\n * const result = await withRepositoryScope(async () => {\n * const repo = getScopedRepository(users);\n * return repo.findAll();\n * });\n * ```\n */\nexport function withRepositoryScope<T>(fn: () => Promise<T>): Promise<T>\n{\n const cache = new Map<string, Repository<any>>();\n return repositoryStorage.run(cache, fn);\n}\n\n/**\n * Get request-scoped repository instance\n *\n * Returns cached instance within the same request, creates new instance for new requests.\n * Falls back to creating a new instance if called outside of a repository scope.\n *\n * ## Behavior:\n * - **Inside scope**: Returns cached instance (same request = same instance)\n * - **Outside scope**: Creates new instance every time (graceful degradation)\n *\n * @param table - Drizzle table definition\n * @param RepositoryClass - Optional custom Repository class\n * @returns Repository instance (cached or new)\n *\n * @example\n * ```typescript\n * // Base Repository\n * const repo = getScopedRepository(users);\n * await repo.findById(1);\n *\n * // Custom Repository\n * class UserRepository extends Repository<typeof users> {\n * async findByEmail(email: string) {\n * return this.findOneWhere({ email });\n * }\n * }\n *\n * const repo = getScopedRepository(users, UserRepository);\n * await repo.findByEmail('john@example.com');\n *\n * // Within same request - returns cached instance\n * const repo2 = getScopedRepository(users, UserRepository); // Same instance!\n * ```\n */\nexport function getScopedRepository<\n TTable extends PgTable,\n TRepo extends Repository<TTable> = Repository<TTable>\n>(\n table: TTable,\n RepositoryClass?: new (table: TTable) => TRepo\n): TRepo\n{\n const cache = repositoryStorage.getStore();\n\n // Outside scope - create new instance (graceful degradation)\n if (!cache)\n {\n return RepositoryClass\n ? new RepositoryClass(table)\n : new Repository(table) as TRepo;\n }\n\n // Inside scope - use cache\n const key = getCacheKey(table, RepositoryClass as any);\n let repo = cache.get(key);\n\n if (!repo)\n {\n repo = RepositoryClass\n ? new RepositoryClass(table)\n : new Repository(table);\n cache.set(key, repo);\n }\n\n return repo as TRepo;\n}\n\n/**\n * Hono middleware for automatic repository scope management\n *\n * Wraps each request in a repository scope, ensuring automatic cache isolation.\n * All repositories accessed via getScopedRepository() within this request will be cached.\n *\n * @returns Hono middleware handler\n *\n * @example\n * ```typescript\n * // Global middleware (recommended)\n * import { createServer } from '@spfn/core';\n * import { RepositoryScope } from '@spfn/core/db';\n *\n * const app = createServer();\n * app.use(RepositoryScope());\n *\n * // Or in server.config.ts\n * export default {\n * middlewares: [\n * { name: 'repositoryScope', handler: RepositoryScope() }\n * ]\n * };\n * ```\n */\nexport function RepositoryScope(): MiddlewareHandler\n{\n return async (_c, next) =>\n {\n return withRepositoryScope(() => next());\n };\n}\n\n/**\n * Get current repository cache size (for debugging/monitoring)\n *\n * Returns the number of cached repository instances in the current request scope.\n * Returns 0 if called outside a scope.\n *\n * @returns Number of cached repositories in current scope\n *\n * @example\n * ```typescript\n * const size = getScopedCacheSize();\n * console.log(`Cached repositories in this request: ${size}`);\n * ```\n */\nexport function getScopedCacheSize(): number\n{\n const cache = repositoryStorage.getStore();\n return cache?.size ?? 0;\n}\n\n/**\n * Check if currently inside a repository scope\n *\n * @returns true if inside scope, false otherwise\n *\n * @example\n * ```typescript\n * if (isInRepositoryScope()) {\n * console.log('Using scoped cache');\n * } else {\n * console.log('Creating new instances');\n * }\n * ```\n */\nexport function isInRepositoryScope(): boolean\n{\n return repositoryStorage.getStore() !== undefined;\n}","/**\n * Table Name Utilities\n *\n * Helper functions for extracting table names from Drizzle table objects.\n * Used by Repository for accessing db.query API with dynamic table names.\n */\n\nimport type { PgTable } from 'drizzle-orm/pg-core';\n\n/**\n * Table name cache for performance optimization\n * Prevents repeated Symbol.for lookups\n */\nconst tableNameCache = new WeakMap<PgTable, string>();\n\n/**\n * Get table name from Drizzle table object\n *\n * Uses WeakMap cache to avoid repeated Symbol lookups for better performance.\n *\n * @param table - Drizzle table schema\n * @returns Table name string\n *\n * @example\n * ```typescript\n * import { users } from './schema';\n * const name = getTableName(users); // 'users'\n * ```\n */\nexport function getTableName(table: PgTable): string\n{\n // Check cache first\n const cached = tableNameCache.get(table);\n if (cached)\n {\n return cached;\n }\n\n // Extract name from Drizzle table metadata\n // Drizzle stores table name in Symbol.for('drizzle:Name')\n const name = (table as any)[Symbol.for('drizzle:Name')] || table.constructor.name;\n\n // Cache for future lookups\n tableNameCache.set(table, name);\n\n return name;\n}","/**\n * Repository Module Exports\n */\n\n// Repository Pattern\nexport { Repository } from './repository.js';\nexport type {\n Pageable,\n Page,\n} from './repository.js';\n\n// Repository Factory (Singleton Pattern)\nexport {\n getRepository,\n clearRepositoryCache,\n getRepositoryCacheSize\n} from './factory.js';\n\n// Request-Scoped Repository (Recommended for testability)\nexport {\n getScopedRepository,\n withRepositoryScope,\n RepositoryScope,\n getScopedCacheSize,\n isInRepositoryScope\n} from './request-scope.js';\n\n// Query Builder\nexport { QueryBuilder } from './query-builder.js';\n\n// Relation Registry\nexport { getTableName } from './relation-registry.js';\n\n// Filter Utilities (formerly from query module)\nexport {\n buildFilters,\n buildSort,\n orFilters,\n applyPagination,\n createPaginationMeta,\n countTotal,\n} from './filters.js';\n\nexport type {\n FilterOperator,\n FilterValue,\n FilterCondition,\n Filters,\n FilterResult,\n SortDirection,\n SortCondition,\n SortResult,\n PaginationParams,\n PaginationMeta,\n DrizzleTable,\n} from './filters.js';","/**\n * WrappedDb - Drizzle + Repository 패턴 통합\n *\n * Drizzle의 모든 기능을 유지하면서 JPA 스타일 Repository 접근 제공\n */\n\nimport type { PgTable } from 'drizzle-orm/pg-core';\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';\n\nimport { Repository } from '../repository';\n\n/**\n * WrappedDb 클래스\n *\n * Drizzle DB를 래핑하여 추가 기능 제공\n */\nexport class WrappedDb\n{\n constructor(private db: PostgresJsDatabase<Record<string, never>>) {}\n\n /**\n * Repository 패턴으로 테이블 접근\n *\n * @example\n * const db = getDb();\n * const userRepo = db.for(users);\n * const result = await userRepo.findPage(pageable);\n */\n for<TTable extends PgTable<any>, TSelect = any>(table: TTable): Repository<TTable, TSelect>\n {\n return new Repository<TTable, TSelect>(this.db, table);\n }\n\n /**\n * Drizzle의 모든 메서드를 프록시\n *\n * select, insert, update, delete, transaction 등 모든 Drizzle 메서드 사용 가능\n */\n get select()\n {\n return this.db.select.bind(this.db);\n }\n\n get insert()\n {\n return this.db.insert.bind(this.db);\n }\n\n get update()\n {\n return this.db.update.bind(this.db);\n }\n\n get delete()\n {\n return this.db.delete.bind(this.db);\n }\n\n get execute()\n {\n return this.db.execute.bind(this.db);\n }\n\n get transaction()\n {\n return this.db.transaction.bind(this.db);\n }\n\n get query()\n {\n return this.db.query;\n }\n\n get $with()\n {\n return this.db.$with.bind(this.db);\n }\n\n /**\n * Raw Drizzle DB 접근 (필요시)\n */\n get raw(): PostgresJsDatabase\n {\n return this.db;\n }\n}\n","/**\n * DB Context Helper\n *\n * Automatically detects transaction context and returns the appropriate DB instance.\n *\n * ✅ Implemented:\n * - AsyncLocalStorage-based transaction detection\n * - Returns default DB instance when no transaction\n * - JPA-style Repository pattern support\n * - Preserves Drizzle core features\n *\n * ⚠️ TODO:\n * - Nested transaction detection and warning logs\n * - Transaction timeout checks\n *\n * 💡 Future considerations:\n * - Add function to force default DB usage (useDefaultDb)\n * - Auto-select Read Replica (detect read-only queries)\n * - Transaction statistics collection (success/failure/rollback count)\n * - Return transaction ID function (for debugging)\n *\n * 🔗 Related files:\n * - src/utils/async-context.ts (AsyncLocalStorage implementation)\n * - src/utils/transaction.ts (Transactional middleware)\n * - src/db/db-instance.ts (Default DB instance)\n * - src/db/wrapped-db.ts (WrappedDb implementation)\n * - src/db/repository.ts (Repository implementation)\n */\nimport { getTransaction } from '../transaction';\n\nimport { getDatabase, type DbConnectionType } from './manager.js';\nimport { WrappedDb } from './wrapped-db.js';\n\n/**\n * Get DB instance (WrappedDb)\n *\n * - If transaction context exists: Returns transaction DB\n * - Otherwise: Returns default DB or specified connection type\n * - Wraps with WrappedDb to provide both Repository pattern + Drizzle features\n *\n * Usage 1: Direct Drizzle use\n * ```typescript\n * export async function GET(c: RouteContext) {\n * const db = getDb();\n * const users = await db.select().from(users);\n * return c.json(users);\n * }\n * ```\n *\n * Usage 2: Repository pattern\n * ```typescript\n * export async function GET(c: RouteContext) {\n * const db = getDb();\n * const userRepo = db.for(users);\n * const result = await userRepo.findPage(pageable);\n * return c.json(result);\n * }\n * ```\n *\n * Usage 3: Specify connection type\n * ```typescript\n * const readDb = getDb('read'); // Use read replica\n * const writeDb = getDb('write'); // Use primary\n * ```\n *\n * @param type - Optional connection type ('read' or 'write')\n * @returns WrappedDb instance (transaction or specified DB)\n */\nexport function getDb(type?: DbConnectionType): WrappedDb\n{\n const tx = getTransaction();\n\n // If transaction exists, always use transaction DB\n if (tx)\n {\n return new WrappedDb(tx);\n }\n\n // Otherwise use specified type or default from manager\n const rawDb = getDatabase(type);\n if (!rawDb)\n {\n throw new Error(\n 'Database not initialized. ' +\n 'Set DATABASE_URL environment variable or call initDatabase() first.'\n );\n }\n\n return new WrappedDb(rawDb);\n}","/**\n * Database Manager Module Exports\n */\n\n// DB Instance & Connection (Backward Compatibility)\nexport { db, getRawDb } from './instance.js';\nexport type { DbConnectionType } from './instance.js';\n\n// DB Context\nexport { getDb } from './context.js';\n\n// Database Factory (Environment Detection)\nexport { createDatabaseFromEnv } from './factory.js';\nexport type { DatabaseClients } from './factory.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\n// Wrapped DB\nexport { WrappedDb } from './wrapped-db.js';","/**\n * Drizzle Kit configuration generator\n * Automatically generates drizzle.config.ts from environment variables\n */\n\nexport interface DrizzleConfigOptions\n{\n /** Database connection URL (defaults to process.env.DATABASE_URL) */\n databaseUrl?: string;\n\n /** Schema files glob pattern (defaults to './src/server/entities/*.ts') */\n schema?: string;\n\n /** Migration output directory (defaults to './drizzle/migrations') */\n out?: string;\n\n /** Database dialect (auto-detected from URL if not provided) */\n dialect?: 'postgresql' | 'mysql' | 'sqlite';\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 schema = options.schema ?? './src/server/entities/*.ts';\n const out = options.out ?? './drizzle/migrations';\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 return `import { defineConfig } from 'drizzle-kit';\n\nexport default defineConfig({\n schema: '${config.schema}',\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 } 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 * Schema Module Exports\n */\n\n// Schema Helpers\nexport { id, timestamps, foreignKey, optionalForeignKey } from './helpers.js';","/**\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 db,\n getRawDb,\n getDb,\n createDatabaseFromEnv,\n initDatabase,\n getDatabase,\n setDatabase,\n closeDatabase,\n getDatabaseInfo,\n createDatabaseConnection,\n checkConnection,\n WrappedDb,\n} from './manager';\n\nexport type {\n DbConnectionType,\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// Repository Pattern\nexport {\n Repository,\n getRepository,\n clearRepositoryCache,\n getRepositoryCacheSize,\n getScopedRepository,\n withRepositoryScope,\n RepositoryScope,\n getScopedCacheSize,\n isInRepositoryScope,\n QueryBuilder,\n getTableName,\n} from './repository';\n\nexport type {\n Pageable,\n Page,\n} from './repository';\n\n// Schema Helpers\nexport { id, timestamps, foreignKey, optionalForeignKey } from './schema';\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';","import { readdir, stat } from 'fs/promises';\nimport { join, relative } from 'path';\nimport type { Hono } from 'hono';\n\n/**\n * Extend Hono Context to support skipMiddlewares metadata\n */\ndeclare module 'hono' {\n interface ContextVariableMap {\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 * ## Usage\n * ```typescript\n * const app = new Hono();\n * await loadRoutes(app);\n * ```\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type RouteInfo = {\n /** URL path (e.g., /users/:id) */\n path: string;\n /** File path relative to routes dir */\n file: string;\n /** Route metadata from export */\n meta?: {\n description?: string;\n tags?: string[];\n auth?: boolean;\n [key: string]: unknown;\n };\n /** Priority (1=static, 2=dynamic, 3=catch-all) */\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\n// ============================================================================\n// Main Loader Class\n// ============================================================================\n\nexport class AutoRouteLoader\n{\n private routes: RouteInfo[] = [];\n private registeredRoutes = new Map<string, string>(); // normalized path → file\n private debug: boolean;\n private readonly middlewares: Array<{ name: string; handler: any }>;\n\n constructor(\n private routesDir: string,\n debug = false,\n middlewares: Array<{ name: string; handler: any }> = []\n )\n {\n this.debug = debug;\n this.middlewares = middlewares;\n }\n\n /**\n * Load all routes from directory\n */\n async load(app: Hono): Promise<RouteStats>\n {\n const startTime = Date.now();\n\n // 1. Scan files\n const files = await this.scanFiles(this.routesDir);\n\n if (files.length === 0)\n {\n console.warn('⚠️ No route files found');\n return this.getStats();\n }\n\n // 2. Calculate priorities for all files\n const filesWithPriority = files.map(file => ({\n path: file,\n priority: this.calculatePriority(relative(this.routesDir, file)),\n }));\n\n // 3. Sort by priority (static=1, dynamic=2, catch-all=3)\n filesWithPriority.sort((a, b) => a.priority - b.priority);\n\n if (this.debug)\n {\n console.log(`\\n📋 Route Registration Order:`);\n console.log(` Priority 1 (Static): ${filesWithPriority.filter(f => f.priority === 1).length} routes`);\n console.log(` Priority 2 (Dynamic): ${filesWithPriority.filter(f => f.priority === 2).length} routes`);\n console.log(` Priority 3 (Catch-all): ${filesWithPriority.filter(f => f.priority === 3).length} routes\\n`);\n }\n\n // 4. Load and register routes in priority order\n let successCount = 0;\n let failureCount = 0;\n\n for (const { path } of filesWithPriority)\n {\n const success = await this.loadRoute(app, path);\n if (success)\n {\n successCount++;\n }\n else\n {\n failureCount++;\n }\n }\n\n // 5. Log stats\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 console.warn(`⚠️ ${failureCount} route(s) failed to load`);\n }\n\n return stats;\n }\n\n /**\n * Get route statistics\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 // Count by priority\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 // Count by tag\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 // ========================================================================\n // Private Methods\n // ========================================================================\n\n /**\n * Recursively scan directory for .ts files\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 // Recurse into subdirectories\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 /**\n * Check if file is a valid route file\n */\n private isValidRouteFile(fileName: string): boolean\n {\n return (\n fileName.endsWith('.ts') &&\n !fileName.endsWith('.test.ts') &&\n !fileName.endsWith('.spec.ts') &&\n !fileName.endsWith('.d.ts') &&\n fileName !== 'contract.ts'\n );\n }\n\n /**\n * Load and register a single route\n * Returns true if successful, false if failed\n */\n private async loadRoute(app: Hono, absolutePath: string): Promise<boolean>\n {\n const relativePath = relative(this.routesDir, absolutePath);\n\n try\n {\n // Import module\n const module = await import(absolutePath);\n\n if (!module.default)\n {\n console.error(`❌ ${relativePath}: Must export Hono instance as default`);\n return false;\n }\n\n // Validate that it's actually a Hono instance\n if (typeof module.default.route !== 'function')\n {\n console.error(`❌ ${relativePath}: Default export is not a Hono instance`);\n return false;\n }\n\n // Convert file path to URL path\n const urlPath = this.fileToPath(relativePath);\n const priority = this.calculatePriority(relativePath);\n\n // Check for route conflicts\n const normalizedPath = this.normalizePath(urlPath);\n const existingFile = this.registeredRoutes.get(normalizedPath);\n\n if (existingFile)\n {\n console.warn(`⚠️ Route conflict detected:`);\n console.warn(` Path: ${urlPath} (normalized: ${normalizedPath})`);\n console.warn(` Already registered by: ${existingFile}`);\n console.warn(` Attempted by: ${relativePath}`);\n console.warn(` → Skipping duplicate registration`);\n return false;\n }\n\n // Track registration\n this.registeredRoutes.set(normalizedPath, relativePath);\n\n // Check if module uses contract-based routing (createApp)\n const hasContractMetas = module.default._contractMetas && module.default._contractMetas.size > 0;\n\n if (hasContractMetas)\n {\n // Contract-based routing: method-level skipMiddlewares\n // Use wildcard pattern to match all sub-paths (e.g., /test/* matches /test/public, /test/private)\n const middlewarePath = urlPath === '/' ? '/*' : `${urlPath}/*`;\n\n // 1. Register meta-setting middleware first\n app.use(middlewarePath, (c, next) =>\n {\n const method = c.req.method;\n const requestPath = new URL(c.req.url).pathname;\n\n // Calculate relative path by removing the route base path\n // E.g., if urlPath = '/test' and requestPath = '/test/public', then relativePath = '/public'\n const relativePath = requestPath.startsWith(urlPath)\n ? requestPath.slice(urlPath.length) || '/'\n : requestPath;\n\n const key = `${method} ${relativePath}`;\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 // 2. Wrap global middlewares to check skipMiddlewares\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(); // Skip this middleware\n }\n\n return middleware.handler(c, next); // Execute middleware\n });\n }\n }\n else\n {\n // File-based routing: file-level skipMiddlewares (fallback)\n const skipList = module.meta?.skipMiddlewares || [];\n const activeMiddlewares = this.middlewares\n .filter(m => !skipList.includes(m.name));\n\n for (const middleware of activeMiddlewares)\n {\n app.use(urlPath, middleware.handler);\n }\n }\n\n // Register route\n app.route(urlPath, module.default);\n\n // Store route info\n this.routes.push({\n path: urlPath,\n file: relativePath,\n meta: module.meta,\n priority,\n });\n\n if (this.debug)\n {\n const icon = priority === 1 ? '🔹' : priority === 2 ? '🔸' : '⭐';\n console.log(` ${icon} ${urlPath.padEnd(40)} → ${relativePath}`);\n }\n\n return true;\n }\n catch (error)\n {\n const err = error as Error;\n\n // Categorize error types and provide helpful messages\n if (err.message.includes('Cannot find module') || err.message.includes('MODULE_NOT_FOUND'))\n {\n console.error(`❌ ${relativePath}: Missing dependency`);\n console.error(` ${err.message}`);\n console.error(` → Run: npm install`);\n }\n else if (err.message.includes('SyntaxError') || err.stack?.includes('SyntaxError'))\n {\n console.error(`❌ ${relativePath}: Syntax error`);\n console.error(` ${err.message}`);\n\n if (this.debug && err.stack)\n {\n console.error(` Stack trace (first 5 lines):`);\n const stackLines = err.stack.split('\\n').slice(0, 5);\n stackLines.forEach(line => console.error(` ${line}`));\n }\n }\n else if (err.message.includes('Unexpected token'))\n {\n console.error(`❌ ${relativePath}: Parse error`);\n console.error(` ${err.message}`);\n console.error(` → Check for syntax errors or invalid TypeScript`);\n }\n else\n {\n console.error(`❌ ${relativePath}: ${err.message}`);\n\n if (this.debug && err.stack)\n {\n console.error(` Stack: ${err.stack}`);\n }\n }\n\n return false;\n }\n }\n\n /**\n * Convert file path to URL path\n *\n * Examples:\n * - users/index.ts → /users\n * - users/[id].ts → /users/:id\n * - posts/[...slug].ts → /posts/*\n */\n private fileToPath(filePath: string): string\n {\n // Remove .ts extension\n let path = filePath.replace(/\\.ts$/, '');\n\n // Split into segments\n const segments = path.split('/');\n\n // Remove 'index' if it's the last segment\n if (segments[segments.length - 1] === 'index')\n {\n segments.pop();\n }\n\n // Transform segments: [id] → :id, [...slug] → *\n const transformed = segments.map(seg =>\n {\n // Catch-all: [...slug] → *\n if (/^\\[\\.\\.\\.[\\w-]+]$/.test(seg))\n {\n return '*';\n }\n // Dynamic: [id] → :id\n if (/^\\[[\\w-]+]$/.test(seg))\n {\n return ':' + seg.slice(1, -1);\n }\n // Skip 'index' segments (index/index.ts → /, posts/index/index.ts → /posts)\n if (seg === 'index')\n {\n return null;\n }\n // Static: users → users\n return seg;\n }).filter(seg => seg !== null);\n\n // Join and ensure leading slash\n const result = '/' + transformed.join('/');\n return result.replace(/\\/+/g, '/').replace(/\\/$/, '') || '/';\n }\n\n /**\n * Calculate route priority\n * 1 = static, 2 = dynamic, 3 = catch-all\n */\n private calculatePriority(path: string): number\n {\n if (/\\[\\.\\.\\.[\\w-]+]/.test(path)) return 3; // Catch-all\n if (/\\[[\\w-]+]/.test(path)) return 2; // Dynamic\n return 1; // Static\n }\n\n /**\n * Normalize path for conflict detection\n *\n * Converts dynamic parameter names to generic placeholders:\n * - /users/:id → /users/:param\n * - /users/:userId → /users/:param (conflict!)\n * - /posts/* → /posts/* (unchanged)\n *\n * This allows detection of routes with different param names\n * that would match the same URL patterns.\n */\n private normalizePath(path: string): string\n {\n // Replace all dynamic params (:xxx) with :param\n // This allows us to detect conflicts like /users/:id and /users/:userId\n return path.replace(/:\\w+/g, ':param');\n }\n\n /**\n * Log statistics\n */\n private logStats(stats: RouteStats, elapsed: number): void\n {\n console.log(`\\n📊 Route Statistics:`);\n console.log(` Total: ${stats.total} routes`);\n console.log(\n ` Priority: ${stats.byPriority.static} static, ` +\n `${stats.byPriority.dynamic} dynamic, ` +\n `${stats.byPriority.catchAll} catch-all`\n );\n\n if (Object.keys(stats.byTag).length > 0)\n {\n const tagCounts = Object.entries(stats.byTag)\n .map(([tag, count]) => `${tag}(${count})`)\n .join(', ');\n console.log(` Tags: ${tagCounts}`);\n }\n\n console.log(`\\n✅ Routes loaded in ${elapsed}ms\\n`);\n }\n}\n\n// ============================================================================\n// Convenience Function\n// ============================================================================\n\n/**\n * Load routes from default location (src/server/routes)\n */\nexport async function loadRoutes(\n app: Hono,\n options?: {\n routesDir?: string;\n debug?: boolean;\n middlewares?: Array<{ name: string; handler: any }>;\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\n const loader = new AutoRouteLoader(routesDir, debug, middlewares);\n return loader.load(app);\n}","import type { Context } from 'hono';\nimport { Value } from '@sinclair/typebox/value';\nimport type { RouteContract, RouteContext, InferContract } from './types.js';\nimport { ValidationError } from '../errors/database-errors.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 *\n * ## Usage\n *\n * ```typescript\n * // Basic usage\n * export const GET = bind(contract, async (c) => {\n * return c.json({ data: 'public' });\n * });\n *\n * // For middleware, use Hono's app-level or route-level middleware:\n * // app.use('/api/*', authMiddleware);\n * // app.get('/users/:id', authMiddleware, bind(contract, handler));\n * ```\n *\n * @param contract - Route contract defining params, query, body, response schemas\n * @param handler - Route handler function\n * @returns Hono-compatible handler function\n */\nexport function bind<TContract extends RouteContract>(\n contract: TContract,\n handler: (c: RouteContext<TContract>) => Response | Promise<Response>\n)\n{\n return async (rawContext: Context) =>\n {\n // ============================================================\n // 1. Validate params\n // ============================================================\n const params = rawContext.req.param();\n if (contract.params)\n {\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 // ============================================================\n // 2. Validate query\n // ============================================================\n const url = new URL(rawContext.req.url);\n const query: Record<string, string | string[]> = {};\n url.searchParams.forEach((v, k) =>\n {\n const existing = query[k];\n if (existing)\n {\n // Convert to array or append to existing array\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 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 // ============================================================\n // 3. Create RouteContext\n // ============================================================\n const routeContext: RouteContext<TContract> = {\n params: params as InferContract<TContract>['params'],\n query: query as InferContract<TContract>['query'],\n\n // data() - validates and returns body\n data: async () =>\n {\n const body = await rawContext.req.json();\n if (contract.body)\n {\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 return body as InferContract<TContract>['body'];\n },\n\n // json() - returns typed response\n json: (data, status, headers) =>\n {\n return rawContext.json(data, status, headers);\n },\n\n // raw Hono context for advanced usage\n raw: rawContext,\n };\n\n // ============================================================\n // 4. Execute handler\n // ============================================================\n return handler(routeContext);\n };\n}","/**\n * Error Handler Middleware\n *\n * Generic middleware that converts errors with statusCode to HTTP responses\n *\n * ✅ Features:\n * - Convert any error with statusCode property to appropriate HTTP status codes\n * - Error logging (log level by status code)\n * - Environment-specific error response format (Production/Development)\n * - Stack trace inclusion (development only)\n * - Support for additional error details\n *\n * 💡 Design:\n * - Domain-independent (doesn't depend on specific error types)\n * - Works with any error that has a statusCode property\n * - Follows dependency inversion principle\n */\nimport type { Context } from 'hono';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { logger } from '../logger';\n\nconst errorLogger = logger.child('error-handler');\n\n/**\n * Error handler options\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\n/**\n * Error response format\n */\ninterface ErrorResponse\n{\n error: {\n message: string;\n type: string;\n statusCode: number;\n stack?: string;\n };\n}\n\n/**\n * Error handler middleware\n *\n * Used in Hono's onError hook\n *\n * @example\n * ```typescript\n * const app = new Hono();\n * app.onError(ErrorHandler());\n * ```\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 // Generic error handling: check for statusCode property\n const statusCode = (err as any).statusCode || 500;\n const errorType = err.name || 'Error';\n\n if (enableLogging)\n {\n // 4xx: warn, 5xx: error\n const logLevel = statusCode >= 500 ? 'error' : 'warn';\n\n errorLogger[logLevel]('Error occurred', {\n type: errorType,\n message: err.message,\n statusCode,\n path: c.req.path,\n method: c.req.method,\n });\n }\n\n const response: ErrorResponse = {\n error: {\n message: err.message || 'Internal Server Error',\n type: errorType,\n statusCode,\n },\n };\n\n // Include additional error details if available\n if ((err as any).details)\n {\n (response.error as any).details = (err as any).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 * Request Logger Middleware\n *\n * Automatic API request/response logging middleware\n *\n * ✅ Features:\n * - Automatic request start/completion logging\n * - Response time measurement\n * - Automatic error logging\n * - Request ID generation (distributed tracing)\n * - Sensitive data masking\n * - Exclude path configuration (health checks, etc.)\n *\n * 💡 Benefits:\n * - Automatic monitoring of all API requests\n * - Identify performance bottlenecks\n * - Easy error tracking\n *\n * 💡 Usage:\n * ```typescript\n * import { RequestLogger } from '@spfn/core';\n *\n * app.use(RequestLogger());\n * ```\n *\n * 🔗 Related files:\n * - src/logger/ (Logger)\n * - src/index.ts (Export)\n */\n\nimport type { Context, Next } from 'hono';\nimport { randomBytes } from 'crypto';\nimport { logger } from '../logger';\n\n/**\n * Request Logger configuration\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\n/**\n * Default configuration\n */\nconst DEFAULT_CONFIG: Required<RequestLoggerConfig> = {\n excludePaths: ['/health', '/ping', '/favicon.ico'],\n sensitiveFields: ['password', 'token', 'apiKey', 'secret', 'authorization'],\n slowRequestThreshold: 1000, // 1 second\n};\n\n/**\n * Generate cryptographically secure request ID\n *\n * Format: req_<timestamp>_<random-hex>\n * Example: req_1759541628730_a3f9c2d8e1b4\n *\n * Collision probability: ~2^-48 (extremely low)\n */\nfunction generateRequestId(): string\n{\n const timestamp = Date.now();\n const randomPart = randomBytes(6).toString('hex'); // 12 hex chars\n return `req_${timestamp}_${randomPart}`;\n}\n\n/**\n * Mask sensitive data with circular reference handling\n *\n * Optimizations:\n * - Pre-computes lowercase fields to avoid repeated toLowerCase() calls\n * - Handles circular references with WeakSet\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 // Prevent circular references\n if (seen.has(obj)) return '[Circular]';\n seen.add(obj);\n\n // Pre-compute lowercase fields (optimization)\n const lowerFields = sensitiveFields.map(f => f.toLowerCase());\n\n const masked = Array.isArray(obj) ? [...obj] : { ...obj };\n\n for (const key in masked)\n {\n const lowerKey = key.toLowerCase();\n\n // Check if sensitive (optimized)\n if (lowerFields.some(field => lowerKey.includes(field)))\n {\n masked[key] = '***MASKED***';\n }\n // Recursively mask nested objects\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 // Check excluded paths\n if (cfg.excludePaths.includes(path))\n {\n return next();\n }\n\n // Generate Request ID and store in context\n const requestId = generateRequestId();\n c.set('requestId', requestId);\n\n // Collect request information\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 // Log request start\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 // Process request\n await next();\n\n // Response completed\n const duration = Date.now() - startTime;\n const status = c.res.status;\n\n // Log response completion\n const logLevel = status >= 400 ? 'warn' : 'info';\n const isSlowRequest = duration >= cfg.slowRequestThreshold;\n\n // Build log data (only include 'slow' when true)\n const logData: Record<string, any> = {\n requestId,\n method,\n path,\n status,\n duration,\n };\n\n if (isSlowRequest)\n {\n logData.slow = true;\n }\n\n apiLogger[logLevel]('Request completed', logData);\n\n // Warn for slow requests\n if (isSlowRequest)\n {\n apiLogger.warn('Slow request detected', {\n requestId,\n method,\n path,\n duration,\n threshold: cfg.slowRequestThreshold,\n });\n }\n }\n catch (error)\n {\n // Error occurred\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 // Re-throw error for error handler to process\n throw error;\n }\n };\n}","import { Hono } from 'hono';\nimport { serve } from '@hono/node-server';\nimport { cors } from 'hono/cors';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport type { Server } from 'http';\n\nimport { loadRoutes } from '../route';\nimport { ErrorHandler } from '../middleware';\nimport { RequestLogger } from '../middleware';\nimport { initRedis, closeRedis } from '../cache';\nimport { initDatabase, closeDatabase } from '../db';\nimport { logger } from '../logger';\n\nimport type { ServerConfig, AppFactory, ServerInstance } from './types.js';\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 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\n // Level 1 & 2: Auto config\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. Default middleware (can be disabled)\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 // 2. Custom middleware from config\n config?.use?.forEach(mw => app.use('*', mw));\n\n // 3. Health check endpoint (before routes)\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, async (c) =>\n {\n const response: any = {\n status: 'ok',\n timestamp: new Date().toISOString(),\n };\n\n if (healthCheckDetailed)\n {\n const { getDatabase } = await import('../db/index.js');\n const { getRedis } = await import('../cache/index.js');\n\n // Check database\n const db = getDatabase();\n let dbStatus = 'disconnected';\n if (db)\n {\n try\n {\n await db.execute('SELECT 1');\n dbStatus = 'connected';\n }\n catch\n {\n dbStatus = 'error';\n }\n }\n\n // Check Redis\n const redis = getRedis();\n let redisStatus = 'disconnected';\n if (redis)\n {\n try\n {\n await redis.ping();\n redisStatus = 'connected';\n }\n catch\n {\n redisStatus = 'error';\n }\n }\n\n response.services = {\n database: dbStatus,\n redis: redisStatus,\n };\n }\n\n return c.json(response);\n });\n\n serverLogger.debug(`Health check endpoint enabled at ${healthCheckPath}`);\n }\n\n // 4. beforeRoutes hook\n await config?.beforeRoutes?.(app);\n\n // 4. Load routes\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 // 5. afterRoutes hook\n await config?.afterRoutes?.(app);\n\n // 6. Error handler (last)\n if (enableErrorHandler)\n {\n app.onError(ErrorHandler());\n }\n\n return app;\n}\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 cwd = process.cwd();\n const configPath = join(cwd, 'src', 'server', 'server.config.ts');\n const configJsPath = join(cwd, 'src', 'server', 'server.config.js');\n\n // Load server.config.ts if exists\n let fileConfig: ServerConfig = {};\n if (existsSync(configPath) || existsSync(configJsPath))\n {\n const configModule = await import(existsSync(configPath) ? configPath : configJsPath);\n fileConfig = configModule.default ?? {};\n }\n\n // Merge config (runtime > file > env > defaults)\n const finalConfig: ServerConfig =\n {\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 const { host, port, debug } = finalConfig;\n\n try\n {\n // Initialize infrastructure (Database and Redis) with config\n serverLogger.debug('Initializing database...');\n await initDatabase(finalConfig.database);\n\n serverLogger.debug('Initializing Redis...');\n await initRedis();\n\n // Create app\n serverLogger.debug('Creating Hono app...');\n const app = await createServer(finalConfig);\n\n // Start server\n serverLogger.debug(`Starting server on ${host}:${port}...`);\n\n const server = serve(\n {\n fetch: app.fetch,\n port: port!,\n hostname: host,\n });\n\n // Configure server timeouts\n const timeoutConfig = finalConfig.timeout ?? {};\n\n const requestTimeout = timeoutConfig.request\n ?? (parseInt(process.env.SERVER_TIMEOUT || '', 10) || 120000); // 2 minutes default\n\n const keepAliveTimeout = timeoutConfig.keepAlive\n ?? (parseInt(process.env.SERVER_KEEPALIVE_TIMEOUT || '', 10) || 65000); // 65 seconds (longer than typical LB timeout)\n\n const headersTimeout = timeoutConfig.headers\n ?? (parseInt(process.env.SERVER_HEADERS_TIMEOUT || '', 10) || 60000); // 60 seconds\n\n // Apply timeouts to Node.js HTTP server\n // The serve() function returns ServerType (Server | Http2Server | Http2SecureServer)\n // All these types support timeout properties\n if ('timeout' in server)\n {\n (server as Server).timeout = requestTimeout;\n (server as Server).keepAliveTimeout = keepAliveTimeout;\n (server as Server).headersTimeout = headersTimeout;\n }\n\n serverLogger.info('Server timeouts configured', {\n request: `${requestTimeout}ms`,\n keepAlive: `${keepAliveTimeout}ms`,\n headers: `${headersTimeout}ms`,\n });\n\n // Clean output similar to Next.js\n console.log(` ▲ SPFN ${debug ? 'dev' : 'production'}`);\n console.log(` - Local: http://${host}:${port}`);\n console.log('');\n\n // Core shutdown logic (without process.exit)\n const shutdownServer = 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 serverLogger.debug('Closing database connections...');\n await closeDatabase();\n\n serverLogger.debug('Closing Redis connections...');\n await closeRedis();\n\n serverLogger.info('Server shutdown completed');\n };\n\n // Graceful shutdown handler (with process.exit and timeout)\n const shutdown = async (signal: string) =>\n {\n serverLogger.info(`${signal} received, starting graceful shutdown...`);\n\n // Get shutdown timeout from config\n const shutdownTimeout = finalConfig.shutdown?.timeout\n ?? (parseInt(process.env.SHUTDOWN_TIMEOUT || '', 10) || 30000);\n\n // Create timeout promise\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 // Race between graceful shutdown and timeout\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 // Manual close method (without process.exit, for tests)\n const close = async () =>\n {\n serverLogger.info('Manual server shutdown requested');\n await shutdownServer();\n };\n\n // Register shutdown handlers\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n\n // Handle uncaught exceptions\n process.on('uncaughtException', (error) =>\n {\n serverLogger.error('Uncaught exception', error);\n shutdown('UNCAUGHT_EXCEPTION');\n });\n\n // Handle unhandled promise rejections\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 // Return server instance\n return {\n server,\n app,\n config: finalConfig,\n close,\n };\n }\n catch (error)\n {\n const err = error as Error;\n serverLogger.error('Server initialization failed', err);\n\n // Cleanup on failure\n try\n {\n serverLogger.debug('Cleaning up after initialization failure...');\n await closeDatabase();\n await closeRedis();\n serverLogger.debug('Cleanup completed');\n }\n catch (cleanupError)\n {\n serverLogger.error('Cleanup failed', cleanupError as Error);\n }\n\n throw error;\n }\n}"]}
1
+ {"version":3,"sources":["../../src/logger/adapters/pino.ts","../../src/logger/types.ts","../../src/logger/formatters.ts","../../src/logger/logger.ts","../../src/logger/transports/console.ts","../../src/logger/transports/file.ts","../../src/logger/config.ts","../../src/logger/adapters/custom.ts","../../src/logger/adapter-factory.ts","../../src/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/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","getDatabase","closeDatabase","init_manager","readdirSync","stat","statSync","dirname","readFileSync","packageSchemas","schema","txLogger","init_helpers","cacheLogger","routeLogger","count","discoverFunctionRoutes","getRedis","Hono","serverLogger"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Pino Logger Adapter\n *\n * High-performance logger adapter using Pino with pretty-print for development and JSON for production.\n */\n\nimport pino from 'pino';\nimport type { LoggerAdapter, AdapterConfig, LogLevel } from './types';\n\n/**\n * Pino Logger Adapter\n */\nexport class PinoAdapter implements LoggerAdapter\n{\n private logger: pino.Logger;\n\n constructor(config: AdapterConfig)\n {\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n // Development: use simple console output without transport\n // Production: use JSON output\n this.logger = pino({\n level: config.level,\n\n // 기본 필드\n base: config.module ? { module: config.module } : undefined,\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const childLogger = new PinoAdapter({ level: this.logger.level as LogLevel, module });\n childLogger.logger = this.logger.child({ module });\n return childLogger;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(context || {}, message);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(context || {}, message);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.warn(errorOrContext || {}, message);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.error(errorOrContext || {}, message);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.fatal(errorOrContext || {}, message);\n }\n }\n\n async close(): Promise<void>\n {\n // Pino는 자동으로 flush됨\n // 필요시 pino.final() 사용 가능\n }\n}","/**\n * Logger Type Definitions\n *\n * 로깅 시스템 타입 정의\n *\n * ✅ 구현 완료:\n * - LogLevel 타입 정의\n * - LogMetadata 인터페이스\n * - Transport 인터페이스\n * - 환경별 설정 타입\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현체)\n * - src/logger/config.ts (설정)\n */\n\n/**\n * 로그 레벨\n * debug < info < warn < error < fatal\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * 로그 레벨 우선순위\n */\nexport const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n fatal: 4,\n};\n\n/**\n * 로그 메타데이터\n */\nexport interface LogMetadata\n{\n timestamp: Date;\n level: LogLevel;\n message: string;\n module?: string;\n error?: Error;\n context?: Record<string, unknown>;\n}\n\n/**\n * Transport 인터페이스\n * 모든 Transport는 이 인터페이스를 구현해야 함\n */\nexport interface Transport\n{\n /**\n * Transport 이름\n */\n name: string;\n\n /**\n * 최소 로그 레벨 (이 레벨 이상만 처리)\n */\n level: LogLevel;\n\n /**\n * 활성화 여부\n */\n enabled: boolean;\n\n /**\n * 로그 처리 함수\n */\n log(metadata: LogMetadata): Promise<void>;\n\n /**\n * Transport 종료 (리소스 정리)\n */\n close?(): Promise<void>;\n}\n\n/**\n * Logger 설정\n */\nexport interface LoggerConfig\n{\n /**\n * 기본 로그 레벨\n */\n level: LogLevel;\n\n /**\n * 모듈명 (context)\n */\n module?: string;\n\n /**\n * Transport 리스트\n */\n transports: Transport[];\n}\n\n/**\n * Transport 설정 (공통)\n */\nexport interface TransportConfig\n{\n level: LogLevel;\n enabled: boolean;\n}\n\n/**\n * Console Transport 설정\n */\nexport interface ConsoleTransportConfig extends TransportConfig\n{\n colorize?: boolean;\n}\n\n/**\n * File Transport 설정\n */\nexport interface FileTransportConfig extends TransportConfig\n{\n logDir: string;\n maxFileSize?: number; // bytes\n maxFiles?: number; // 최대 로그 파일 개수\n}\n\n/**\n * Slack Transport 설정\n */\nexport interface SlackTransportConfig extends TransportConfig\n{\n webhookUrl: string;\n channel?: string;\n username?: string;\n}\n\n/**\n * Email Transport 설정\n */\nexport interface EmailTransportConfig extends TransportConfig\n{\n from: string;\n to: string[];\n smtpHost: string;\n smtpPort: number;\n smtpUser?: string;\n smtpPassword?: string;\n}","/**\n * Logger Formatters\n *\n * Log formatting utilities for console, JSON, Slack, and Email outputs with sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata } from './types';\n\n/**\n * 민감 정보로 간주되는 키 목록\n * 이 키들을 포함하는 필드는 자동으로 마스킹됨\n */\nconst SENSITIVE_KEYS = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'accesstoken',\n 'access_token',\n 'refreshtoken',\n 'refresh_token',\n 'authorization',\n 'auth',\n 'cookie',\n 'session',\n 'sessionid',\n 'session_id',\n 'privatekey',\n 'private_key',\n 'creditcard',\n 'credit_card',\n 'cardnumber',\n 'card_number',\n 'cvv',\n 'ssn',\n 'pin',\n];\n\n/**\n * 마스킹된 값\n */\nconst MASKED_VALUE = '***MASKED***';\n\n/**\n * 키가 민감 정보를 포함하는지 확인\n */\nfunction isSensitiveKey(key: string): boolean\n{\n const lowerKey = key.toLowerCase();\n return SENSITIVE_KEYS.some(sensitive => lowerKey.includes(sensitive));\n}\n\n/**\n * 민감 정보 마스킹\n * Context 객체에서 민감한 정보(비밀번호, 토큰 등)를 마스킹\n *\n * @param data - 원본 데이터\n * @returns 마스킹된 데이터\n */\nexport function maskSensitiveData(data: unknown): unknown\n{\n // null, undefined 처리\n if (data === null || data === undefined)\n {\n return data;\n }\n\n // 배열 처리\n if (Array.isArray(data))\n {\n return data.map(item => maskSensitiveData(item));\n }\n\n // 객체 처리\n if (typeof data === 'object')\n {\n const masked: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data))\n {\n if (isSensitiveKey(key))\n {\n // 민감 정보 키는 마스킹\n masked[key] = MASKED_VALUE;\n }\n else if (typeof value === 'object' && value !== null)\n {\n // 중첩된 객체는 재귀 처리\n masked[key] = maskSensitiveData(value);\n }\n else\n {\n // 일반 값은 그대로 유지\n masked[key] = value;\n }\n }\n\n return masked;\n }\n\n // 기본 타입은 그대로 반환\n return data;\n}\n\n/**\n * ANSI 컬러 코드\n */\nconst COLORS = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n\n // 로그 레벨 컬러\n debug: '\\x1b[36m', // cyan\n info: '\\x1b[32m', // green\n warn: '\\x1b[33m', // yellow\n error: '\\x1b[31m', // red\n fatal: '\\x1b[35m', // magenta\n\n // 추가 컬러\n gray: '\\x1b[90m',\n};\n\n/**\n * 로그 레벨을 컬러 문자열로 변환\n */\nexport function colorizeLevel(level: LogLevel): string\n{\n const color = COLORS[level];\n const levelStr = level.toUpperCase().padEnd(5);\n return `${color}${levelStr}${COLORS.reset}`;\n}\n\n/**\n * 타임스탬프 포맷 (ISO 8601)\n */\nexport function formatTimestamp(date: Date): string\n{\n return date.toISOString();\n}\n\n/**\n * 타임스탬프 포맷 (사람이 읽기 쉬운 형식)\n */\nexport function formatTimestampHuman(date: Date): string\n{\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n const seconds = String(date.getSeconds()).padStart(2, '0');\n const ms = String(date.getMilliseconds()).padStart(3, '0');\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`;\n}\n\n/**\n * 에러 객체를 문자열로 변환 (스택 트레이스 포함)\n */\nexport function formatError(error: Error): string\n{\n const lines: string[] = [];\n\n lines.push(`${error.name}: ${error.message}`);\n\n if (error.stack)\n {\n const stackLines = error.stack.split('\\n').slice(1);\n lines.push(...stackLines);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Context 객체를 문자열로 변환\n */\nexport function formatContext(context: Record<string, unknown>): string\n{\n try\n {\n return JSON.stringify(context, null, 2);\n }\n catch (error)\n {\n return '[Context serialization failed]';\n }\n}\n\n/**\n * 콘솔용 컬러 포맷\n */\nexport function formatConsole(metadata: LogMetadata, colorize = true): string\n{\n const parts: string[] = [];\n\n // [타임스탬프]\n const timestamp = formatTimestampHuman(metadata.timestamp);\n if (colorize)\n {\n parts.push(`${COLORS.gray}[${timestamp}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${timestamp}]`);\n }\n\n // [module=value]\n if (metadata.module)\n {\n if (colorize)\n {\n parts.push(`${COLORS.dim}[module=${metadata.module}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[module=${metadata.module}]`);\n }\n }\n\n // Context를 각각 [key=value] 형태로 추가\n if (metadata.context && Object.keys(metadata.context).length > 0)\n {\n Object.entries(metadata.context).forEach(([key, value]) =>\n {\n const valueStr = typeof value === 'string' ? value : String(value);\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Slack 메시지 포맷\n */\nexport function formatSlack(metadata: LogMetadata): string\n{\n const emoji = {\n debug: ':bug:',\n info: ':information_source:',\n warn: ':warning:',\n error: ':x:',\n fatal: ':fire:',\n };\n\n const parts: string[] = [];\n\n parts.push(`${emoji[metadata.level]} *${metadata.level.toUpperCase()}*`);\n\n if (metadata.module)\n {\n parts.push(`\\`[${metadata.module}]\\``);\n }\n\n parts.push(metadata.message);\n\n let message = parts.join(' ');\n\n if (metadata.context)\n {\n message += '\\n```\\n' + JSON.stringify(metadata.context, null, 2) + '\\n```';\n }\n\n if (metadata.error)\n {\n message += '\\n```\\n' + formatError(metadata.error) + '\\n```';\n }\n\n return message;\n}\n\n/**\n * Email 제목 생성\n */\nexport function formatEmailSubject(metadata: LogMetadata): string\n{\n const prefix = `[${metadata.level.toUpperCase()}]`;\n const module = metadata.module ? `[${metadata.module}]` : '';\n\n return `${prefix}${module} ${metadata.message}`;\n}\n\n/**\n * Email 본문 생성 (HTML)\n */\nexport function formatEmailBody(metadata: LogMetadata): string\n{\n const parts: string[] = [];\n\n parts.push('<html>');\n parts.push('<body style=\"font-family: monospace; padding: 20px;\">');\n\n // 헤더\n parts.push(`<h2 style=\"color: ${getEmailColor(metadata.level)};\">`);\n parts.push(`${metadata.level.toUpperCase()}`);\n parts.push('</h2>');\n\n // 시간\n parts.push('<p>');\n parts.push(`<strong>Timestamp:</strong> ${formatTimestamp(metadata.timestamp)}`);\n parts.push('</p>');\n\n // 모듈\n if (metadata.module)\n {\n parts.push('<p>');\n parts.push(`<strong>Module:</strong> ${metadata.module}`);\n parts.push('</p>');\n }\n\n // 메시지\n parts.push('<p>');\n parts.push(`<strong>Message:</strong> ${metadata.message}`);\n parts.push('</p>');\n\n // Context\n if (metadata.context)\n {\n parts.push('<h3>Context</h3>');\n parts.push('<pre style=\"background: #f4f4f4; padding: 10px; border-radius: 4px;\">');\n parts.push(JSON.stringify(metadata.context, null, 2));\n parts.push('</pre>');\n }\n\n // 에러\n if (metadata.error)\n {\n parts.push('<h3>Error Stack Trace</h3>');\n parts.push('<pre style=\"background: #fff0f0; padding: 10px; border-radius: 4px;\">');\n parts.push(formatError(metadata.error));\n parts.push('</pre>');\n }\n\n parts.push('</body>');\n parts.push('</html>');\n\n return parts.join('\\n');\n}\n\n/**\n * Email 레벨별 컬러\n */\nfunction getEmailColor(level: LogLevel): string\n{\n const colors: Record<LogLevel, string> = {\n debug: '#00BCD4',\n info: '#4CAF50',\n warn: '#FF9800',\n error: '#F44336',\n fatal: '#9C27B0',\n };\n\n return colors[level];\n}","/**\n * Logger Class\n *\n * Central logging class with multiple transports, child loggers, and sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata, LoggerConfig, Transport } from './types';\nimport { LOG_LEVEL_PRIORITY } from './types';\nimport { maskSensitiveData } from './formatters';\n\n/**\n * Logger class\n */\nexport class Logger\n{\n private readonly config: LoggerConfig;\n private readonly module?: string;\n\n constructor(config: LoggerConfig)\n {\n this.config = config;\n this.module = config.module;\n }\n\n /**\n * Get current log level\n */\n get level(): LogLevel\n {\n return this.config.level;\n }\n\n /**\n * Create child logger (per module)\n */\n child(module: string): Logger\n {\n return new Logger({\n ...this.config,\n module,\n });\n }\n\n /**\n * Debug log\n */\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.log('debug', message, undefined, context);\n }\n\n /**\n * Info log\n */\n info(message: string, context?: Record<string, unknown>): void\n {\n this.log('info', message, undefined, context);\n }\n\n /**\n * Warn log\n */\n warn(message: string, context?: Record<string, unknown>): void;\n warn(message: string, error: Error, context?: Record<string, unknown>): void;\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('warn', message, errorOrContext, context);\n }\n else\n {\n this.log('warn', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Error log\n */\n error(message: string, context?: Record<string, unknown>): void;\n error(message: string, error: Error, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('error', message, errorOrContext, context);\n }\n else\n {\n this.log('error', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Fatal log\n */\n fatal(message: string, context?: Record<string, unknown>): void;\n fatal(message: string, error: Error, context?: Record<string, unknown>): void;\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('fatal', message, errorOrContext, context);\n }\n else\n {\n this.log('fatal', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Log processing (internal)\n */\n private log(level: LogLevel, message: string, error?: Error, context?: Record<string, unknown>): void\n {\n // Early return if log level is below configured level\n // This prevents unnecessary metadata creation and processing\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level])\n {\n return;\n }\n\n const metadata: LogMetadata = {\n timestamp: new Date(),\n level,\n message,\n module: this.module,\n error,\n // Mask sensitive information in context to prevent credential leaks\n context: context ? maskSensitiveData(context) as Record<string, unknown> : undefined,\n };\n\n // Pass to all enabled Transports\n this.processTransports(metadata);\n }\n\n /**\n * Process Transports\n */\n private processTransports(metadata: LogMetadata): void\n {\n const promises = this.config.transports\n .filter(transport => transport.enabled)\n .map(transport => this.safeTransportLog(transport, metadata));\n\n // Async processing to prevent Transport errors from blocking logs\n Promise.all(promises).catch(error =>\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport error: ${errorMessage}\\n`);\n });\n }\n\n /**\n * Transport log (error-safe)\n */\n private async safeTransportLog(transport: Transport, metadata: LogMetadata): Promise<void>\n {\n try\n {\n await transport.log(metadata);\n }\n catch (error)\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport \"${transport.name}\" failed: ${errorMessage}\\n`);\n }\n }\n\n /**\n * Close all Transports\n */\n async close(): Promise<void>\n {\n const closePromises = this.config.transports\n .filter(transport => transport.close)\n .map(transport => transport.close!());\n\n await Promise.all(closePromises);\n }\n}","/**\n * Console Transport\n *\n * 콘솔 출력 Transport\n *\n * ✅ 구현 완료:\n * - 콘솔 출력 (stdout/stderr)\n * - 컬러 출력 지원\n * - 로그 레벨별 스트림 분리 (warn/error/fatal → stderr)\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (Transport 인터페이스)\n * - src/logger/formatters.ts (포맷터)\n * - src/logger/config.ts (설정)\n */\n\nimport type { Transport, LogMetadata, LogLevel, ConsoleTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatConsole } from '../formatters';\n\n/**\n * Console Transport\n */\nexport class ConsoleTransport implements Transport\n{\n public readonly name = 'console';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private colorize: boolean;\n\n constructor(config: ConsoleTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.colorize = config.colorize ?? true;\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // 포맷팅\n const message = formatConsole(metadata, this.colorize);\n\n // warn/error/fatal은 stderr로, 나머지는 stdout으로\n if (metadata.level === 'warn' || metadata.level === 'error' || metadata.level === 'fatal')\n {\n console.error(message);\n }\n else\n {\n console.log(message);\n }\n }\n}","/**\n * File Transport\n *\n * File output transport with date and size-based rotation, automatic cleanup.\n */\n\nimport { createWriteStream, existsSync, mkdirSync, statSync, readdirSync, unlinkSync, renameSync } from 'fs';\nimport type { WriteStream } from 'fs';\nimport { join } from 'path';\nimport type { Transport, LogMetadata, LogLevel, FileTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatJSON } from '../formatters';\n\n/**\n * File Transport\n */\nexport class FileTransport implements Transport\n{\n public readonly name = 'file';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private readonly logDir: string;\n private readonly maxFileSize: number;\n private readonly maxFiles: number;\n private currentStream: WriteStream | null = null;\n private currentFilename: string | null = null;\n\n constructor(config: FileTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.logDir = config.logDir;\n this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024; // 10MB\n this.maxFiles = config.maxFiles ?? 10;\n\n // 로그 디렉토리가 없으면 생성\n if (!existsSync(this.logDir))\n {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // JSON 포맷으로 변환\n const message = formatJSON(metadata);\n\n // 파일명: YYYY-MM-DD.log\n const filename = this.getLogFilename(metadata.timestamp);\n\n // 날짜가 변경되면 스트림 교체\n if (this.currentFilename !== filename)\n {\n await this.rotateStream(filename);\n await this.cleanOldFiles(); // 오래된 파일 정리\n }\n // 파일 크기 체크 및 로테이션\n else if (this.currentFilename)\n {\n await this.checkAndRotateBySize();\n }\n\n // 스트림에 쓰기\n if (this.currentStream)\n {\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.write(message + '\\n', 'utf-8', (error: Error | null | undefined) =>\n {\n if (error)\n {\n // 파일 쓰기 실패 시 stderr로 출력 (fallback)\n process.stderr.write(`[FileTransport] Failed to write log: ${error.message}\\n`);\n reject(error);\n }\n else\n {\n resolve();\n }\n });\n });\n }\n }\n\n /**\n * 스트림 교체 (날짜 변경 시)\n */\n private async rotateStream(filename: string): Promise<void>\n {\n // 기존 스트림 닫기\n if (this.currentStream)\n {\n await this.closeStream();\n }\n\n // 새 스트림 생성\n const filepath = join(this.logDir, filename);\n\n this.currentStream = createWriteStream(filepath, {\n flags: 'a', // append mode\n encoding: 'utf-8',\n });\n\n this.currentFilename = filename;\n\n // 스트림 에러 핸들링\n this.currentStream.on('error', (error) =>\n {\n process.stderr.write(`[FileTransport] Stream error: ${error.message}\\n`);\n // 에러 발생 시 스트림 초기화\n this.currentStream = null;\n this.currentFilename = null;\n });\n }\n\n /**\n * 현재 스트림 닫기\n */\n private async closeStream(): Promise<void>\n {\n if (!this.currentStream)\n {\n return;\n }\n\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.end((error: Error | null | undefined) =>\n {\n if (error)\n {\n reject(error);\n }\n else\n {\n this.currentStream = null;\n this.currentFilename = null;\n resolve();\n }\n });\n });\n }\n\n /**\n * 파일 크기 체크 및 크기 기반 로테이션\n */\n private async checkAndRotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n const filepath = join(this.logDir, this.currentFilename);\n\n // 파일이 존재하지 않으면 스킵\n if (!existsSync(filepath))\n {\n return;\n }\n\n try\n {\n const stats = statSync(filepath);\n\n // 파일 크기가 maxFileSize를 초과하면 로테이션\n if (stats.size >= this.maxFileSize)\n {\n await this.rotateBySize();\n }\n }\n catch (error)\n {\n // 파일 stat 실패 시 무시\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 크기 기반 로테이션 수행\n * 예: 2025-01-01.log -> 2025-01-01.1.log, 2025-01-01.1.log -> 2025-01-01.2.log\n */\n private async rotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n // 기존 스트림 닫기\n await this.closeStream();\n\n const baseName = this.currentFilename.replace(/\\.log$/, '');\n const files = readdirSync(this.logDir);\n\n // 현재 날짜의 로그 파일들 찾기 (예: 2025-01-01.log, 2025-01-01.1.log, ...)\n const relatedFiles = files\n .filter(file => file.startsWith(baseName) && file.endsWith('.log'))\n .sort()\n .reverse(); // 역순 정렬로 높은 번호부터 처리\n\n // 기존 파일들을 번호 증가시켜 이동 (예: .1.log -> .2.log)\n for (const file of relatedFiles)\n {\n const match = file.match(/\\.(\\d+)\\.log$/);\n if (match)\n {\n const oldNum = parseInt(match[1], 10);\n const newNum = oldNum + 1;\n const oldPath = join(this.logDir, file);\n const newPath = join(this.logDir, `${baseName}.${newNum}.log`);\n\n try\n {\n renameSync(oldPath, newPath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}\\n`);\n }\n }\n }\n\n // 현재 파일을 .1.log로 이동\n const currentPath = join(this.logDir, this.currentFilename);\n const newPath = join(this.logDir, `${baseName}.1.log`);\n\n try\n {\n if (existsSync(currentPath))\n {\n renameSync(currentPath, newPath);\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}\\n`);\n }\n\n // 새 스트림 생성 (동일한 파일명으로)\n await this.rotateStream(this.currentFilename);\n }\n\n /**\n * 오래된 로그 파일 정리\n * maxFiles 개수를 초과하는 로그 파일 삭제\n */\n private async cleanOldFiles(): Promise<void>\n {\n try\n {\n // 디렉토리가 존재하지 않으면 스킵\n if (!existsSync(this.logDir))\n {\n return;\n }\n\n const files = readdirSync(this.logDir);\n\n // .log로 끝나는 파일만 필터링 후 수정 시간 기준 정렬\n const logFiles = files\n .filter(file => file.endsWith('.log'))\n .map(file =>\n {\n const filepath = join(this.logDir, file);\n const stats = statSync(filepath);\n return { file, mtime: stats.mtime };\n })\n .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); // 최신 파일이 앞으로\n\n // maxFiles를 초과하는 오래된 파일들 삭제\n if (logFiles.length > this.maxFiles)\n {\n const filesToDelete = logFiles.slice(this.maxFiles);\n\n for (const { file } of filesToDelete)\n {\n const filepath = join(this.logDir, file);\n try\n {\n unlinkSync(filepath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to delete old file \"${file}\": ${errorMessage}\\n`);\n }\n }\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 날짜별 로그 파일명 생성\n */\n private getLogFilename(date: Date): string\n {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}.log`;\n }\n\n async close(): Promise<void>\n {\n // 스트림 정리\n await this.closeStream();\n }\n}","/**\n * Logger Configuration\n *\n * Environment-based logger configuration with validation for console, file, Slack, and Email transports.\n */\n\nimport { existsSync, accessSync, constants, mkdirSync, writeFileSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type {\n LogLevel,\n ConsoleTransportConfig,\n FileTransportConfig,\n SlackTransportConfig,\n EmailTransportConfig,\n} from './types';\n\n/**\n * Check if file logging is enabled (for self-hosted)\n */\nexport function isFileLoggingEnabled(): boolean\n{\n return process.env.LOGGER_FILE_ENABLED === 'true';\n}\n\n/**\n * Get default log level by environment\n */\nexport function getDefaultLogLevel(): LogLevel\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment)\n {\n return 'debug';\n }\n\n if (isProduction)\n {\n return 'info';\n }\n\n // Test environment\n return 'warn';\n}\n\n/**\n * Console Transport configuration\n */\nexport function getConsoleConfig(): ConsoleTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'debug',\n enabled: true,\n colorize: !isProduction, // Dev: colored output, Production: plain text\n };\n}\n\n/**\n * File Transport configuration\n */\nexport function getFileConfig(): FileTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'info',\n enabled: isProduction, // File logging in production only\n logDir: process.env.LOG_DIR || './logs',\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n };\n}\n\n/**\n * Slack Transport configuration\n */\nexport function getSlackConfig(): SlackTransportConfig | null\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return null; // Disabled if not configured\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'error', // Send error and above to Slack\n enabled: isProduction, // Enabled in production only\n webhookUrl,\n channel: process.env.SLACK_CHANNEL,\n username: process.env.SLACK_USERNAME || 'Logger Bot',\n };\n}\n\n/**\n * Email Transport configuration\n */\nexport function getEmailConfig(): EmailTransportConfig | null\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // Disabled if required settings are missing\n if (!smtpHost || !smtpPort || !emailFrom || !emailTo)\n {\n return null;\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'fatal', // Send fatal level only via email\n enabled: isProduction, // Enabled in production only\n from: emailFrom,\n to: emailTo.split(',').map(email => email.trim()),\n smtpHost,\n smtpPort: parseInt(smtpPort, 10),\n smtpUser: process.env.SMTP_USER,\n smtpPassword: process.env.SMTP_PASSWORD,\n };\n}\n\n/**\n * Validate directory path and write permissions\n */\nfunction validateDirectoryWritable(dirPath: string): void\n{\n // Check if directory exists\n if (!existsSync(dirPath))\n {\n // Try to create directory\n try\n {\n mkdirSync(dirPath, { recursive: true });\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to create log directory \"${dirPath}\": ${errorMessage}`);\n }\n }\n\n // Check write permission\n try\n {\n accessSync(dirPath, constants.W_OK);\n }\n catch\n {\n throw new Error(`Log directory \"${dirPath}\" is not writable. Please check permissions.`);\n }\n\n // Try to write a test file\n const testFile = join(dirPath, '.logger-write-test');\n try\n {\n writeFileSync(testFile, 'test', 'utf-8');\n unlinkSync(testFile);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Cannot write to log directory \"${dirPath}\": ${errorMessage}`);\n }\n}\n\n/**\n * Validate file transport configuration\n */\nfunction validateFileConfig(): void\n{\n if (!isFileLoggingEnabled())\n {\n return; // File logging disabled, skip validation\n }\n\n const logDir = process.env.LOG_DIR;\n\n // Check if LOG_DIR is set\n if (!logDir)\n {\n throw new Error(\n 'LOG_DIR environment variable is required when LOGGER_FILE_ENABLED=true. ' +\n 'Example: LOG_DIR=/var/log/myapp'\n );\n }\n\n // Validate directory\n validateDirectoryWritable(logDir);\n}\n\n/**\n * Validate Slack transport configuration\n */\nfunction validateSlackConfig(): void\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return; // Slack disabled, skip validation\n }\n\n // Validate webhook URL format\n if (!webhookUrl.startsWith('https://hooks.slack.com/'))\n {\n throw new Error(\n `Invalid SLACK_WEBHOOK_URL: \"${webhookUrl}\". ` +\n 'Slack webhook URLs must start with \"https://hooks.slack.com/\"'\n );\n }\n}\n\n/**\n * Validate Email transport configuration\n */\nfunction validateEmailConfig(): void\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // If any email config is set, all required fields must be present\n const hasAnyEmailConfig = smtpHost || smtpPort || emailFrom || emailTo;\n if (!hasAnyEmailConfig)\n {\n return; // Email disabled, skip validation\n }\n\n // Validate all required fields\n const missingFields: string[] = [];\n if (!smtpHost) missingFields.push('SMTP_HOST');\n if (!smtpPort) missingFields.push('SMTP_PORT');\n if (!emailFrom) missingFields.push('EMAIL_FROM');\n if (!emailTo) missingFields.push('EMAIL_TO');\n\n if (missingFields.length > 0)\n {\n throw new Error(\n `Email transport configuration incomplete. Missing: ${missingFields.join(', ')}. ` +\n 'Either set all required fields or remove all email configuration.'\n );\n }\n\n // Validate SMTP port is a number\n const port = parseInt(smtpPort!, 10);\n if (isNaN(port) || port < 1 || port > 65535)\n {\n throw new Error(\n `Invalid SMTP_PORT: \"${smtpPort}\". Must be a number between 1 and 65535.`\n );\n }\n\n // Validate email format (basic check)\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(emailFrom!))\n {\n throw new Error(`Invalid EMAIL_FROM format: \"${emailFrom}\"`);\n }\n\n // Validate email recipients\n const recipients = emailTo!.split(',').map(e => e.trim());\n for (const email of recipients)\n {\n if (!emailRegex.test(email))\n {\n throw new Error(`Invalid email address in EMAIL_TO: \"${email}\"`);\n }\n }\n}\n\n/**\n * Validate environment variables\n */\nfunction validateEnvironment(): void\n{\n const nodeEnv = process.env.NODE_ENV;\n\n if (!nodeEnv)\n {\n process.stderr.write(\n '[Logger] Warning: NODE_ENV is not set. Defaulting to test environment.\\n'\n );\n }\n // Allow any NODE_ENV value (development, production, test, staging, local, etc.)\n // No validation needed - users can use custom environments\n}\n\n/**\n * Validate all logger configuration\n * Throws an error if configuration is invalid\n */\nexport function validateConfig(): void\n{\n try\n {\n validateEnvironment();\n validateFileConfig();\n validateSlackConfig();\n validateEmailConfig();\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n throw new Error(`[Logger] Configuration validation failed: ${error.message}`);\n }\n throw error;\n }\n}","/**\n * Custom Logger Adapter\n *\n * 자체 구현한 Logger를 사용하는 Adapter\n *\n * ✅ 구현 완료:\n * - 기존 Logger 클래스 래핑\n * - Transport 시스템 (Console, File)\n * - Child logger 지원\n *\n * 💡 용도:\n * - Pino 의존성 제거 필요시\n * - 커스텀 Transport 필요시\n * - 완전한 제어가 필요한 경우\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현)\n * - src/logger/adapters/types.ts (인터페이스)\n */\n\nimport { Logger } from '../logger';\nimport { ConsoleTransport } from '../transports/console';\nimport { FileTransport } from '../transports/file';\nimport { getConsoleConfig, getFileConfig } from '../config';\nimport type { LoggerAdapter, AdapterConfig } from './types';\nimport type { Transport } from '../types';\n\n/**\n * Transport 초기화\n */\nfunction initializeTransports(): Transport[]\n{\n const transports: Transport[] = [];\n\n // Console Transport (항상 활성화)\n const consoleConfig = getConsoleConfig();\n transports.push(new ConsoleTransport(consoleConfig));\n\n // File Transport (프로덕션에서만 활성화)\n const fileConfig = getFileConfig();\n if (fileConfig.enabled)\n {\n transports.push(new FileTransport(fileConfig));\n }\n\n return transports;\n}\n\n/**\n * Custom Logger Adapter\n */\nexport class CustomAdapter implements LoggerAdapter\n{\n private logger: Logger;\n\n constructor(config: AdapterConfig)\n {\n this.logger = new Logger({\n level: config.level,\n module: config.module,\n transports: initializeTransports(),\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const adapter = new CustomAdapter({ level: this.logger.level, module });\n adapter.logger = this.logger.child(module);\n return adapter;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(message, context);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn(message, errorOrContext, context);\n }\n else\n {\n this.logger.warn(message, errorOrContext);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error(message, errorOrContext, context);\n }\n else\n {\n this.logger.error(message, errorOrContext);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal(message, errorOrContext, context);\n }\n else\n {\n this.logger.fatal(message, errorOrContext);\n }\n }\n\n async close(): Promise<void>\n {\n await this.logger.close();\n }\n}","/**\n * Logger Adapter Factory\n *\n * Adapter creation and initialization logic\n */\n\nimport { PinoAdapter } from './adapters/pino.js';\nimport { CustomAdapter } from './adapters/custom.js';\nimport { getDefaultLogLevel, validateConfig } from './config.js';\nimport type { LoggerAdapter } from './adapters/types.js';\n\n/**\n * Adapter type\n */\ntype AdapterType = 'pino' | 'custom';\n\n/**\n * Create adapter instance\n */\nfunction createAdapter(type: AdapterType): LoggerAdapter\n{\n const level = getDefaultLogLevel();\n\n switch (type)\n {\n case 'pino':\n return new PinoAdapter({ level });\n\n case 'custom':\n return new CustomAdapter({ level });\n\n default:\n return new PinoAdapter({ level });\n }\n}\n\n/**\n * Read adapter type from environment variable\n */\nfunction getAdapterType(): AdapterType\n{\n const adapterEnv = process.env.LOGGER_ADAPTER as AdapterType;\n\n if (adapterEnv === 'custom' || adapterEnv === 'pino')\n {\n return adapterEnv;\n }\n\n // Default: pino\n return 'pino';\n}\n\n/**\n * Initialize logger with configuration validation\n */\nfunction initializeLogger(): LoggerAdapter\n{\n // Validate configuration before creating logger\n validateConfig();\n\n // Create and return logger instance\n return createAdapter(getAdapterType());\n}\n\n/**\n * Singleton Logger instance\n */\nexport const logger: LoggerAdapter = initializeLogger();","/**\n * Logger Module Exports\n *\n * Entry point for logger module (Pure re-export only)\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 * 💡 Adapter switching:\n * - Environment variable: LOGGER_ADAPTER=pino (default) or custom\n * - Pino: High performance, production-proven\n * - Custom: Full control, no Pino dependency\n */\n\n// Logger Instance\nexport { logger } from './adapter-factory.js';\n\n// Types\nexport type { LogLevel, LoggerAdapter } from './adapters/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 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 // Debug logging to trace database access\n dbLogger.debug(`getDatabase() called with type=${type}, writeInstance=${!!writeInst}, readInstance=${!!readInst}`);\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 *\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';\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 * Used by ErrorHandler middleware for all error responses.\n * Compatible with ApiResponse pattern for consistent API responses.\n */\nexport interface ErrorResponse\n{\n success: false;\n error: {\n message: string;\n type: string;\n statusCode: number;\n stack?: string;\n details?: any;\n };\n}\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 errorLogger[logLevel]('Error occurred', {\n type: errorType,\n message: err.message,\n statusCode,\n path: c.req.path,\n method: c.req.method,\n });\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 logLevel = status >= 400 ? 'warn' : 'info';\n const isSlowRequest = duration >= cfg.slowRequestThreshold;\n\n const logData: Record<string, any> = {\n requestId,\n method,\n path,\n status,\n duration,\n };\n\n if (isSlowRequest)\n {\n logData.slow = true;\n }\n\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}","/**\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?.beforeRoutes)\n {\n return;\n }\n\n try\n {\n await config.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?.afterRoutes)\n {\n return;\n }\n\n try\n {\n await config.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);\n const shutdown = createGracefulShutdown(shutdownServer, finalConfig);\n\n registerShutdownHandlers(shutdown);\n\n return {\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 catch (error)\n {\n const err = error as Error;\n serverLogger.error('Server initialization failed', err);\n\n await cleanupOnFailure();\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 serverLogger.debug('Initializing database...');\n await initDatabase(config.database);\n\n serverLogger.debug('Initializing Redis...');\n await initRedis();\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): () => 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 serverLogger.debug('Closing database connections...');\n await closeDatabase();\n\n serverLogger.debug('Closing Redis connections...');\n await closeRedis();\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 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(): Promise<void>\n{\n try\n {\n serverLogger.debug('Cleaning up after initialization failure...');\n await closeDatabase();\n await closeRedis();\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}"]}