@spfn/core 0.2.0-beta.32 → 0.2.0-beta.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/event/sse/client.d.ts +1 -1
- package/dist/event/sse/index.d.ts +2 -2
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/{types-DAVwA-_7.d.ts → types-BUmrohqx.d.ts} +24 -0
- package/docs/database.md +24 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { E as EventRouterDef, I as InferEventNames } from '../../router-Di7ENoah.js';
|
|
2
|
-
import { k as SSESubscribeOptions, m as SSEUnsubscribe, l as SSEConnectionState, h as SSEClientConfig } from '../../types-
|
|
2
|
+
import { k as SSESubscribeOptions, m as SSEUnsubscribe, l as SSEConnectionState, h as SSEClientConfig } from '../../types-BUmrohqx.js';
|
|
3
3
|
import '@sinclair/typebox';
|
|
4
4
|
import 'hono';
|
|
5
5
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context } from 'hono';
|
|
2
2
|
import { E as EventRouterDef } from '../../router-Di7ENoah.js';
|
|
3
|
-
import { S as SSEHandlerConfig, b as SSETokenManager } from '../../types-
|
|
4
|
-
export { C as CacheTokenStore, a as SSEAuthConfig, h as SSEClientConfig, l as SSEConnectionState, i as SSEEventHandler, j as SSEEventHandlers, g as SSEHandlerAuthConfig, f as SSEMessage, k as SSESubscribeOptions, c as SSEToken, e as SSETokenManagerConfig, d as SSETokenStore, m as SSEUnsubscribe } from '../../types-
|
|
3
|
+
import { S as SSEHandlerConfig, b as SSETokenManager } from '../../types-BUmrohqx.js';
|
|
4
|
+
export { C as CacheTokenStore, a as SSEAuthConfig, h as SSEClientConfig, l as SSEConnectionState, i as SSEEventHandler, j as SSEEventHandlers, g as SSEHandlerAuthConfig, f as SSEMessage, k as SSESubscribeOptions, c as SSEToken, e as SSETokenManagerConfig, d as SSETokenStore, m as SSEUnsubscribe } from '../../types-BUmrohqx.js';
|
|
5
5
|
import '@sinclair/typebox';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/server/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { NamedMiddleware, Router } from '@spfn/core/route';
|
|
|
6
6
|
import { OnErrorContext } from '@spfn/core/middleware';
|
|
7
7
|
import { J as JobRouter, B as BossOptions } from '../boss-DI1r4kTS.js';
|
|
8
8
|
import { E as EventRouterDef } from '../router-Di7ENoah.js';
|
|
9
|
-
import { S as SSEHandlerConfig, a as SSEAuthConfig } from '../types-
|
|
9
|
+
import { S as SSEHandlerConfig, a as SSEAuthConfig } from '../types-BUmrohqx.js';
|
|
10
10
|
import '@sinclair/typebox';
|
|
11
11
|
import 'pg-boss';
|
|
12
12
|
|
package/dist/server/index.js
CHANGED
|
@@ -1095,7 +1095,8 @@ async function registerSSEEndpoint(app, config) {
|
|
|
1095
1095
|
} catch {
|
|
1096
1096
|
}
|
|
1097
1097
|
}
|
|
1098
|
-
|
|
1098
|
+
const externalManager = typeof authConfig.tokenManager === "function" ? authConfig.tokenManager() : authConfig.tokenManager;
|
|
1099
|
+
tokenManager = externalManager ?? new SSETokenManager({
|
|
1099
1100
|
ttl: authConfig.tokenTtl,
|
|
1100
1101
|
store
|
|
1101
1102
|
});
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/logger/formatters.ts","../../src/env/loader.ts","../../src/server/dotenv-loader.ts","../../src/event/sse/handler.ts","../../src/event/sse/token-manager.ts","../../src/server/logger.ts","../../src/server/shutdown-manager.ts","../../src/server/helpers.ts","../../src/server/create-server.ts","../../src/job/boss.ts","../../src/job/job-router.ts","../../src/job/register-jobs.ts","../../src/server/banner.ts","../../src/server/validation.ts","../../src/server/start-server.ts","../../src/server/config-builder.ts"],"names":["logger","resolve","existsSync","getCache","instance","jobLogger","job","join","env","infraConfig","getDatabase","formatUnhandledRejection","cors"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Logger Formatters\n *\n * Log formatting utilities for console and JSON 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 * Circular reference를 안전하게 처리\n *\n * @param data - 원본 데이터\n * @param seen - 순환 참조 감지용 WeakSet (내부 사용)\n * @returns 마스킹된 데이터\n */\nexport function maskSensitiveData(data: unknown, seen = new WeakSet<object>()): unknown\n{\n // null, undefined 처리\n if (data === null || data === undefined)\n {\n return data;\n }\n\n // 기본 타입은 그대로 반환\n if (typeof data !== 'object')\n {\n return data;\n }\n\n // Circular reference 감지\n if (seen.has(data as object))\n {\n return '[Circular]';\n }\n seen.add(data as object);\n\n // 배열 처리\n if (Array.isArray(data))\n {\n return data.map(item => maskSensitiveData(item, seen));\n }\n\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 // 중첩된 객체는 재귀 처리 (seen 전달)\n masked[key] = maskSensitiveData(value, seen);\n }\n else\n {\n // 일반 값은 그대로 유지\n masked[key] = value;\n }\n }\n\n return masked;\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 // [pid=12345]\n const pid = process.pid;\n if (colorize)\n {\n parts.push(`${COLORS.dim}[pid=${pid}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[pid=${pid}]`);\n }\n\n // [module=value]\n if (metadata.module)\n {\n if (colorize)\n {\n parts.push(`${COLORS.dim}[module=${metadata.module}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[module=${metadata.module}]`);\n }\n }\n\n // Context를 각각 [key=value] 형태로 추가\n if (metadata.context && Object.keys(metadata.context).length > 0)\n {\n Object.entries(metadata.context).forEach(([key, value]) =>\n {\n let valueStr: string;\n if (typeof value === 'string')\n {\n valueStr = value;\n }\n else if (typeof value === 'object' && value !== null)\n {\n try\n {\n valueStr = JSON.stringify(value);\n }\n catch (error)\n {\n valueStr = '[circular]';\n }\n }\n else\n {\n valueStr = String(value);\n }\n\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Drizzle ORM 에러에서 쿼리 정보 추출\n *\n * Drizzle ORM은 에러 메시지에 다음 형식으로 정보를 포함:\n * - \"Failed query: <QUERY>\\nparams: <PARAMS>\"\n * - \"Query: <QUERY>\"\n *\n * @param error - Error 객체\n * @returns 쿼리 정보 (query, params, table)\n */\nexport function extractQueryInfo(error: Error): {\n query?: string;\n params?: unknown;\n table?: string;\n} | null\n{\n const message = error.message;\n\n if (!message) return null;\n\n const result: {\n query?: string;\n params?: unknown;\n table?: string;\n } = {};\n\n // Extract query from \"Failed query: ...\" or \"Query: ...\"\n const queryMatch = message.match(/(?:Failed query:|Query:)\\s*([^\\n]+)/);\n if (queryMatch)\n {\n result.query = queryMatch[1].trim();\n\n // Extract table name from query (e.g., UPDATE \"table_name\" or INSERT INTO \"table_name\")\n const tableMatch = result.query.match(/(?:UPDATE|INSERT INTO|DELETE FROM|FROM)\\s+\"?([a-zA-Z_][a-zA-Z0-9_]*)\"?\\.\"?([a-zA-Z_][a-zA-Z0-9_]*)\"?|(?:UPDATE|INSERT INTO|DELETE FROM|FROM)\\s+\"?([a-zA-Z_][a-zA-Z0-9_]*)\"?/i);\n if (tableMatch)\n {\n // Schema.Table or just Table\n result.table = tableMatch[2] || tableMatch[3] || tableMatch[1];\n }\n }\n\n // Extract params from \"params: ...\"\n const paramsMatch = message.match(/params:\\s*(.+?)(?:\\n|$)/);\n if (paramsMatch)\n {\n const paramsStr = paramsMatch[1].trim();\n try\n {\n // Try to parse as comma-separated values\n result.params = paramsStr.split(',').map(p => p.trim());\n }\n catch (e)\n {\n result.params = paramsStr;\n }\n }\n\n return Object.keys(result).length > 0 ? result : null;\n}\n\n/**\n * Promise rejection의 호출 스택에서 실제 발생 위치 추출\n *\n * 스택 트레이스에서 다음 정보를 추출:\n * - 실제 에러 발생 파일 경로\n * - 라인 번호\n * - 함수명/메서드명\n * - Repository 정보 (있는 경우)\n *\n * @param error - Error 객체\n * @returns Promise context 정보\n */\nexport function extractPromiseContext(error: Error): Record<string, unknown>\n{\n const context: Record<string, unknown> = {};\n\n if (!error.stack) return context;\n\n const stackLines = error.stack.split('\\n');\n\n // Skip first line (error message) and find first meaningful stack frame\n // Ignore node_modules and internal Node.js paths\n for (let i = 1; i < stackLines.length; i++)\n {\n const line = stackLines[i].trim();\n\n // Skip node_modules and node internals\n if (line.includes('node_modules') || line.includes('node:internal')) continue;\n\n // Extract file, line number, and function name\n // Format: \"at ClassName.methodName (file.ts:line:col)\"\n // or: \"at functionName (file.ts:line:col)\"\n // or: \"at file.ts:line:col\"\n\n const match = line.match(/at\\s+(?:([a-zA-Z_$][\\w$]*(?:\\.[a-zA-Z_$][\\w$]*)*)\\s+)?\\(?([^)]+):(\\d+):(\\d+)\\)?/);\n\n if (match)\n {\n const [, functionName, filePath, lineNumber, columnNumber] = match;\n\n // Extract just the filename from the full path\n const fileNameMatch = filePath.match(/([^/\\\\]+)$/);\n const fileName = fileNameMatch ? fileNameMatch[1] : filePath;\n\n context.file = fileName;\n context.line = parseInt(lineNumber, 10);\n context.column = parseInt(columnNumber, 10);\n\n if (functionName)\n {\n // Check if it's a class method (e.g., \"ClassName.methodName\")\n const methodMatch = functionName.match(/^(.+)\\.([^.]+)$/);\n if (methodMatch)\n {\n const [, className, methodName] = methodMatch;\n\n context.class = className;\n context.method = methodName;\n\n // Check if it's a Repository\n if (className.includes('Repository'))\n {\n context.repository = className;\n }\n }\n else\n {\n context.function = functionName;\n }\n }\n\n // Found first relevant frame, stop here\n break;\n }\n }\n\n return context;\n}\n\n/**\n * Unhandled rejection 에러를 상세하게 포맷팅\n *\n * Promise context와 DB 쿼리 정보를 자동으로 추출하여\n * 에러 발생 위치와 원인을 명확하게 파악할 수 있도록 함\n *\n * @param reason - Rejection 원인 (Error 또는 기타)\n * @param promise - Promise 객체\n * @returns 상세 context 정보\n */\nexport function formatUnhandledRejection(reason: unknown, promise: Promise<unknown>): {\n error: Error;\n context: Record<string, unknown>;\n}\n{\n // Convert reason to Error if not already\n let error: Error;\n if (reason instanceof Error)\n {\n error = reason;\n }\n else if (typeof reason === 'string')\n {\n error = new Error(reason);\n }\n else\n {\n error = new Error(JSON.stringify(reason));\n }\n\n const context: Record<string, unknown> = {\n promise: String(promise),\n };\n\n // Extract promise context (file, line, function, etc.)\n const promiseContext = extractPromiseContext(error);\n if (Object.keys(promiseContext).length > 0)\n {\n context.promiseContext = promiseContext;\n }\n\n // Extract DB query info if available\n const queryInfo = extractQueryInfo(error);\n if (queryInfo)\n {\n context.queryInfo = queryInfo;\n }\n\n return { error, context };\n}","/**\n * Environment Variable Loader\n *\n * Next.js 스타일의 환경변수 파일 로딩 (환경별 분리 지원)\n *\n * 로딩 우선순위 (낮음 -> 높음, 나중 파일이 덮어씀):\n * 1. .env - 기본값 (committed)\n * 2. .env.{NODE_ENV} - 환경별 오버라이드 (committed)\n * 3. .env.local - 로컬 오버라이드 (gitignored, test에서 스킵)\n * 4. .env.{NODE_ENV}.local - 환경별 시크릿 (gitignored)\n * 5. .env.server - 서버 전용 기본값 (committed)\n * 6. .env.server.local - 서버 전용 시크릿 (gitignored)\n *\n * @example\n * ```typescript\n * import { loadEnv } from '@spfn/core/env/loader';\n *\n * // 기본 사용 (NODE_ENV 자동 감지)\n * loadEnv();\n *\n * // 특정 환경 지정\n * loadEnv({ nodeEnv: 'production' });\n *\n * // 서버 레이어 제외 (Next.js 클라이언트용)\n * loadEnv({ server: false });\n * ```\n *\n * @module env/loader\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { parse } from 'dotenv';\nimport { logger } from '@spfn/core/logger';\n\nconst envLogger = logger.child('@spfn/core:env-loader');\n\n/**\n * loadEnv 옵션\n */\nexport interface LoadEnvOptions\n{\n /**\n * 프로젝트 루트 경로\n * @default process.cwd()\n */\n cwd?: string;\n\n /**\n * NODE_ENV 값 (환경별 .env 파일 결정)\n * @default process.env.NODE_ENV || 'local'\n */\n nodeEnv?: string;\n\n /**\n * 서버 전용 파일 포함 여부 (.env.server, .env.server.local)\n * @default true\n */\n server?: boolean;\n\n /**\n * 디버그 모드 (로드된 파일 로깅)\n * @default false\n */\n debug?: boolean;\n\n /**\n * 기존 process.env 값 덮어쓰기 허용\n * @default false\n */\n override?: boolean;\n}\n\n/**\n * 환경변수 로드 결과\n */\nexport interface LoadEnvResult\n{\n /**\n * 로드된 파일 목록\n */\n loadedFiles: string[];\n\n /**\n * 로드된 환경변수 키 목록\n */\n loadedKeys: string[];\n}\n\n/**\n * NODE_ENV에 따른 .env 파일 목록 생성 (우선순위 낮음 -> 높음)\n *\n * 더 구체적인 파일이 승리:\n * - environment > base\n * - server > shared\n * - local > committed\n */\nfunction getEnvFiles(nodeEnv: string, server: boolean): string[]\n{\n const files: string[] = [\n '.env',\n `.env.${nodeEnv}`,\n ];\n\n // test 환경에서는 .env.local 스킵 (테스트 결정론성 보장)\n if (nodeEnv !== 'test')\n {\n files.push('.env.local');\n }\n\n files.push(`.env.${nodeEnv}.local`);\n\n if (server)\n {\n files.push('.env.server');\n files.push('.env.server.local');\n }\n\n return files;\n}\n\n/**\n * 단일 .env 파일 파싱\n */\nfunction parseEnvFile(filePath: string): Record<string, string> | null\n{\n if (!existsSync(filePath))\n {\n return null;\n }\n\n return parse(readFileSync(filePath, 'utf-8'));\n}\n\n/**\n * 프로젝트 루트의 환경변수 파일들을 규칙에 따라 로드\n *\n * 모든 파일을 파싱 후 머지한 뒤 process.env에 한번에 적용.\n * 이미 process.env에 존재하는 키는 덮어쓰지 않음 (플랫폼 주입 보호).\n *\n * @param options - 로드 옵션\n * @returns 로드 결과 (로드된 파일, 키 목록)\n */\nexport function loadEnv(options: LoadEnvOptions = {}): LoadEnvResult\n{\n const {\n cwd = process.cwd(),\n nodeEnv = process.env.NODE_ENV || 'local',\n server = true,\n debug = false,\n override = false,\n } = options;\n\n const envFiles = getEnvFiles(nodeEnv, server);\n const loadedFiles: string[] = [];\n\n // 1) 기존 process.env 키 스냅샷 저장\n const existingKeys = new Set(Object.keys(process.env));\n\n // 2) 모든 .env 파일 파싱 후 머지 (나중 파일이 승리)\n const merged: Record<string, string> = {};\n\n for (const fileName of envFiles)\n {\n const filePath = resolve(cwd, fileName);\n const parsed = parseEnvFile(filePath);\n\n if (parsed === null)\n {\n continue;\n }\n\n loadedFiles.push(fileName);\n Object.assign(merged, parsed);\n }\n\n // 3) 머지된 결과를 process.env에 적용\n const loadedKeys: string[] = [];\n\n for (const [key, value] of Object.entries(merged))\n {\n // 기존 process.env에 이미 있는 키는 스킵 (override가 false일 때)\n if (!override && existingKeys.has(key))\n {\n continue;\n }\n\n process.env[key] = value;\n loadedKeys.push(key);\n }\n\n if (debug && loadedFiles.length > 0)\n {\n envLogger.debug(`Loaded env files: ${loadedFiles.join(', ')}`);\n envLogger.debug(`Loaded ${loadedKeys.length} environment variables`);\n }\n\n return { loadedFiles, loadedKeys };\n}\n\n/**\n * 환경변수가 이미 로드되었는지 확인하는 플래그\n */\nlet isEnvLoaded = false;\n\n/**\n * 환경변수를 한 번만 로드 (중복 호출 방지)\n *\n * @param options - 로드 옵션\n * @returns 로드 결과 (이미 로드된 경우 빈 결과)\n */\nexport function loadEnvOnce(options: LoadEnvOptions = {}): LoadEnvResult\n{\n if (isEnvLoaded)\n {\n return { loadedFiles: [], loadedKeys: [] };\n }\n\n isEnvLoaded = true;\n return loadEnv(options);\n}\n\n/**\n * 환경변수 로드 상태 리셋 (테스트용)\n */\nexport function resetEnvLoadState(): void\n{\n isEnvLoaded = false;\n}\n","/**\n * @deprecated Use `loadEnv` from '@spfn/core/env/loader' instead.\n * This module will be removed in the next major version.\n */\n\nimport { loadEnv } from '../env/loader';\n\nlet warned = false;\n\n/**\n * @deprecated Use `loadEnv()` from '@spfn/core/env/loader' instead.\n */\nexport function loadEnvFiles(): void\n{\n if (!warned)\n {\n warned = true;\n console.warn(\n '[SPFN] loadEnvFiles() is deprecated. Use loadEnv() from \"@spfn/core/env/loader\" instead.'\n );\n }\n\n loadEnv();\n}\n","/**\n * SSE Handler for Hono\n *\n * Creates SSE stream endpoint for event subscription\n *\n * @example\n * ```typescript\n * import { Hono } from 'hono';\n * import { createSSEHandler } from '@spfn/core/event/sse';\n * import { eventRouter } from './events';\n *\n * const app = new Hono();\n *\n * // GET /events/stream?events=userCreated,orderPlaced\n * app.get('/events/stream', createSSEHandler(eventRouter));\n * ```\n */\n\nimport type { Context } from 'hono';\nimport { streamSSE } from 'hono/streaming';\nimport { logger } from '@spfn/core/logger';\nimport type { EventRouterDef, InferEventNames } from '../router';\nimport type { SSEHandlerConfig, SSEHandlerAuthConfig } from './types';\nimport type { SSETokenManager } from './token-manager';\n\nconst sseLogger = logger.child('@spfn/core:sse');\n\n// Extend Hono context with SSE subject\ndeclare module 'hono'\n{\n interface ContextVariableMap\n {\n sseSubject?: string;\n }\n}\n\n/**\n * Create SSE handler for Hono\n *\n * Query parameters:\n * - events: Comma-separated list of event names to subscribe\n * - token: One-time auth token (when auth is enabled)\n *\n * @example\n * ```typescript\n * app.get('/events/stream', createSSEHandler(eventRouter, {\n * pingInterval: 30000,\n * }));\n * ```\n */\nexport function createSSEHandler<TRouter extends EventRouterDef<any>>(\n router: TRouter,\n config: SSEHandlerConfig = {},\n tokenManager?: SSETokenManager\n)\n{\n const {\n pingInterval = 30000,\n auth: authConfig,\n } = config;\n\n return async (c: Context) =>\n {\n // ── 1. Token Authentication ──\n const subject = await authenticateToken(c, tokenManager);\n if (subject === false)\n {\n return c.json({ error: 'Missing token parameter' }, 401);\n }\n if (subject === null)\n {\n return c.json({ error: 'Invalid or expired token' }, 401);\n }\n if (subject)\n {\n c.set('sseSubject', subject);\n }\n\n // ── 2. Parse events from query parameter ──\n const requestedEvents = parseRequestedEvents(c);\n if (!requestedEvents)\n {\n return c.json({ error: 'Missing events parameter' }, 400);\n }\n\n // ── 3. Validate event names ──\n const validEventNames = router.eventNames as string[];\n const invalidEvents = requestedEvents.filter(e => !validEventNames.includes(e));\n\n if (invalidEvents.length > 0)\n {\n return c.json({\n error: 'Invalid event names',\n invalidEvents,\n validEvents: validEventNames,\n }, 400);\n }\n\n // ── 4. Subscription Authorization ──\n const allowedEvents = await authorizeEvents(subject, requestedEvents, authConfig);\n if (allowedEvents === null)\n {\n return c.json({ error: 'Not authorized for any requested events' }, 403);\n }\n\n sseLogger.debug('SSE connection requested', {\n events: allowedEvents,\n subject: subject || undefined,\n clientIp: c.req.header('x-forwarded-for') || c.req.header('x-real-ip'),\n });\n\n // ── 5. SSE Stream ──\n return streamSSE(c, async (stream) =>\n {\n const unsubscribes: (() => void)[] = [];\n let messageId = 0;\n\n for (const eventName of allowedEvents as InferEventNames<TRouter>[])\n {\n const eventDef = router.events[eventName];\n\n if (!eventDef)\n {\n continue;\n }\n\n const unsubscribe = eventDef.subscribe((payload: unknown) =>\n {\n // ── Payload Filtering ──\n if (subject && authConfig?.filter?.[eventName as string])\n {\n if (!authConfig.filter[eventName as string](subject, payload))\n {\n return;\n }\n }\n\n messageId++;\n\n const message = {\n event: eventName,\n data: payload,\n };\n\n sseLogger.debug('SSE sending event', {\n event: eventName,\n messageId,\n });\n\n // Fire-and-forget in sync callback\n void stream.writeSSE({\n id: String(messageId),\n event: eventName as string,\n data: JSON.stringify(message),\n });\n });\n\n unsubscribes.push(unsubscribe);\n }\n\n sseLogger.info('SSE connection established', {\n events: allowedEvents,\n subscriptionCount: unsubscribes.length,\n });\n\n // Send initial connection message\n await stream.writeSSE({\n event: 'connected',\n data: JSON.stringify({\n subscribedEvents: allowedEvents,\n timestamp: Date.now(),\n }),\n });\n\n // Keep-alive ping\n const pingTimer = setInterval(() =>\n {\n // Fire-and-forget in sync callback\n void stream.writeSSE({\n event: 'ping',\n data: JSON.stringify({ timestamp: Date.now() }),\n });\n }, pingInterval);\n\n // Wait for client disconnect using abort signal\n const abortSignal = c.req.raw.signal;\n\n while (!abortSignal.aborted)\n {\n await stream.sleep(pingInterval);\n }\n\n // Cleanup\n clearInterval(pingTimer);\n unsubscribes.forEach(fn => fn());\n\n sseLogger.info('SSE connection closed', {\n events: allowedEvents,\n });\n }, async (err: Error) =>\n {\n sseLogger.error('SSE stream error', {\n error: err.message,\n });\n });\n };\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Authenticate via one-time token\n * @returns subject string if authenticated, undefined if no auth required,\n * false if token missing, null if token invalid/expired\n */\nasync function authenticateToken(\n c: Context,\n tokenManager?: SSETokenManager\n): Promise<string | undefined | false | null>\n{\n if (!tokenManager)\n {\n return undefined;\n }\n\n const token = c.req.query('token');\n if (!token)\n {\n return false;\n }\n\n return await tokenManager.verify(token);\n}\n\n/**\n * Parse requested events from query parameter\n */\nfunction parseRequestedEvents(c: Context): string[] | null\n{\n const eventsParam = c.req.query('events');\n if (!eventsParam)\n {\n return null;\n }\n\n return eventsParam.split(',').map(e => e.trim());\n}\n\n/**\n * Authorize event subscription via auth hook\n * @returns allowed events array, or null if rejected\n */\nasync function authorizeEvents(\n subject: string | undefined,\n requestedEvents: string[],\n authConfig?: SSEHandlerAuthConfig\n): Promise<string[] | null>\n{\n if (!subject || !authConfig?.authorize)\n {\n return requestedEvents;\n }\n\n const allowed = await authConfig.authorize(subject, requestedEvents);\n\n if (allowed.length === 0)\n {\n return null;\n }\n\n return allowed;\n}\n","/**\n * SSE Token Manager\n *\n * Auth-agnostic token issuance and verification for SSE connections.\n * Issues one-time-use tokens with TTL for Token Exchange pattern.\n *\n * @example\n * ```typescript\n * const manager = new SSETokenManager({ ttl: 30000 });\n *\n * // Issue token for authenticated user\n * const token = await manager.issue('user-123');\n *\n * // Verify and consume token (one-time use)\n * const subject = await manager.verify(token); // 'user-123'\n * const again = await manager.verify(token); // null (already consumed)\n *\n * // Cleanup on shutdown\n * manager.destroy();\n * ```\n */\n\nimport { randomBytes } from 'crypto';\n\n/**\n * Minimal cache client interface (compatible with ioredis Redis | Cluster)\n */\ntype CacheClient = {\n set(key: string, value: string, ...args: any[]): Promise<any>;\n getdel?(key: string): Promise<string | null>;\n get(key: string): Promise<string | null>;\n del(key: string | string[]): Promise<number>;\n};\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Stored SSE token data\n */\nexport interface SSEToken\n{\n token: string;\n subject: string;\n expiresAt: number;\n}\n\n/**\n * Token storage interface\n *\n * Implement this for custom storage backends (e.g., Redis for multi-instance).\n */\nexport interface SSETokenStore\n{\n /** Store a token */\n set(token: string, data: SSEToken): Promise<void>;\n\n /** Get and delete a token (one-time use) */\n consume(token: string): Promise<SSEToken | null>;\n\n /** Remove expired tokens */\n cleanup(): Promise<void>;\n}\n\n/**\n * SSETokenManager configuration\n */\nexport interface SSETokenManagerConfig\n{\n /**\n * Token time-to-live in milliseconds\n * @default 30000\n */\n ttl?: number;\n\n /**\n * Custom token store (default: in-memory Map)\n */\n store?: SSETokenStore;\n\n /**\n * Cleanup interval in milliseconds\n * @default 60000\n */\n cleanupInterval?: number;\n}\n\n// ============================================================================\n// InMemoryTokenStore\n// ============================================================================\n\nclass InMemoryTokenStore implements SSETokenStore\n{\n private tokens = new Map<string, SSEToken>();\n\n async set(token: string, data: SSEToken): Promise<void>\n {\n this.tokens.set(token, data);\n }\n\n async consume(token: string): Promise<SSEToken | null>\n {\n const data = this.tokens.get(token);\n if (!data)\n {\n return null;\n }\n\n this.tokens.delete(token);\n return data;\n }\n\n async cleanup(): Promise<void>\n {\n const now = Date.now();\n\n for (const [token, data] of this.tokens)\n {\n if (data.expiresAt <= now)\n {\n this.tokens.delete(token);\n }\n }\n }\n}\n\n// ============================================================================\n// CacheTokenStore (Redis/Valkey)\n// ============================================================================\n\n/**\n * Redis/Valkey-backed token store for multi-instance deployments.\n *\n * Uses SET EX for automatic TTL expiry and GETDEL for atomic one-time consumption.\n * No cleanup needed — Redis handles expiration automatically.\n *\n * @example\n * ```typescript\n * import { getCache } from '@spfn/core/cache';\n *\n * const cache = getCache();\n * if (cache) {\n * const store = new CacheTokenStore(cache);\n * const manager = new SSETokenManager({ store });\n * }\n * ```\n */\nexport class CacheTokenStore implements SSETokenStore\n{\n private prefix = 'sse:token:';\n\n constructor(private cache: CacheClient) {}\n\n async set(token: string, data: SSEToken): Promise<void>\n {\n const ttlSeconds = Math.max(1, Math.ceil((data.expiresAt - Date.now()) / 1000));\n await this.cache.set(\n this.prefix + token,\n JSON.stringify(data),\n 'EX',\n ttlSeconds,\n );\n }\n\n async consume(token: string): Promise<SSEToken | null>\n {\n const key = this.prefix + token;\n\n // GETDEL (Redis 6.2+) for atomic consume, fallback to GET+DEL\n let raw: string | null = null;\n\n if (this.cache.getdel)\n {\n raw = await this.cache.getdel(key);\n }\n else\n {\n raw = await this.cache.get(key);\n if (raw)\n {\n await this.cache.del(key);\n }\n }\n\n if (!raw)\n {\n return null;\n }\n\n return JSON.parse(raw) as SSEToken;\n }\n\n async cleanup(): Promise<void>\n {\n // No-op: Redis TTL handles expiration automatically\n }\n}\n\n// ============================================================================\n// SSETokenManager\n// ============================================================================\n\nexport class SSETokenManager\n{\n private store: SSETokenStore;\n private ttl: number;\n private cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(config?: SSETokenManagerConfig)\n {\n this.ttl = config?.ttl ?? 30000;\n this.store = config?.store ?? new InMemoryTokenStore();\n\n const cleanupInterval = config?.cleanupInterval ?? 60000;\n this.cleanupTimer = setInterval(() => void this.store.cleanup(), cleanupInterval);\n this.cleanupTimer.unref();\n }\n\n /**\n * Issue a new one-time-use token for the given subject\n */\n async issue(subject: string): Promise<string>\n {\n const token = randomBytes(32).toString('hex');\n\n await this.store.set(token, {\n token,\n subject,\n expiresAt: Date.now() + this.ttl,\n });\n\n return token;\n }\n\n /**\n * Verify and consume a token\n * @returns subject string if valid, null if invalid/expired/already consumed\n */\n async verify(token: string): Promise<string | null>\n {\n const data = await this.store.consume(token);\n\n if (!data || data.expiresAt <= Date.now())\n {\n return null;\n }\n\n return data.subject;\n }\n\n /**\n * Cleanup timer and resources\n */\n destroy(): void\n {\n if (this.cleanupTimer)\n {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n }\n}\n","import { logger } from \"@spfn/core/logger\";\n\nexport const serverLogger = logger.child('@spfn/core:server');","/**\n * Shutdown Manager\n *\n * Manages graceful shutdown with drain behavior.\n * All tracked operations must complete before shutdown proceeds.\n *\n * Features:\n * - Hook registry: Multiple modules can register independent cleanup handlers\n * - Operation tracking: Long-running tasks are awaited during shutdown (drain)\n * - State management: isShuttingDown() for rejecting new work\n */\n\nimport { serverLogger } from './logger';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ShutdownHookOptions\n{\n /**\n * Timeout for this hook in milliseconds\n * If the hook exceeds this time, it is skipped and the next hook runs\n * @default 10000 (10s)\n */\n timeout?: number;\n\n /**\n * Execution order (lower runs first)\n * @default 100\n */\n order?: number;\n}\n\ninterface ShutdownHook\n{\n name: string;\n handler: () => Promise<void>;\n timeout: number;\n order: number;\n}\n\ninterface TrackedOperation\n{\n name: string;\n startedAt: number;\n}\n\ntype ShutdownState = 'running' | 'draining' | 'closed';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_HOOK_TIMEOUT = 10_000;\nconst DEFAULT_HOOK_ORDER = 100;\nconst DRAIN_POLL_INTERVAL = 500;\n\n// ============================================================================\n// ShutdownManager\n// ============================================================================\n\nexport class ShutdownManager\n{\n private state: ShutdownState = 'running';\n private hooks: ShutdownHook[] = [];\n private operations = new Map<string, TrackedOperation>();\n private operationCounter = 0;\n\n /**\n * Register a shutdown hook\n *\n * Hooks run in order during shutdown, after all tracked operations drain.\n * Each hook has its own timeout — failure does not block subsequent hooks.\n *\n * @example\n * shutdown.onShutdown('ai-service', async () => {\n * await aiService.cancelPending();\n * }, { timeout: 30000, order: 10 });\n */\n onShutdown(\n name: string,\n handler: () => Promise<void>,\n options?: ShutdownHookOptions\n ): void\n {\n this.hooks.push({\n name,\n handler,\n timeout: options?.timeout ?? DEFAULT_HOOK_TIMEOUT,\n order: options?.order ?? DEFAULT_HOOK_ORDER,\n });\n\n // Keep sorted by order\n this.hooks.sort((a, b) => a.order - b.order);\n\n serverLogger.debug(`Shutdown hook registered: ${name}`, {\n order: options?.order ?? DEFAULT_HOOK_ORDER,\n timeout: `${options?.timeout ?? DEFAULT_HOOK_TIMEOUT}ms`,\n });\n }\n\n /**\n * Track a long-running operation\n *\n * During shutdown (drain phase), the process waits for ALL tracked\n * operations to complete before proceeding with cleanup.\n *\n * If shutdown has already started, the operation is rejected immediately.\n *\n * @returns The operation result (pass-through)\n *\n * @example\n * const result = await shutdown.trackOperation(\n * 'ai-generate',\n * aiService.generate(prompt)\n * );\n */\n async trackOperation<T>(name: string, operation: Promise<T>): Promise<T>\n {\n if (this.state !== 'running')\n {\n throw new Error(`Cannot start operation '${name}': server is shutting down`);\n }\n\n const id = `${name}-${++this.operationCounter}`;\n\n this.operations.set(id, {\n name,\n startedAt: Date.now(),\n });\n\n serverLogger.debug(`Operation tracked: ${id}`, {\n activeOperations: this.operations.size,\n });\n\n try\n {\n return await operation;\n }\n finally\n {\n this.operations.delete(id);\n\n serverLogger.debug(`Operation completed: ${id}`, {\n activeOperations: this.operations.size,\n });\n }\n }\n\n /**\n * Whether the server is shutting down\n *\n * Use this to reject new work early (e.g., return 503 in route handlers).\n */\n isShuttingDown(): boolean\n {\n return this.state !== 'running';\n }\n\n /**\n * Number of currently active tracked operations\n */\n getActiveOperationCount(): number\n {\n return this.operations.size;\n }\n\n /**\n * Mark shutdown as started immediately\n *\n * Call this at the very beginning of the shutdown sequence so that:\n * - Health check returns 503 right away\n * - trackOperation() rejects new work\n * - isShuttingDown() returns true\n */\n beginShutdown(): void\n {\n if (this.state !== 'running')\n {\n return;\n }\n this.state = 'draining';\n serverLogger.info('Shutdown manager: state set to draining');\n }\n\n /**\n * Execute the full shutdown sequence\n *\n * 1. State → draining (reject new operations)\n * 2. Wait for all tracked operations to complete (drain)\n * 3. Run shutdown hooks in order\n * 4. State → closed\n *\n * @param drainTimeout - Max time to wait for operations to drain (ms)\n */\n async execute(drainTimeout: number): Promise<void>\n {\n // beginShutdown() may have already been called\n if (this.state === 'closed')\n {\n serverLogger.warn('ShutdownManager.execute() called but already closed');\n return;\n }\n\n this.state = 'draining';\n serverLogger.info('Shutdown manager: draining started', {\n activeOperations: this.operations.size,\n registeredHooks: this.hooks.length,\n drainTimeout: `${drainTimeout}ms`,\n });\n\n // Phase 1: Drain — wait for all tracked operations to complete\n await this.drain(drainTimeout);\n\n // Phase 2: Run shutdown hooks in order\n await this.executeHooks();\n\n this.state = 'closed';\n serverLogger.info('Shutdown manager: all hooks executed');\n }\n\n // ========================================================================\n // Private\n // ========================================================================\n\n /**\n * Wait for all tracked operations to complete, up to drainTimeout\n */\n private async drain(drainTimeout: number): Promise<void>\n {\n if (this.operations.size === 0)\n {\n serverLogger.info('Shutdown manager: no active operations, drain skipped');\n return;\n }\n\n serverLogger.info(`Shutdown manager: waiting for ${this.operations.size} operations to drain...`);\n\n const deadline = Date.now() + drainTimeout;\n\n while (this.operations.size > 0 && Date.now() < deadline)\n {\n const remaining = deadline - Date.now();\n const ops = Array.from(this.operations.values()).map(op => ({\n name: op.name,\n elapsed: `${Math.round((Date.now() - op.startedAt) / 1000)}s`,\n }));\n\n serverLogger.info('Shutdown manager: drain in progress', {\n activeOperations: this.operations.size,\n remainingTimeout: `${Math.round(remaining / 1000)}s`,\n operations: ops,\n });\n\n await sleep(Math.min(DRAIN_POLL_INTERVAL, remaining));\n }\n\n if (this.operations.size > 0)\n {\n const abandoned = Array.from(this.operations.values()).map(op => op.name);\n serverLogger.warn('Shutdown manager: drain timeout — abandoning operations', {\n abandoned,\n });\n }\n else\n {\n serverLogger.info('Shutdown manager: all operations drained successfully');\n }\n }\n\n /**\n * Execute registered shutdown hooks in order\n */\n private async executeHooks(): Promise<void>\n {\n if (this.hooks.length === 0)\n {\n return;\n }\n\n serverLogger.info(`Shutdown manager: executing ${this.hooks.length} hooks...`);\n\n for (const hook of this.hooks)\n {\n serverLogger.debug(`Shutdown hook [${hook.name}] starting (timeout: ${hook.timeout}ms)`);\n\n try\n {\n await withTimeout(\n hook.handler(),\n hook.timeout,\n `Shutdown hook '${hook.name}' timeout after ${hook.timeout}ms`\n );\n serverLogger.info(`Shutdown hook [${hook.name}] completed`);\n }\n catch (error)\n {\n serverLogger.error(\n `Shutdown hook [${hook.name}] failed`,\n error as Error\n );\n // Continue with next hook — don't block shutdown\n }\n }\n }\n}\n\n// ============================================================================\n// Singleton\n// ============================================================================\n\nlet instance: ShutdownManager | null = null;\n\n/**\n * Get the global ShutdownManager instance\n *\n * Available after server starts. Use this to register shutdown hooks\n * or track long-running operations.\n *\n * @example\n * import { getShutdownManager } from '@spfn/core/server';\n *\n * const shutdown = getShutdownManager();\n *\n * // Register cleanup\n * shutdown.onShutdown('my-service', async () => {\n * await myService.close();\n * });\n *\n * // Track long operation\n * await shutdown.trackOperation('ai-task', longRunningPromise);\n */\nexport function getShutdownManager(): ShutdownManager\n{\n if (!instance)\n {\n instance = new ShutdownManager();\n }\n return instance;\n}\n\n/**\n * Reset the singleton (for testing)\n * @internal\n */\nexport function resetShutdownManager(): void\n{\n instance = null;\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void>\n{\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeout: number,\n message: string\n): Promise<T>\n{\n let timeoutId: NodeJS.Timeout | undefined;\n\n return Promise.race([\n promise.finally(() =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n }),\n new Promise<never>((_, reject) =>\n {\n timeoutId = setTimeout(() =>\n {\n reject(new Error(message));\n }, timeout);\n }),\n ]);\n}\n","import type { Hono, Handler, MiddlewareHandler } from 'hono';\nimport type { Server } from 'http';\nimport { Agent, setGlobalDispatcher } from 'undici';\nimport { getDatabase } from '@spfn/core/db';\nimport { getCache } from '@spfn/core/cache';\nimport { env } from '@spfn/core/config';\nimport { getShutdownManager } from './shutdown-manager';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface ServiceStatus\n{\n status: string;\n error?: string;\n}\n\ninterface HealthCheckResponse\n{\n status: 'ok' | 'degraded';\n timestamp: string;\n services?: {\n database: ServiceStatus;\n redis: ServiceStatus;\n };\n}\n\ninterface StartupConfig\n{\n middleware: {\n logger: boolean;\n cors: boolean;\n errorHandler: boolean;\n custom: number;\n };\n healthCheck: {\n enabled: boolean;\n path?: string;\n detailed?: boolean;\n };\n hooks: {\n beforeRoutes: boolean;\n afterRoutes: boolean;\n };\n timeout: {\n request: string;\n keepAlive: string;\n headers: string;\n };\n shutdown: {\n timeout: string;\n };\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\nexport function createHealthCheckHandler(detailed: boolean): Handler\n{\n return async (c) =>\n {\n // Return 503 immediately during shutdown (for k8s readiness probe)\n const shutdownManager = getShutdownManager();\n if (shutdownManager.isShuttingDown())\n {\n return c.json({\n status: 'shutting_down',\n timestamp: new Date().toISOString(),\n }, 503);\n }\n\n const response: HealthCheckResponse = {\n status: 'ok',\n timestamp: new Date().toISOString(),\n };\n\n if (detailed)\n {\n let dbStatus: string = 'unknown';\n let dbError: string | undefined;\n\n // Try to get database instance\n try\n {\n const db = getDatabase();\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 catch (error)\n {\n // Database not initialized\n dbStatus = 'not_initialized';\n dbError = 'Database not available';\n }\n\n const redis = getCache();\n let redisStatus: string = redis ? 'unknown' : 'not_initialized';\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 =\n (dbStatus === 'error' || dbStatus === 'not_initialized') ||\n (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 ?? env.SERVER_TIMEOUT,\n keepAlive: config?.keepAlive ?? env.SERVER_KEEPALIVE_TIMEOUT,\n headers: config?.headers ?? env.SERVER_HEADERS_TIMEOUT,\n };\n}\n\nexport function getShutdownTimeout(config?: { timeout?: number }): number\n{\n return config?.timeout ?? env.SHUTDOWN_TIMEOUT;\n}\n\nexport function getFetchTimeoutConfig(config?: {\n connect?: number;\n headers?: number;\n body?: number;\n}): {\n connect: number;\n headers: number;\n body: number;\n}\n{\n return {\n connect: config?.connect ?? env.FETCH_CONNECT_TIMEOUT,\n headers: config?.headers ?? env.FETCH_HEADERS_TIMEOUT,\n body: config?.body ?? env.FETCH_BODY_TIMEOUT,\n };\n}\n\nexport function applyGlobalFetchTimeouts(timeouts: {\n connect: number;\n headers: number;\n body: number;\n}): void\n{\n const agent = new Agent({\n connect: { timeout: timeouts.connect },\n headersTimeout: timeouts.headers,\n bodyTimeout: timeouts.body,\n });\n setGlobalDispatcher(agent);\n}\n\nexport function buildMiddlewareOrder(config: {\n middleware?: {\n logger?: boolean;\n cors?: boolean;\n errorHandler?: boolean;\n };\n use?: MiddlewareHandler[];\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?: MiddlewareHandler[];\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): StartupConfig\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 ?? (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 ?? env.SHUTDOWN_TIMEOUT}ms`,\n },\n };\n}\n","/**\n * Create Hono Server\n *\n * Creates and configures a Hono application instance.\n */\n\nimport { Hono, type Context } from 'hono';\nimport { cors } from 'hono/cors';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\n\nimport { registerRoutes, type RegisteredRoute } from '@spfn/core/route';\nimport { ErrorHandler, RequestLogger } from '@spfn/core/middleware';\nimport { createSSEHandler } from '../event/sse/handler';\nimport { SSETokenManager, CacheTokenStore } from '../event/sse/token-manager';\nimport { createHealthCheckHandler } from './helpers';\nimport { serverLogger } from './logger';\n\nimport type { ServerConfig, AppFactory } from './types';\n\n// Extend Hono context with error handler flag\ndeclare module 'hono'\n{\n interface ContextVariableMap\n {\n errorHandlerEnabled?: boolean;\n }\n}\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');\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 // Determine which path exists to avoid duplicate checks\n const actualPath = existsSync(appPath) ? appPath : appJsPath;\n const appModule = await import(actualPath);\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 // Register routes (if provided via config)\n if (config?.routes)\n {\n const routes = registerRoutes(app, config.routes, config.middlewares);\n logRegisteredRoutes(routes, config?.debug ?? false);\n }\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 if (Array.isArray(config?.use))\n {\n config.use.forEach(mw => app.use('*', mw));\n }\n\n // 4. Health check endpoint\n registerHealthCheckEndpoint(app, config);\n\n // 5. beforeRoutes hook from config\n await executeBeforeRoutesHook(app, config);\n\n // 6. Load routes\n await loadAppRoutes(app, config);\n\n // 7. Register SSE endpoint (if events router provided)\n await registerSSEEndpoint(app, config);\n\n // 8. afterRoutes hook from config\n await executeAfterRoutesHook(app, config);\n\n // 9. Error handler\n if (enableErrorHandler)\n {\n app.onError(ErrorHandler({ onError: config?.middleware?.onError }));\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)\n {\n // Only apply cors if config.cors is not explicitly false\n // This handles both config.cors = undefined and config.cors = {...options}\n const corsOptions = config?.cors !== false ? config?.cors : undefined;\n app.use('*', cors(corsOptions));\n }\n}\n\nfunction registerHealthCheckEndpoint(app: Hono, config?: ServerConfig): void\n{\n const healthCheckConfig = config?.healthCheck ?? {};\n const healthCheckEnabled = healthCheckConfig.enabled !== false;\n const healthCheckPath = healthCheckConfig.path ?? '/health';\n const healthCheckDetailed = healthCheckConfig.detailed\n ?? process.env.NODE_ENV === 'development';\n\n if (healthCheckEnabled)\n {\n app.get(healthCheckPath, createHealthCheckHandler(healthCheckDetailed));\n serverLogger.debug(`Health check endpoint enabled at ${healthCheckPath}`);\n }\n}\n\nasync function executeBeforeRoutesHook(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (config?.lifecycle?.beforeRoutes)\n {\n await config.lifecycle.beforeRoutes(app);\n }\n}\n\nasync function loadAppRoutes(app: Hono, config?: ServerConfig): Promise<void>\n{\n const debug = isDebugMode(config);\n\n // Register define-route based routes (if provided)\n if (config?.routes)\n {\n const routes = registerRoutes(app, config.routes, config.middlewares);\n logRegisteredRoutes(routes, debug);\n }\n else if (debug)\n {\n serverLogger.warn('⚠️ No routes configured. Use defineServerConfig().routes() to register routes.');\n }\n}\n\n/**\n * Log registered routes in a formatted table\n */\nfunction logRegisteredRoutes(routes: RegisteredRoute[], debug: boolean): void\n{\n if (routes.length === 0)\n {\n if (debug)\n {\n serverLogger.warn('⚠️ No routes registered');\n }\n return;\n }\n\n // Sort routes by path for better readability\n const sortedRoutes = [...routes].sort((a, b) => a.path.localeCompare(b.path));\n\n // Calculate max method length for alignment\n const maxMethodLen = Math.max(...sortedRoutes.map(r => r.method.length));\n\n // Build route list string\n const routeLines = sortedRoutes.map(r =>\n ` ${r.method.padEnd(maxMethodLen)} ${r.path}`\n ).join('\\n');\n\n serverLogger.info(`✓ Routes registered (${routes.length}):\\n${routeLines}`);\n}\n\nasync function executeAfterRoutesHook(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (config?.lifecycle?.afterRoutes)\n {\n await config.lifecycle.afterRoutes(app);\n }\n}\n\n/**\n * Register SSE endpoint for event streaming\n *\n * When auth is enabled:\n * - POST /events/token — issues one-time SSE token (protected by config.middlewares)\n * - GET /events/stream?token=...&events=... — SSE stream (token verified)\n */\nasync function registerSSEEndpoint(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (!config?.events)\n {\n return;\n }\n\n const eventsConfig = config.eventsConfig ?? {};\n const streamPath = eventsConfig.path ?? '/events/stream';\n const authConfig = eventsConfig.auth;\n const debug = isDebugMode(config);\n\n let tokenManager: SSETokenManager | undefined;\n\n if (authConfig?.enabled)\n {\n // Auto-detect cache for token store (multi-instance support)\n let store = authConfig.store;\n if (!store)\n {\n try\n {\n const { getCache } = await import('@spfn/core/cache');\n const cache = getCache();\n if (cache)\n {\n store = new CacheTokenStore(cache as any);\n if (debug)\n {\n serverLogger.info('SSE token store: cache (Redis/Valkey)');\n }\n }\n }\n catch\n {\n // Cache module not available, use in-memory\n }\n }\n\n tokenManager = new SSETokenManager({\n ttl: authConfig.tokenTtl,\n store,\n });\n\n // Derive token path: /events/stream → /events/token\n const tokenPath = streamPath.replace(/\\/[^/]+$/, '/token');\n\n // Apply config.middlewares (e.g., authenticate) to token endpoint\n const mwHandlers = (config.middlewares ?? []).map(mw => mw.handler);\n const getSubject = authConfig.getSubject\n ?? ((c: Context) => (c.get('auth') as Record<string, string> | undefined)?.userId ?? null);\n\n app.post(tokenPath, ...mwHandlers, async (c: Context) =>\n {\n const subject = getSubject(c);\n if (!subject)\n {\n return c.json({ error: 'Unable to identify subject' }, 401);\n }\n\n const token = await tokenManager!.issue(subject);\n return c.json({ token });\n });\n\n if (debug)\n {\n serverLogger.info(`✓ SSE token endpoint registered at POST ${tokenPath}`);\n }\n }\n\n // Register SSE stream handler\n app.get(streamPath, createSSEHandler(config.events, eventsConfig, tokenManager));\n\n if (debug)\n {\n const eventNames = config.events.eventNames as string[];\n serverLogger.info(`✓ SSE endpoint registered at ${streamPath}`, {\n events: eventNames,\n auth: !!authConfig?.enabled,\n });\n }\n}\n\n/**\n * Determine if debug mode is enabled\n */\nfunction isDebugMode(config?: ServerConfig): boolean\n{\n return config?.debug ?? process.env.NODE_ENV === 'development';\n}","/**\n * pg-boss Wrapper\n *\n * Manages pg-boss instance lifecycle\n */\n\nimport PgBoss from 'pg-boss';\nimport { logger } from '@spfn/core/logger';\n\nconst jobLogger = logger.child('@spfn/core:job');\n\n/**\n * Check if connection string uses SSL without certificate verification\n *\n * pg library verifies certificates by default even with sslmode=require.\n * For require/prefer modes (no explicit verification), we disable cert checking\n * to support self-signed certificates.\n */\nfunction requiresSSLWithoutVerification(connectionString: string): boolean\n{\n try\n {\n const url = new URL(connectionString);\n const sslmode = url.searchParams.get('sslmode');\n return sslmode === 'require' || sslmode === 'prefer';\n }\n catch\n {\n return false;\n }\n}\n\n/**\n * Remove sslmode parameter from connection string URL\n *\n * pg driver interprets sslmode=require as verify-full, which overrides\n * the ssl option object. Stripping it lets us control SSL via the ssl option only.\n */\nfunction stripSslModeFromUrl(connectionString: string): string\n{\n const url = new URL(connectionString);\n url.searchParams.delete('sslmode');\n return url.toString();\n}\n\n/**\n * globalThis keys for cross-module-cache singleton (ESM/CJS share same instance)\n */\nconst BOSS_KEY = Symbol.for('spfn:boss-instance');\nconst CONFIG_KEY = Symbol.for('spfn:boss-config');\n\nconst g = globalThis as any;\n\nfunction getBossInstance(): PgBoss | null\n{\n return g[BOSS_KEY] ?? null;\n}\n\nfunction setBossInstance(instance: PgBoss | null): void\n{\n g[BOSS_KEY] = instance;\n}\n\nfunction getBossConfig(): BossConfig | null\n{\n return g[CONFIG_KEY] ?? null;\n}\n\nfunction setBossConfig(config: BossConfig | null): void\n{\n g[CONFIG_KEY] = config;\n}\n\n/**\n * Options for pg-boss initialization\n *\n * @example\n * ```typescript\n * await initBoss({\n * connectionString: process.env.DATABASE_URL,\n * schema: 'spfn_queue',\n * clearOnStart: process.env.NODE_ENV === 'development',\n * });\n * ```\n */\nexport interface BossOptions\n{\n /**\n * PostgreSQL connection string\n *\n * @example 'postgresql://user:password@localhost:5432/mydb'\n */\n connectionString: string;\n\n /**\n * Schema name for pg-boss tables\n *\n * pg-boss creates its own tables in this schema.\n *\n * @default 'spfn_queue'\n */\n schema?: string;\n\n /**\n * Maintenance interval in seconds\n *\n * pg-boss runs maintenance tasks (cleanup, archiving) at this interval.\n *\n * @default 120\n */\n maintenanceIntervalSeconds?: number;\n\n /**\n * Monitor state changes interval in seconds\n *\n * When set, pg-boss emits state change events at this interval.\n *\n * @default undefined (disabled)\n */\n monitorIntervalSeconds?: number;\n\n /**\n * Clear all pending/scheduled jobs on startup\n *\n * Useful for development mode to start with a clean queue.\n * Should be false in production.\n *\n * @default false\n */\n clearOnStart?: boolean;\n}\n\n/**\n * @deprecated Use BossOptions instead\n */\nexport type BossConfig = BossOptions;\n\n/**\n * Initialize pg-boss with the given configuration\n *\n * Must be called before registerJobs(). Typically handled by defineServerConfig().\n *\n * @param options - pg-boss configuration options\n * @returns The pg-boss instance\n *\n * @example\n * ```typescript\n * const boss = await initBoss({\n * connectionString: process.env.DATABASE_URL!,\n * schema: 'spfn_queue',\n * });\n * ```\n */\nexport async function initBoss(options: BossOptions): Promise<PgBoss>\n{\n const existing = getBossInstance();\n if (existing)\n {\n jobLogger.warn('pg-boss already initialized, returning existing instance');\n return existing;\n }\n\n jobLogger.info('Initializing pg-boss...');\n\n setBossConfig(options);\n\n const needsSSL = requiresSSLWithoutVerification(options.connectionString);\n\n const pgBossOptions: PgBoss.ConstructorOptions = {\n // pg 드라이버가 URL의 sslmode=require를 verify-full로 해석해서\n // ssl 옵션을 무시하므로, URL에서 sslmode를 빼고 ssl 객체만 전달\n connectionString: needsSSL\n ? stripSslModeFromUrl(options.connectionString)\n : options.connectionString,\n schema: options.schema ?? 'spfn_queue',\n maintenanceIntervalSeconds: options.maintenanceIntervalSeconds ?? 120,\n };\n\n if (needsSSL)\n {\n pgBossOptions.ssl = { rejectUnauthorized: false };\n }\n\n // Only set monitorIntervalSeconds if explicitly provided (must be >= 1)\n if (options.monitorIntervalSeconds !== undefined && options.monitorIntervalSeconds >= 1)\n {\n pgBossOptions.monitorIntervalSeconds = options.monitorIntervalSeconds;\n }\n\n const boss = new PgBoss(pgBossOptions);\n\n // Event handlers\n boss.on('error', (error) =>\n {\n jobLogger.error('pg-boss error:', error);\n });\n\n await boss.start();\n\n setBossInstance(boss);\n\n jobLogger.info('pg-boss started successfully');\n\n return boss;\n}\n\n/**\n * Get the current pg-boss instance\n */\nexport function getBoss(): PgBoss | null\n{\n return getBossInstance();\n}\n\n/**\n * Stop pg-boss gracefully\n */\nexport async function stopBoss(): Promise<void>\n{\n const boss = getBossInstance();\n if (!boss)\n {\n return;\n }\n\n jobLogger.info('Stopping pg-boss...');\n\n try\n {\n await boss.stop({ graceful: true, timeout: 30000 });\n jobLogger.info('pg-boss stopped gracefully');\n }\n catch (error)\n {\n jobLogger.error('Error stopping pg-boss:', error);\n throw error;\n }\n finally\n {\n setBossInstance(null);\n setBossConfig(null);\n }\n}\n\n/**\n * Check if pg-boss is initialized and running\n */\nexport function isBossRunning(): boolean\n{\n return getBossInstance() !== null;\n}\n\n/**\n * Check if jobs should be cleared on start\n */\nexport function shouldClearOnStart(): boolean\n{\n return getBossConfig()?.clearOnStart ?? false;\n}\n","/**\n * Job Router\n *\n * Groups job definitions for registration with the server\n */\n\nimport type { JobDef, JobRouter, JobRouterEntry } from './types';\n\n/**\n * Type guard to check if value is a JobDef\n */\nexport function isJobDef(value: unknown): value is JobDef<any>\n{\n return (\n value !== null &&\n typeof value === 'object' &&\n 'name' in value &&\n 'handler' in value &&\n 'send' in value &&\n 'run' in value\n );\n}\n\n/**\n * Type guard to check if value is a JobRouter\n */\nexport function isJobRouter(value: unknown): value is JobRouter<any>\n{\n return (\n value !== null &&\n typeof value === 'object' &&\n 'jobs' in value &&\n '_jobs' in value\n );\n}\n\n/**\n * Define a job router to group jobs together\n *\n * @example\n * ```typescript\n * // Flat structure\n * export const jobRouter = defineJobRouter({\n * sendWelcomeEmail,\n * dailyReport,\n * initCache,\n * });\n *\n * // Nested structure\n * export const jobRouter = defineJobRouter({\n * email: defineJobRouter({\n * sendWelcome: sendWelcomeEmailJob,\n * sendReset: sendResetPasswordJob,\n * }),\n * reports: defineJobRouter({\n * daily: dailyReportJob,\n * weekly: weeklyReportJob,\n * }),\n * });\n *\n * // Mixed\n * export const jobRouter = defineJobRouter({\n * initCache, // flat\n * email: defineJobRouter({ ... }), // nested\n * });\n * ```\n */\nexport function defineJobRouter<\n TJobs extends Record<string, JobRouterEntry>\n>(jobs: TJobs): JobRouter<TJobs>\n{\n return {\n jobs,\n _jobs: jobs,\n };\n}\n\n/**\n * Collect all JobDefs from a JobRouter (including nested)\n */\nexport function collectJobs(\n router: JobRouter<any>,\n prefix = ''\n): JobDef<any>[]\n{\n const jobs: JobDef<any>[] = [];\n\n for (const [key, value] of Object.entries(router.jobs))\n {\n const name = prefix ? `${prefix}.${key}` : key;\n\n if (isJobRouter(value))\n {\n // Nested router - recurse\n jobs.push(...collectJobs(value, name));\n }\n else if (isJobDef(value))\n {\n jobs.push(value);\n }\n }\n\n return jobs;\n}\n","/**\n * Job Registration\n *\n * Registers jobs with pg-boss\n */\n\nimport type PgBoss from 'pg-boss';\nimport { logger } from '@spfn/core/logger';\nimport type { JobDef, JobOptions, JobRouter } from './types';\nimport type { EventDef } from '@spfn/core/event';\nimport { collectJobs } from './job-router';\nimport { getBoss, shouldClearOnStart } from './boss';\n\nconst jobLogger = logger.child('@spfn/core:job');\n\n/**\n * Get the pg-boss queue name for an event\n */\nexport function getEventQueueName(eventName: string): string\n{\n return `event:${eventName}`;\n}\n\n/**\n * Build default pg-boss options for a job\n */\nfunction getDefaultJobOptions(options?: JobOptions): PgBoss.SendOptions\n{\n return {\n retryLimit: options?.retryLimit ?? 3,\n retryDelay: options?.retryDelay ?? 1000,\n expireInSeconds: options?.expireInSeconds ?? 300,\n };\n}\n\n/**\n * Register all jobs from a JobRouter with pg-boss\n *\n * This function:\n * 1. Collects all jobs from the router (including nested routers)\n * 2. Optionally clears existing jobs (if clearOnStart is enabled)\n * 3. Registers each job's worker handler with pg-boss\n * 4. Sets up cron schedules for scheduled jobs\n * 5. Queues runOnce jobs\n * 6. Connects event subscriptions to job queues\n *\n * @param router - JobRouter containing job definitions\n *\n * @example\n * ```typescript\n * // Define jobs\n * const sendEmail = job('send-email')\n * .input(Type.Object({ to: Type.String() }))\n * .handler(async (input) => { ... });\n *\n * const dailyReport = job('daily-report')\n * .cron('0 9 * * *')\n * .handler(async () => { ... });\n *\n * // Create router\n * const jobRouter = defineJobRouter({ sendEmail, dailyReport });\n *\n * // Initialize pg-boss first\n * await initBoss({ connectionString: process.env.DATABASE_URL! });\n *\n * // Register jobs\n * await registerJobs(jobRouter);\n * ```\n */\nexport async function registerJobs(router: JobRouter<any>): Promise<void>\n{\n const boss = getBoss();\n if (!boss)\n {\n throw new Error(\n 'pg-boss not initialized. Call initBoss() before registerJobs()'\n );\n }\n\n const jobs = collectJobs(router);\n const clearOnStart = shouldClearOnStart();\n\n jobLogger.info(`Registering ${jobs.length} job(s)...`);\n\n // Clear existing jobs if requested (useful for development)\n if (clearOnStart)\n {\n jobLogger.info('Clearing existing jobs before registration...');\n for (const job of jobs)\n {\n // Clear job queue\n await boss.deleteAllJobs(job.name);\n\n // Also clear event queue if subscribed\n if (job.subscribedEvent)\n {\n const eventQueue = getEventQueueName(job.subscribedEvent);\n await boss.deleteAllJobs(eventQueue);\n }\n }\n jobLogger.info('Existing jobs cleared');\n }\n\n for (const job of jobs)\n {\n await registerJob(job);\n }\n\n jobLogger.info('All jobs registered successfully');\n}\n\n/**\n * Create queue if not exists (required for pg-boss v11+)\n */\nasync function ensureQueue(boss: PgBoss, queueName: string): Promise<void>\n{\n await boss.createQueue(queueName);\n}\n\n/**\n * Register worker handler for a job\n */\nasync function registerWorker(\n boss: PgBoss,\n job: JobDef<any>,\n queueName: string\n): Promise<void>\n{\n // Ensure queue exists before registering worker\n await ensureQueue(boss, queueName);\n\n await boss.work(\n queueName,\n { batchSize: 1 },\n async (jobs) =>\n {\n for (const pgBossJob of jobs)\n {\n jobLogger.debug(`[Job:${job.name}] Executing...`, { jobId: pgBossJob.id });\n\n const startTime = Date.now();\n\n try\n {\n if (job.inputSchema)\n {\n await (job.handler as (input: unknown) => Promise<void>)(pgBossJob.data);\n }\n else\n {\n await (job.handler as () => Promise<void>)();\n }\n\n const duration = Date.now() - startTime;\n jobLogger.info(`[Job:${job.name}] Completed in ${duration}ms`, {\n jobId: pgBossJob.id,\n duration,\n });\n }\n catch (error)\n {\n const duration = Date.now() - startTime;\n jobLogger.error(`[Job:${job.name}] Failed after ${duration}ms`, {\n jobId: pgBossJob.id,\n duration,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n }\n );\n}\n\n/**\n * Connect event to pg-boss queue\n */\nfunction connectEventToQueue(\n boss: PgBoss,\n job: JobDef<any>,\n queueName: string\n): void\n{\n if (!job._subscribedEventDef)\n {\n return;\n }\n\n const eventDef = job._subscribedEventDef as EventDef<any>;\n eventDef._registerJobQueue(queueName, async (queue, payload) =>\n {\n await boss.send(queue, payload as object, getDefaultJobOptions(job.options));\n });\n\n jobLogger.debug(`[Job:${job.name}] Connected to event: ${job.subscribedEvent}`);\n}\n\n/**\n * Register cron schedule for a job\n */\nasync function registerCronSchedule(boss: PgBoss, job: JobDef<any>): Promise<void>\n{\n if (!job.cronExpression)\n {\n return;\n }\n\n jobLogger.debug(`[Job:${job.name}] Scheduling cron: ${job.cronExpression}`);\n\n // Ensure queue exists for cron jobs (uses job.name as queue)\n await ensureQueue(boss, job.name);\n\n await boss.schedule(\n job.name,\n job.cronExpression,\n {},\n getDefaultJobOptions(job.options)\n );\n\n jobLogger.info(`[Job:${job.name}] Cron scheduled: ${job.cronExpression}`);\n}\n\n/**\n * Queue a runOnce job\n */\nasync function queueRunOnceJob(boss: PgBoss, job: JobDef<any>): Promise<void>\n{\n if (!job.runOnce)\n {\n return;\n }\n\n jobLogger.debug(`[Job:${job.name}] Queuing runOnce job`);\n\n // Ensure queue exists for runOnce jobs (uses job.name as queue)\n await ensureQueue(boss, job.name);\n\n await boss.send(\n job.name,\n {},\n {\n ...getDefaultJobOptions(job.options),\n singletonKey: `runOnce:${job.name}`,\n }\n );\n\n jobLogger.info(`[Job:${job.name}] runOnce job queued`);\n}\n\n/**\n * Register a single job with pg-boss\n */\nasync function registerJob(job: JobDef<any>): Promise<void>\n{\n const boss = getBoss();\n if (!boss)\n {\n throw new Error('pg-boss not initialized');\n }\n\n const queueName = job.subscribedEvent\n ? getEventQueueName(job.subscribedEvent)\n : job.name;\n\n jobLogger.debug(`Registering job: ${job.name}`, {\n queueName,\n subscribedEvent: job.subscribedEvent,\n });\n\n await registerWorker(boss, job, queueName);\n connectEventToQueue(boss, job, queueName);\n await registerCronSchedule(boss, job);\n await queueRunOnceJob(boss, job);\n\n jobLogger.debug(`Job registered: ${job.name}`);\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';\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}","/**\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 type { Hono } from 'hono';\nimport type { Server } from 'http';\nimport { join } from 'path';\n\nimport { closeCache, initCache } from '@spfn/core/cache';\nimport { closeDatabase, initDatabase, getDatabase } from '@spfn/core/db';\nimport { initBoss, stopBoss, registerJobs } from '../job';\nimport { serverLogger } from './logger';\nimport { printBanner } from './banner';\nimport { createServer } from './create-server';\nimport { loadEnv } from '../env/loader';\nimport {\n applyServerTimeouts,\n applyGlobalFetchTimeouts,\n buildMiddlewareOrder,\n buildStartupConfig,\n getFetchTimeoutConfig,\n getShutdownTimeout,\n getTimeoutConfig,\n} from './helpers';\nimport { getShutdownManager, resetShutdownManager } from './shutdown-manager';\n\nimport type { ServerConfig, ServerInstance } from './types';\nimport { validateServerConfig } from './validation';\nimport { env } from '@spfn/core/config';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_MAX_LISTENERS = 15;\n\nconst TIMEOUTS = {\n SERVER_CLOSE: 5000,\n DATABASE_CLOSE: 5000,\n REDIS_CLOSE: 5000,\n PRODUCTION_ERROR_SHUTDOWN: 10000,\n} as const;\n\nconst CONFIG_FILE_PATHS = [\n '.spfn/server/server.config.mjs',\n '.spfn/server/server.config',\n 'src/server/server.config',\n 'src/server/server.config.ts',\n] as const;\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface InfrastructureConfig\n{\n database: boolean;\n redis: boolean;\n}\n\n/**\n * Shutdown state manager to prevent race conditions\n */\ninterface ShutdownState\n{\n isShuttingDown: boolean;\n}\n\n// ============================================================================\n// Module State\n// ============================================================================\n\n/**\n * Track whether process-level shutdown handlers have been registered\n * Process handlers should only be registered once\n */\nlet processHandlersRegistered = false;\n\n// ============================================================================\n// Main Entry Point\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 loadEnv();\n\n const finalConfig = await loadAndMergeConfig(config);\n const { host, port, debug } = finalConfig;\n\n validateServerConfig(finalConfig);\n\n // Validate required config values\n if (!host || !port)\n {\n throw new Error('Server host and port are required');\n }\n\n if (debug)\n {\n logMiddlewareOrder(finalConfig);\n }\n\n // Create shutdown state for this server instance\n const shutdownState: ShutdownState = {\n isShuttingDown: false,\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 const fetchTimeouts = getFetchTimeoutConfig(finalConfig.fetchTimeout);\n applyGlobalFetchTimeouts(fetchTimeouts);\n\n logServerTimeouts(timeouts);\n printBanner({\n mode: debug ? 'Development' : 'Production',\n host,\n port,\n });\n\n logServerStarted(debug, host, port, finalConfig, timeouts);\n\n const shutdownServer = createShutdownHandler(server as Server, finalConfig, shutdownState);\n const shutdown = createGracefulShutdown(shutdownServer, finalConfig, shutdownState);\n\n // Register process-level handlers\n registerProcessHandlers(shutdown);\n\n const serverInstance: ServerInstance = {\n server,\n app,\n config: finalConfig,\n close: async () =>\n {\n serverLogger.info('Manual server shutdown requested');\n await shutdownServer();\n },\n };\n\n // Execute afterStart hook from config\n if (finalConfig.lifecycle?.afterStart)\n {\n serverLogger.debug('Executing afterStart hook...');\n try\n {\n await finalConfig.lifecycle.afterStart(serverInstance);\n }\n catch (error)\n {\n serverLogger.error('afterStart hook failed', error as Error);\n // Don't throw - server is already running\n // Just log the error and continue\n }\n }\n\n return serverInstance;\n }\n catch (error)\n {\n const err = error as Error;\n serverLogger.error('Server initialization failed', err);\n\n await cleanupOnFailure(finalConfig);\n\n throw error;\n }\n}\n\n// ============================================================================\n// Configuration Loading\n// ============================================================================\n\nasync function loadAndMergeConfig(config?: ServerConfig): Promise<ServerConfig>\n{\n const cwd = process.cwd();\n let fileConfig: ServerConfig = {};\n let loadedConfigPath: string | null = null;\n\n // Try loading config files in priority order\n for (const configPath of CONFIG_FILE_PATHS)\n {\n const fullPath = join(cwd, configPath);\n if (existsSync(fullPath))\n {\n try\n {\n const configModule = await import(fullPath);\n fileConfig = configModule.default ?? {};\n loadedConfigPath = configPath;\n break;\n }\n catch (error)\n {\n serverLogger.error(`Failed to load config from ${configPath} - file exists but import failed`, error as Error);\n // Continue trying other config files instead of failing\n }\n }\n }\n\n if (loadedConfigPath)\n {\n serverLogger.debug(`Loaded configuration from ${loadedConfigPath}`);\n }\n else\n {\n serverLogger.debug('No configuration file found, using defaults');\n }\n\n return {\n ...fileConfig,\n ...config,\n port: config?.port ?? fileConfig?.port ?? env.PORT,\n host: config?.host ?? fileConfig?.host ?? env.HOST,\n };\n}\n\n// ============================================================================\n// Infrastructure Management\n// ============================================================================\n\n/**\n * Determine which infrastructure components should be initialized\n */\nfunction getInfrastructureConfig(config: ServerConfig): InfrastructureConfig\n{\n return {\n database: config.infrastructure?.database !== false,\n redis: config.infrastructure?.redis !== false,\n };\n}\n\nasync function initializeInfrastructure(config: ServerConfig): Promise<void>\n{\n if (config.lifecycle?.beforeInfrastructure)\n {\n serverLogger.debug('Executing beforeInfrastructure hook...');\n await config.lifecycle.beforeInfrastructure(config);\n }\n\n const infraConfig = getInfrastructureConfig(config);\n\n if (infraConfig.database)\n {\n serverLogger.debug('Initializing database...');\n await initDatabase(config.database);\n }\n else\n {\n serverLogger.debug('Database initialization disabled');\n }\n\n if (infraConfig.redis)\n {\n serverLogger.debug('Initializing Redis...');\n await initCache();\n }\n else\n {\n serverLogger.debug('Redis initialization disabled');\n }\n\n if (config.lifecycle?.afterInfrastructure)\n {\n serverLogger.debug('Executing afterInfrastructure hook...');\n await config.lifecycle.afterInfrastructure();\n }\n\n // Initialize jobs if configured\n if (config.jobs)\n {\n const dbUrl = env.DATABASE_URL;\n if (!dbUrl)\n {\n throw new Error(\n 'Jobs require database connection. ' +\n 'Ensure DATABASE_URL is set or database is enabled.'\n );\n }\n\n serverLogger.debug('Initializing pg-boss...');\n await initBoss({\n connectionString: dbUrl,\n ...config.jobsConfig,\n });\n\n serverLogger.debug('Registering jobs...');\n await registerJobs(config.jobs);\n }\n\n // Initialize workflows if configured\n if (config.workflows)\n {\n const infraConfig = getInfrastructureConfig(config);\n if (!infraConfig.database)\n {\n throw new Error(\n 'Workflows require database connection. ' +\n 'Ensure database is enabled in infrastructure config.'\n );\n }\n\n serverLogger.debug('Initializing workflow engine...');\n config.workflows._init(\n getDatabase(),\n config.workflowsConfig\n );\n serverLogger.info('Workflow engine initialized');\n }\n}\n\n// ============================================================================\n// HTTP Server Management\n// ============================================================================\n\nfunction startHttpServer(app: Hono, host: string, port: number): ReturnType<typeof serve>\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 logMiddlewareOrder(config: ServerConfig): void\n{\n const middlewareOrder = buildMiddlewareOrder(config);\n serverLogger.debug('Middleware execution order', {\n order: middlewareOrder,\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\n// ============================================================================\n// Graceful Shutdown\n// ============================================================================\n\nfunction createShutdownHandler(\n server: Server,\n config: ServerConfig,\n shutdownState: ShutdownState\n): () => Promise<void>\n{\n return async () =>\n {\n // Prevent re-entry\n if (shutdownState.isShuttingDown)\n {\n serverLogger.debug('Shutdown already in progress for this instance, skipping');\n return;\n }\n\n shutdownState.isShuttingDown = true;\n\n const shutdownTimeout = getShutdownTimeout(config.shutdown);\n const shutdownManager = getShutdownManager();\n\n // Immediately mark as draining so health check returns 503\n // and trackOperation() rejects new work\n shutdownManager.beginShutdown();\n\n // ── Phase 1: Stop accepting new connections ──\n serverLogger.info('Phase 1: Closing HTTP server (stop accepting new connections)...');\n await closeHttpServer(server);\n\n // ── Phase 2: Stop pg-boss (stop accepting new jobs) ──\n if (config.jobs)\n {\n serverLogger.info('Phase 2: Stopping pg-boss...');\n try\n {\n await stopBoss();\n serverLogger.info('pg-boss stopped');\n }\n catch (error)\n {\n serverLogger.error('pg-boss stop failed', error as Error);\n }\n }\n\n // ── Phase 3: Drain — wait for all tracked operations to complete ──\n // Use 80% of remaining shutdown timeout for drain + hooks\n const drainTimeout = Math.floor(shutdownTimeout * 0.8);\n serverLogger.info(`Phase 3: Draining tracked operations (timeout: ${drainTimeout}ms)...`);\n await shutdownManager.execute(drainTimeout);\n\n // ── Phase 4: Execute beforeShutdown lifecycle hook (backward compat) ──\n if (config.lifecycle?.beforeShutdown)\n {\n serverLogger.info('Phase 4: Executing beforeShutdown lifecycle hook...');\n try\n {\n await config.lifecycle.beforeShutdown();\n }\n catch (error)\n {\n serverLogger.error('beforeShutdown lifecycle hook failed', error as Error);\n }\n }\n\n // ── Phase 5: Close infrastructure (DB, Redis) ──\n serverLogger.info('Phase 5: Closing infrastructure...');\n const infraConfig = getInfrastructureConfig(config);\n\n if (infraConfig.database)\n {\n await closeInfrastructure(closeDatabase, 'Database', TIMEOUTS.DATABASE_CLOSE);\n }\n\n if (infraConfig.redis)\n {\n await closeInfrastructure(closeCache, 'Redis', TIMEOUTS.REDIS_CLOSE);\n }\n\n serverLogger.info('Server shutdown completed');\n };\n}\n\n/**\n * Close HTTP server with timeout\n */\nasync function closeHttpServer(server: Server): Promise<void>\n{\n let timeoutId: NodeJS.Timeout | undefined;\n\n await Promise.race([\n new Promise<void>((resolve, reject) =>\n {\n server.close((err) =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n\n if (err)\n {\n serverLogger.error('HTTP server close error', err);\n reject(err);\n }\n else\n {\n serverLogger.info('HTTP server closed');\n resolve();\n }\n });\n }),\n new Promise<void>((_, reject) =>\n {\n timeoutId = setTimeout(() =>\n {\n reject(new Error(`HTTP server close timeout after ${TIMEOUTS.SERVER_CLOSE}ms`));\n }, TIMEOUTS.SERVER_CLOSE);\n }),\n ]).catch((error) =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n serverLogger.warn('HTTP server close timeout, forcing shutdown', error as Error);\n });\n}\n\n/**\n * Close infrastructure component with timeout\n */\nasync function closeInfrastructure(\n closeFn: () => Promise<void>,\n name: string,\n timeout: number\n): Promise<void>\n{\n let timeoutId: NodeJS.Timeout | undefined;\n\n try\n {\n await Promise.race([\n closeFn().then(() =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n }),\n new Promise<void>((_, reject) =>\n {\n timeoutId = setTimeout(() =>\n {\n reject(new Error(`${name} close timeout after ${timeout}ms`));\n }, timeout);\n }),\n ]);\n serverLogger.info(`${name} connections closed successfully`);\n }\n catch (error)\n {\n if (timeoutId) clearTimeout(timeoutId);\n serverLogger.error(`${name} close failed or timed out`, error as Error);\n // Continue with shutdown even if close fails\n }\n}\n\nfunction createGracefulShutdown(\n shutdownServer: () => Promise<void>,\n config: ServerConfig,\n shutdownState: ShutdownState\n): (signal: string) => Promise<void>\n{\n return async (signal: string) =>\n {\n // Prevent re-entry\n if (shutdownState.isShuttingDown)\n {\n serverLogger.warn(`${signal} received but shutdown already in progress, ignoring`);\n return;\n }\n\n serverLogger.info(`${signal} received, starting graceful shutdown...`);\n\n const shutdownTimeout = getShutdownTimeout(config.shutdown);\n let timeoutId: NodeJS.Timeout | undefined;\n\n try\n {\n await Promise.race([\n shutdownServer().then(() =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n }),\n new Promise<never>((_, reject) =>\n {\n timeoutId = setTimeout(() =>\n {\n reject(new Error(`Graceful shutdown timeout after ${shutdownTimeout}ms`));\n }, shutdownTimeout);\n }),\n ]);\n\n if (timeoutId) clearTimeout(timeoutId);\n serverLogger.info('Graceful shutdown completed successfully');\n process.exit(0);\n }\n catch (error)\n {\n if (timeoutId) clearTimeout(timeoutId);\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\n// ============================================================================\n// Error Handlers\n// ============================================================================\n\n/**\n * Handle process errors - log and continue, don't kill the server\n */\nfunction handleProcessError(errorType: string): void\n{\n serverLogger.warn(`${errorType} occurred - server continues running. Check logs above for details.`);\n}\n\nfunction registerProcessHandlers(\n shutdown: (signal: string) => Promise<void>\n): void\n{\n // Prevent duplicate registration\n if (processHandlersRegistered)\n {\n serverLogger.debug('Process handlers already registered, skipping');\n return;\n }\n\n processHandlersRegistered = true;\n\n // Increase max listeners to prevent warnings in development with hot reload\n const currentMax = process.getMaxListeners();\n if (currentMax < DEFAULT_MAX_LISTENERS)\n {\n process.setMaxListeners(DEFAULT_MAX_LISTENERS);\n }\n\n process.on('SIGTERM', () =>\n {\n shutdown('SIGTERM').catch((error) =>\n {\n serverLogger.error('SIGTERM handler failed', error as Error);\n process.exit(1);\n });\n });\n\n process.on('SIGINT', () =>\n {\n shutdown('SIGINT').catch((error) =>\n {\n serverLogger.error('SIGINT handler failed', error as Error);\n process.exit(1);\n });\n });\n\n process.on('uncaughtException', (error) =>\n {\n // Enhanced logging for EADDRINUSE errors\n if (error.message?.includes('EADDRINUSE'))\n {\n serverLogger.error('Port conflict detected - detailed trace:', error, {\n code: (error as any).code,\n port: (error as any).port,\n address: (error as any).address,\n syscall: (error as any).syscall,\n });\n }\n else\n {\n serverLogger.error('Uncaught exception', error);\n }\n\n handleProcessError('UNCAUGHT_EXCEPTION');\n });\n\n process.on('unhandledRejection', (reason, promise) =>\n {\n // Enhanced error logging with promise context extraction\n if (reason instanceof Error)\n {\n // Import formatUnhandledRejection dynamically to avoid circular deps\n import('../logger/formatters').then(({ formatUnhandledRejection }) =>\n {\n const { error, context } = formatUnhandledRejection(reason, promise);\n\n serverLogger.error('Unhandled promise rejection', error, context);\n }).catch(() =>\n {\n // Fallback if formatUnhandledRejection fails\n serverLogger.error('Unhandled promise rejection', reason, {\n promise,\n });\n });\n }\n else\n {\n serverLogger.error('Unhandled promise rejection', {\n reason,\n promise,\n });\n }\n\n handleProcessError('UNHANDLED_REJECTION');\n });\n\n serverLogger.debug('Process-level shutdown handlers registered successfully');\n}\n\n// ============================================================================\n// Cleanup\n// ============================================================================\n\nasync function cleanupOnFailure(config: ServerConfig): Promise<void>\n{\n try\n {\n serverLogger.debug('Cleaning up after initialization failure...');\n\n // Only cleanup resources that were enabled for initialization\n const infraConfig = getInfrastructureConfig(config);\n\n if (infraConfig.database)\n {\n await closeInfrastructure(closeDatabase, 'Database', TIMEOUTS.DATABASE_CLOSE);\n }\n\n if (infraConfig.redis)\n {\n await closeInfrastructure(closeCache, 'Redis', TIMEOUTS.REDIS_CLOSE);\n }\n\n resetShutdownManager();\n serverLogger.debug('Cleanup completed');\n }\n catch (cleanupError)\n {\n serverLogger.error('Cleanup failed', cleanupError as Error);\n }\n}","/**\n * Server Config Builder\n *\n * Provides a fluent API for building server configuration\n */\n\nimport type { MiddlewareHandler } from 'hono';\nimport type { ServerConfig } from './types';\nimport type { Router, NamedMiddleware } from '@spfn/core/route';\nimport type { JobRouter, BossOptions } from '../job';\nimport type { EventRouterDef } from '../event/router';\nimport type { SSEHandlerConfig, SSEAuthConfig } from '../event/sse/types';\nimport { serverLogger } from './logger';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype Lifecycle = NonNullable<ServerConfig['lifecycle']>;\ntype LifecycleKey = keyof Lifecycle;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nfunction collectHooks<K extends LifecycleKey>(\n lifecycles: Lifecycle[],\n key: K\n): NonNullable<Lifecycle[K]>[]\n{\n return lifecycles\n .map(lc => lc[key])\n .filter((hook): hook is NonNullable<Lifecycle[K]> => hook !== undefined);\n}\n\nfunction createMergedHook<T extends (...args: any[]) => void | Promise<void>>(\n hooks: T[]\n): T | undefined\n{\n if (hooks.length === 0)\n {\n return undefined;\n }\n\n return (async (...args: Parameters<T>) =>\n {\n for (const hook of hooks)\n {\n await hook(...args);\n }\n }) as T;\n}\n\nexport class ServerConfigBuilder\n{\n private config: ServerConfig = {};\n private lifecycles: NonNullable<ServerConfig['lifecycle']>[] = [];\n\n /**\n * Set server port\n */\n port(port: number): this\n {\n this.config.port = port;\n return this;\n }\n\n /**\n * Set server hostname\n */\n host(host: string): this\n {\n this.config.host = host;\n return this;\n }\n\n /**\n * Set CORS configuration\n */\n cors(cors: ServerConfig['cors']): this\n {\n this.config.cors = cors;\n return this;\n }\n\n /**\n * Configure built-in middleware\n */\n middleware(middleware: ServerConfig['middleware']): this\n {\n this.config.middleware = middleware;\n return this;\n }\n\n /**\n * Add custom middleware\n */\n use(handlers: MiddlewareHandler[]): this\n {\n this.config.use = handlers;\n return this;\n }\n\n /**\n * Add named middlewares for route-level skip control\n */\n middlewares(middlewares: ServerConfig['middlewares']): this\n {\n this.config.middlewares = middlewares;\n return this;\n }\n\n /**\n * Register define-route based router\n *\n * Automatically applies:\n * - Global middlewares from router._globalMiddlewares (via .use())\n * - Package routers from router._packageRouters (via .packages())\n *\n * @example\n * ```typescript\n * const appRouter = defineRouter({\n * getUser: route.get('/users/:id')...\n * })\n * .packages([authRouter, cmsAppRouter])\n * .use([authMiddleware]);\n *\n * export default defineServerConfig()\n * .routes(appRouter) // middlewares auto-applied\n * .build();\n * ```\n */\n routes(router: Router<any>): this\n {\n this.config.routes = router;\n\n // Collect all global middlewares from router and package routers\n const allGlobalMiddlewares: NamedMiddleware[] = [];\n\n // Add main router's global middlewares\n if (router._globalMiddlewares?.length > 0)\n {\n allGlobalMiddlewares.push(...router._globalMiddlewares);\n }\n\n // Add package routers' global middlewares\n if (router._packageRouters?.length > 0)\n {\n for (const pkgRouter of router._packageRouters)\n {\n if (pkgRouter._globalMiddlewares?.length > 0)\n {\n allGlobalMiddlewares.push(...pkgRouter._globalMiddlewares);\n }\n }\n }\n\n // Merge with existing middlewares\n if (allGlobalMiddlewares.length > 0)\n {\n this.config.middlewares = [\n ...(this.config.middlewares || []),\n ...allGlobalMiddlewares,\n ];\n }\n\n return this;\n }\n\n /**\n * Register background jobs router\n *\n * @example\n * ```typescript\n * import { job, defineJobRouter } from '@spfn/core/job';\n *\n * const sendEmail = job('send-email')\n * .input(Type.Object({ to: Type.String() }))\n * .handler(async (input) => { ... });\n *\n * const jobRouter = defineJobRouter({ sendEmail });\n *\n * export default defineServerConfig()\n * .routes(appRouter)\n * .jobs(jobRouter)\n * .build();\n * ```\n */\n jobs(router: JobRouter<any>, config?: Omit<BossOptions, 'connectionString'>): this\n {\n this.config.jobs = router;\n if (config)\n {\n this.config.jobsConfig = config;\n }\n return this;\n }\n\n /**\n * Register event router for SSE (Server-Sent Events)\n *\n * Enables real-time event streaming to frontend clients.\n * Events defined with defineEvent() can be subscribed by:\n * - Backend: .subscribe() for internal handlers\n * - Jobs: .on(event) for background processing\n * - Frontend: SSE stream for real-time updates\n *\n * @example\n * ```typescript\n * import { defineEvent, defineEventRouter } from '@spfn/core/event';\n *\n * const userCreated = defineEvent('user.created', Type.Object({\n * userId: Type.String(),\n * }));\n *\n * const eventRouter = defineEventRouter({ userCreated });\n *\n * export default defineServerConfig()\n * .routes(appRouter)\n * .events(eventRouter) // → GET /events/stream\n * .build();\n *\n * // Custom path\n * .events(eventRouter, { path: '/sse' })\n * ```\n */\n events<TRouter extends EventRouterDef<any>>(\n router: TRouter,\n config?: Omit<SSEHandlerConfig, 'auth'> & { path?: string; auth?: SSEAuthConfig<TRouter> }\n ): this\n {\n this.config.events = router;\n if (config)\n {\n // SSEAuthConfig<TRouter> is assignable to SSEHandlerAuthConfig at runtime\n this.config.eventsConfig = config as SSEHandlerConfig & { path?: string };\n }\n return this;\n }\n\n /**\n * Enable/disable debug mode\n */\n debug(enabled: boolean): this\n {\n this.config.debug = enabled;\n return this;\n }\n\n /**\n * Configure database settings\n */\n database(database: ServerConfig['database']): this\n {\n this.config.database = database;\n return this;\n }\n\n /**\n * Configure server timeout settings\n */\n timeout(timeout: ServerConfig['timeout']): this\n {\n this.config.timeout = timeout;\n return this;\n }\n\n /**\n * Configure graceful shutdown settings\n */\n shutdown(shutdown: ServerConfig['shutdown']): this\n {\n this.config.shutdown = shutdown;\n return this;\n }\n\n /**\n * Configure health check endpoint\n */\n healthCheck(healthCheck: ServerConfig['healthCheck']): this\n {\n this.config.healthCheck = healthCheck;\n return this;\n }\n\n /**\n * Configure infrastructure initialization\n */\n infrastructure(infrastructure: ServerConfig['infrastructure']): this\n {\n this.config.infrastructure = infrastructure;\n return this;\n }\n\n /**\n * Register workflow router for workflow orchestration\n *\n * Automatically initializes the workflow engine after database is ready.\n *\n * @example\n * ```typescript\n * import { defineWorkflowRouter } from '@spfn/workflow';\n *\n * const workflowRouter = defineWorkflowRouter([\n * provisionTenant,\n * deprovisionTenant,\n * ]);\n *\n * export default defineServerConfig()\n * .routes(appRouter)\n * .workflows(workflowRouter)\n * .build();\n * ```\n */\n workflows(\n router: ServerConfig['workflows'],\n config?: ServerConfig['workflowsConfig']\n ): this\n {\n this.config.workflows = router;\n if (config)\n {\n this.config.workflowsConfig = config;\n }\n return this;\n }\n\n /**\n * Configure lifecycle hooks\n * Can be called multiple times - hooks will be executed in registration order\n */\n lifecycle(lifecycle: ServerConfig['lifecycle']): this\n {\n if (lifecycle)\n {\n this.lifecycles.push(lifecycle);\n }\n return this;\n }\n\n /**\n * Build and return the final configuration\n */\n build(): ServerConfig\n {\n if (this.lifecycles.length > 0)\n {\n serverLogger.info('Merging lifecycles', { count: this.lifecycles.length });\n this.config.lifecycle = this.mergeLifecycles();\n }\n\n return this.config;\n }\n\n private mergeLifecycles(): Lifecycle\n {\n return {\n beforeInfrastructure: createMergedHook(\n collectHooks(this.lifecycles, 'beforeInfrastructure')\n ),\n afterInfrastructure: createMergedHook(\n collectHooks(this.lifecycles, 'afterInfrastructure')\n ),\n beforeRoutes: createMergedHook(\n collectHooks(this.lifecycles, 'beforeRoutes')\n ),\n afterRoutes: createMergedHook(\n collectHooks(this.lifecycles, 'afterRoutes')\n ),\n afterStart: createMergedHook(\n collectHooks(this.lifecycles, 'afterStart')\n ),\n beforeShutdown: createMergedHook(\n collectHooks(this.lifecycles, 'beforeShutdown')\n ),\n };\n }\n}\n\n/**\n * Create a new server configuration builder\n *\n * @example\n * ```typescript\n * // server.config.ts\n * import { defineServerConfig, route, defineRouter } from '@spfn/core/server';\n * import { Type } from '@sinclair/typebox';\n *\n * const appRouter = defineRouter({\n * getUser: route.get('/users/:id')\n * .input({ params: Type.Object({ id: Type.String() }) })\n * .handler(async (c) => {\n * const { params } = await c.data();\n * return { id: params.id, name: 'John' };\n * }),\n * });\n *\n * export default defineServerConfig()\n * .port(3000)\n * .routes(appRouter)\n * .middleware({ logger: true, cors: true })\n * .debug(true)\n * .build();\n * ```\n */\nexport function defineServerConfig(): ServerConfigBuilder\n{\n return new ServerConfigBuilder();\n}"]}
|
|
1
|
+
{"version":3,"sources":["../../src/logger/formatters.ts","../../src/env/loader.ts","../../src/server/dotenv-loader.ts","../../src/event/sse/handler.ts","../../src/event/sse/token-manager.ts","../../src/server/logger.ts","../../src/server/shutdown-manager.ts","../../src/server/helpers.ts","../../src/server/create-server.ts","../../src/job/boss.ts","../../src/job/job-router.ts","../../src/job/register-jobs.ts","../../src/server/banner.ts","../../src/server/validation.ts","../../src/server/start-server.ts","../../src/server/config-builder.ts"],"names":["logger","resolve","existsSync","getCache","instance","jobLogger","job","join","env","infraConfig","getDatabase","formatUnhandledRejection","cors"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Logger Formatters\n *\n * Log formatting utilities for console and JSON 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 * Circular reference를 안전하게 처리\n *\n * @param data - 원본 데이터\n * @param seen - 순환 참조 감지용 WeakSet (내부 사용)\n * @returns 마스킹된 데이터\n */\nexport function maskSensitiveData(data: unknown, seen = new WeakSet<object>()): unknown\n{\n // null, undefined 처리\n if (data === null || data === undefined)\n {\n return data;\n }\n\n // 기본 타입은 그대로 반환\n if (typeof data !== 'object')\n {\n return data;\n }\n\n // Circular reference 감지\n if (seen.has(data as object))\n {\n return '[Circular]';\n }\n seen.add(data as object);\n\n // 배열 처리\n if (Array.isArray(data))\n {\n return data.map(item => maskSensitiveData(item, seen));\n }\n\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 // 중첩된 객체는 재귀 처리 (seen 전달)\n masked[key] = maskSensitiveData(value, seen);\n }\n else\n {\n // 일반 값은 그대로 유지\n masked[key] = value;\n }\n }\n\n return masked;\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 // [pid=12345]\n const pid = process.pid;\n if (colorize)\n {\n parts.push(`${COLORS.dim}[pid=${pid}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[pid=${pid}]`);\n }\n\n // [module=value]\n if (metadata.module)\n {\n if (colorize)\n {\n parts.push(`${COLORS.dim}[module=${metadata.module}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[module=${metadata.module}]`);\n }\n }\n\n // Context를 각각 [key=value] 형태로 추가\n if (metadata.context && Object.keys(metadata.context).length > 0)\n {\n Object.entries(metadata.context).forEach(([key, value]) =>\n {\n let valueStr: string;\n if (typeof value === 'string')\n {\n valueStr = value;\n }\n else if (typeof value === 'object' && value !== null)\n {\n try\n {\n valueStr = JSON.stringify(value);\n }\n catch (error)\n {\n valueStr = '[circular]';\n }\n }\n else\n {\n valueStr = String(value);\n }\n\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Drizzle ORM 에러에서 쿼리 정보 추출\n *\n * Drizzle ORM은 에러 메시지에 다음 형식으로 정보를 포함:\n * - \"Failed query: <QUERY>\\nparams: <PARAMS>\"\n * - \"Query: <QUERY>\"\n *\n * @param error - Error 객체\n * @returns 쿼리 정보 (query, params, table)\n */\nexport function extractQueryInfo(error: Error): {\n query?: string;\n params?: unknown;\n table?: string;\n} | null\n{\n const message = error.message;\n\n if (!message) return null;\n\n const result: {\n query?: string;\n params?: unknown;\n table?: string;\n } = {};\n\n // Extract query from \"Failed query: ...\" or \"Query: ...\"\n const queryMatch = message.match(/(?:Failed query:|Query:)\\s*([^\\n]+)/);\n if (queryMatch)\n {\n result.query = queryMatch[1].trim();\n\n // Extract table name from query (e.g., UPDATE \"table_name\" or INSERT INTO \"table_name\")\n const tableMatch = result.query.match(/(?:UPDATE|INSERT INTO|DELETE FROM|FROM)\\s+\"?([a-zA-Z_][a-zA-Z0-9_]*)\"?\\.\"?([a-zA-Z_][a-zA-Z0-9_]*)\"?|(?:UPDATE|INSERT INTO|DELETE FROM|FROM)\\s+\"?([a-zA-Z_][a-zA-Z0-9_]*)\"?/i);\n if (tableMatch)\n {\n // Schema.Table or just Table\n result.table = tableMatch[2] || tableMatch[3] || tableMatch[1];\n }\n }\n\n // Extract params from \"params: ...\"\n const paramsMatch = message.match(/params:\\s*(.+?)(?:\\n|$)/);\n if (paramsMatch)\n {\n const paramsStr = paramsMatch[1].trim();\n try\n {\n // Try to parse as comma-separated values\n result.params = paramsStr.split(',').map(p => p.trim());\n }\n catch (e)\n {\n result.params = paramsStr;\n }\n }\n\n return Object.keys(result).length > 0 ? result : null;\n}\n\n/**\n * Promise rejection의 호출 스택에서 실제 발생 위치 추출\n *\n * 스택 트레이스에서 다음 정보를 추출:\n * - 실제 에러 발생 파일 경로\n * - 라인 번호\n * - 함수명/메서드명\n * - Repository 정보 (있는 경우)\n *\n * @param error - Error 객체\n * @returns Promise context 정보\n */\nexport function extractPromiseContext(error: Error): Record<string, unknown>\n{\n const context: Record<string, unknown> = {};\n\n if (!error.stack) return context;\n\n const stackLines = error.stack.split('\\n');\n\n // Skip first line (error message) and find first meaningful stack frame\n // Ignore node_modules and internal Node.js paths\n for (let i = 1; i < stackLines.length; i++)\n {\n const line = stackLines[i].trim();\n\n // Skip node_modules and node internals\n if (line.includes('node_modules') || line.includes('node:internal')) continue;\n\n // Extract file, line number, and function name\n // Format: \"at ClassName.methodName (file.ts:line:col)\"\n // or: \"at functionName (file.ts:line:col)\"\n // or: \"at file.ts:line:col\"\n\n const match = line.match(/at\\s+(?:([a-zA-Z_$][\\w$]*(?:\\.[a-zA-Z_$][\\w$]*)*)\\s+)?\\(?([^)]+):(\\d+):(\\d+)\\)?/);\n\n if (match)\n {\n const [, functionName, filePath, lineNumber, columnNumber] = match;\n\n // Extract just the filename from the full path\n const fileNameMatch = filePath.match(/([^/\\\\]+)$/);\n const fileName = fileNameMatch ? fileNameMatch[1] : filePath;\n\n context.file = fileName;\n context.line = parseInt(lineNumber, 10);\n context.column = parseInt(columnNumber, 10);\n\n if (functionName)\n {\n // Check if it's a class method (e.g., \"ClassName.methodName\")\n const methodMatch = functionName.match(/^(.+)\\.([^.]+)$/);\n if (methodMatch)\n {\n const [, className, methodName] = methodMatch;\n\n context.class = className;\n context.method = methodName;\n\n // Check if it's a Repository\n if (className.includes('Repository'))\n {\n context.repository = className;\n }\n }\n else\n {\n context.function = functionName;\n }\n }\n\n // Found first relevant frame, stop here\n break;\n }\n }\n\n return context;\n}\n\n/**\n * Unhandled rejection 에러를 상세하게 포맷팅\n *\n * Promise context와 DB 쿼리 정보를 자동으로 추출하여\n * 에러 발생 위치와 원인을 명확하게 파악할 수 있도록 함\n *\n * @param reason - Rejection 원인 (Error 또는 기타)\n * @param promise - Promise 객체\n * @returns 상세 context 정보\n */\nexport function formatUnhandledRejection(reason: unknown, promise: Promise<unknown>): {\n error: Error;\n context: Record<string, unknown>;\n}\n{\n // Convert reason to Error if not already\n let error: Error;\n if (reason instanceof Error)\n {\n error = reason;\n }\n else if (typeof reason === 'string')\n {\n error = new Error(reason);\n }\n else\n {\n error = new Error(JSON.stringify(reason));\n }\n\n const context: Record<string, unknown> = {\n promise: String(promise),\n };\n\n // Extract promise context (file, line, function, etc.)\n const promiseContext = extractPromiseContext(error);\n if (Object.keys(promiseContext).length > 0)\n {\n context.promiseContext = promiseContext;\n }\n\n // Extract DB query info if available\n const queryInfo = extractQueryInfo(error);\n if (queryInfo)\n {\n context.queryInfo = queryInfo;\n }\n\n return { error, context };\n}","/**\n * Environment Variable Loader\n *\n * Next.js 스타일의 환경변수 파일 로딩 (환경별 분리 지원)\n *\n * 로딩 우선순위 (낮음 -> 높음, 나중 파일이 덮어씀):\n * 1. .env - 기본값 (committed)\n * 2. .env.{NODE_ENV} - 환경별 오버라이드 (committed)\n * 3. .env.local - 로컬 오버라이드 (gitignored, test에서 스킵)\n * 4. .env.{NODE_ENV}.local - 환경별 시크릿 (gitignored)\n * 5. .env.server - 서버 전용 기본값 (committed)\n * 6. .env.server.local - 서버 전용 시크릿 (gitignored)\n *\n * @example\n * ```typescript\n * import { loadEnv } from '@spfn/core/env/loader';\n *\n * // 기본 사용 (NODE_ENV 자동 감지)\n * loadEnv();\n *\n * // 특정 환경 지정\n * loadEnv({ nodeEnv: 'production' });\n *\n * // 서버 레이어 제외 (Next.js 클라이언트용)\n * loadEnv({ server: false });\n * ```\n *\n * @module env/loader\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { parse } from 'dotenv';\nimport { logger } from '@spfn/core/logger';\n\nconst envLogger = logger.child('@spfn/core:env-loader');\n\n/**\n * loadEnv 옵션\n */\nexport interface LoadEnvOptions\n{\n /**\n * 프로젝트 루트 경로\n * @default process.cwd()\n */\n cwd?: string;\n\n /**\n * NODE_ENV 값 (환경별 .env 파일 결정)\n * @default process.env.NODE_ENV || 'local'\n */\n nodeEnv?: string;\n\n /**\n * 서버 전용 파일 포함 여부 (.env.server, .env.server.local)\n * @default true\n */\n server?: boolean;\n\n /**\n * 디버그 모드 (로드된 파일 로깅)\n * @default false\n */\n debug?: boolean;\n\n /**\n * 기존 process.env 값 덮어쓰기 허용\n * @default false\n */\n override?: boolean;\n}\n\n/**\n * 환경변수 로드 결과\n */\nexport interface LoadEnvResult\n{\n /**\n * 로드된 파일 목록\n */\n loadedFiles: string[];\n\n /**\n * 로드된 환경변수 키 목록\n */\n loadedKeys: string[];\n}\n\n/**\n * NODE_ENV에 따른 .env 파일 목록 생성 (우선순위 낮음 -> 높음)\n *\n * 더 구체적인 파일이 승리:\n * - environment > base\n * - server > shared\n * - local > committed\n */\nfunction getEnvFiles(nodeEnv: string, server: boolean): string[]\n{\n const files: string[] = [\n '.env',\n `.env.${nodeEnv}`,\n ];\n\n // test 환경에서는 .env.local 스킵 (테스트 결정론성 보장)\n if (nodeEnv !== 'test')\n {\n files.push('.env.local');\n }\n\n files.push(`.env.${nodeEnv}.local`);\n\n if (server)\n {\n files.push('.env.server');\n files.push('.env.server.local');\n }\n\n return files;\n}\n\n/**\n * 단일 .env 파일 파싱\n */\nfunction parseEnvFile(filePath: string): Record<string, string> | null\n{\n if (!existsSync(filePath))\n {\n return null;\n }\n\n return parse(readFileSync(filePath, 'utf-8'));\n}\n\n/**\n * 프로젝트 루트의 환경변수 파일들을 규칙에 따라 로드\n *\n * 모든 파일을 파싱 후 머지한 뒤 process.env에 한번에 적용.\n * 이미 process.env에 존재하는 키는 덮어쓰지 않음 (플랫폼 주입 보호).\n *\n * @param options - 로드 옵션\n * @returns 로드 결과 (로드된 파일, 키 목록)\n */\nexport function loadEnv(options: LoadEnvOptions = {}): LoadEnvResult\n{\n const {\n cwd = process.cwd(),\n nodeEnv = process.env.NODE_ENV || 'local',\n server = true,\n debug = false,\n override = false,\n } = options;\n\n const envFiles = getEnvFiles(nodeEnv, server);\n const loadedFiles: string[] = [];\n\n // 1) 기존 process.env 키 스냅샷 저장\n const existingKeys = new Set(Object.keys(process.env));\n\n // 2) 모든 .env 파일 파싱 후 머지 (나중 파일이 승리)\n const merged: Record<string, string> = {};\n\n for (const fileName of envFiles)\n {\n const filePath = resolve(cwd, fileName);\n const parsed = parseEnvFile(filePath);\n\n if (parsed === null)\n {\n continue;\n }\n\n loadedFiles.push(fileName);\n Object.assign(merged, parsed);\n }\n\n // 3) 머지된 결과를 process.env에 적용\n const loadedKeys: string[] = [];\n\n for (const [key, value] of Object.entries(merged))\n {\n // 기존 process.env에 이미 있는 키는 스킵 (override가 false일 때)\n if (!override && existingKeys.has(key))\n {\n continue;\n }\n\n process.env[key] = value;\n loadedKeys.push(key);\n }\n\n if (debug && loadedFiles.length > 0)\n {\n envLogger.debug(`Loaded env files: ${loadedFiles.join(', ')}`);\n envLogger.debug(`Loaded ${loadedKeys.length} environment variables`);\n }\n\n return { loadedFiles, loadedKeys };\n}\n\n/**\n * 환경변수가 이미 로드되었는지 확인하는 플래그\n */\nlet isEnvLoaded = false;\n\n/**\n * 환경변수를 한 번만 로드 (중복 호출 방지)\n *\n * @param options - 로드 옵션\n * @returns 로드 결과 (이미 로드된 경우 빈 결과)\n */\nexport function loadEnvOnce(options: LoadEnvOptions = {}): LoadEnvResult\n{\n if (isEnvLoaded)\n {\n return { loadedFiles: [], loadedKeys: [] };\n }\n\n isEnvLoaded = true;\n return loadEnv(options);\n}\n\n/**\n * 환경변수 로드 상태 리셋 (테스트용)\n */\nexport function resetEnvLoadState(): void\n{\n isEnvLoaded = false;\n}\n","/**\n * @deprecated Use `loadEnv` from '@spfn/core/env/loader' instead.\n * This module will be removed in the next major version.\n */\n\nimport { loadEnv } from '../env/loader';\n\nlet warned = false;\n\n/**\n * @deprecated Use `loadEnv()` from '@spfn/core/env/loader' instead.\n */\nexport function loadEnvFiles(): void\n{\n if (!warned)\n {\n warned = true;\n console.warn(\n '[SPFN] loadEnvFiles() is deprecated. Use loadEnv() from \"@spfn/core/env/loader\" instead.'\n );\n }\n\n loadEnv();\n}\n","/**\n * SSE Handler for Hono\n *\n * Creates SSE stream endpoint for event subscription\n *\n * @example\n * ```typescript\n * import { Hono } from 'hono';\n * import { createSSEHandler } from '@spfn/core/event/sse';\n * import { eventRouter } from './events';\n *\n * const app = new Hono();\n *\n * // GET /events/stream?events=userCreated,orderPlaced\n * app.get('/events/stream', createSSEHandler(eventRouter));\n * ```\n */\n\nimport type { Context } from 'hono';\nimport { streamSSE } from 'hono/streaming';\nimport { logger } from '@spfn/core/logger';\nimport type { EventRouterDef, InferEventNames } from '../router';\nimport type { SSEHandlerConfig, SSEHandlerAuthConfig } from './types';\nimport type { SSETokenManager } from './token-manager';\n\nconst sseLogger = logger.child('@spfn/core:sse');\n\n// Extend Hono context with SSE subject\ndeclare module 'hono'\n{\n interface ContextVariableMap\n {\n sseSubject?: string;\n }\n}\n\n/**\n * Create SSE handler for Hono\n *\n * Query parameters:\n * - events: Comma-separated list of event names to subscribe\n * - token: One-time auth token (when auth is enabled)\n *\n * @example\n * ```typescript\n * app.get('/events/stream', createSSEHandler(eventRouter, {\n * pingInterval: 30000,\n * }));\n * ```\n */\nexport function createSSEHandler<TRouter extends EventRouterDef<any>>(\n router: TRouter,\n config: SSEHandlerConfig = {},\n tokenManager?: SSETokenManager\n)\n{\n const {\n pingInterval = 30000,\n auth: authConfig,\n } = config;\n\n return async (c: Context) =>\n {\n // ── 1. Token Authentication ──\n const subject = await authenticateToken(c, tokenManager);\n if (subject === false)\n {\n return c.json({ error: 'Missing token parameter' }, 401);\n }\n if (subject === null)\n {\n return c.json({ error: 'Invalid or expired token' }, 401);\n }\n if (subject)\n {\n c.set('sseSubject', subject);\n }\n\n // ── 2. Parse events from query parameter ──\n const requestedEvents = parseRequestedEvents(c);\n if (!requestedEvents)\n {\n return c.json({ error: 'Missing events parameter' }, 400);\n }\n\n // ── 3. Validate event names ──\n const validEventNames = router.eventNames as string[];\n const invalidEvents = requestedEvents.filter(e => !validEventNames.includes(e));\n\n if (invalidEvents.length > 0)\n {\n return c.json({\n error: 'Invalid event names',\n invalidEvents,\n validEvents: validEventNames,\n }, 400);\n }\n\n // ── 4. Subscription Authorization ──\n const allowedEvents = await authorizeEvents(subject, requestedEvents, authConfig);\n if (allowedEvents === null)\n {\n return c.json({ error: 'Not authorized for any requested events' }, 403);\n }\n\n sseLogger.debug('SSE connection requested', {\n events: allowedEvents,\n subject: subject || undefined,\n clientIp: c.req.header('x-forwarded-for') || c.req.header('x-real-ip'),\n });\n\n // ── 5. SSE Stream ──\n return streamSSE(c, async (stream) =>\n {\n const unsubscribes: (() => void)[] = [];\n let messageId = 0;\n\n for (const eventName of allowedEvents as InferEventNames<TRouter>[])\n {\n const eventDef = router.events[eventName];\n\n if (!eventDef)\n {\n continue;\n }\n\n const unsubscribe = eventDef.subscribe((payload: unknown) =>\n {\n // ── Payload Filtering ──\n if (subject && authConfig?.filter?.[eventName as string])\n {\n if (!authConfig.filter[eventName as string](subject, payload))\n {\n return;\n }\n }\n\n messageId++;\n\n const message = {\n event: eventName,\n data: payload,\n };\n\n sseLogger.debug('SSE sending event', {\n event: eventName,\n messageId,\n });\n\n // Fire-and-forget in sync callback\n void stream.writeSSE({\n id: String(messageId),\n event: eventName as string,\n data: JSON.stringify(message),\n });\n });\n\n unsubscribes.push(unsubscribe);\n }\n\n sseLogger.info('SSE connection established', {\n events: allowedEvents,\n subscriptionCount: unsubscribes.length,\n });\n\n // Send initial connection message\n await stream.writeSSE({\n event: 'connected',\n data: JSON.stringify({\n subscribedEvents: allowedEvents,\n timestamp: Date.now(),\n }),\n });\n\n // Keep-alive ping\n const pingTimer = setInterval(() =>\n {\n // Fire-and-forget in sync callback\n void stream.writeSSE({\n event: 'ping',\n data: JSON.stringify({ timestamp: Date.now() }),\n });\n }, pingInterval);\n\n // Wait for client disconnect using abort signal\n const abortSignal = c.req.raw.signal;\n\n while (!abortSignal.aborted)\n {\n await stream.sleep(pingInterval);\n }\n\n // Cleanup\n clearInterval(pingTimer);\n unsubscribes.forEach(fn => fn());\n\n sseLogger.info('SSE connection closed', {\n events: allowedEvents,\n });\n }, async (err: Error) =>\n {\n sseLogger.error('SSE stream error', {\n error: err.message,\n });\n });\n };\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Authenticate via one-time token\n * @returns subject string if authenticated, undefined if no auth required,\n * false if token missing, null if token invalid/expired\n */\nasync function authenticateToken(\n c: Context,\n tokenManager?: SSETokenManager\n): Promise<string | undefined | false | null>\n{\n if (!tokenManager)\n {\n return undefined;\n }\n\n const token = c.req.query('token');\n if (!token)\n {\n return false;\n }\n\n return await tokenManager.verify(token);\n}\n\n/**\n * Parse requested events from query parameter\n */\nfunction parseRequestedEvents(c: Context): string[] | null\n{\n const eventsParam = c.req.query('events');\n if (!eventsParam)\n {\n return null;\n }\n\n return eventsParam.split(',').map(e => e.trim());\n}\n\n/**\n * Authorize event subscription via auth hook\n * @returns allowed events array, or null if rejected\n */\nasync function authorizeEvents(\n subject: string | undefined,\n requestedEvents: string[],\n authConfig?: SSEHandlerAuthConfig\n): Promise<string[] | null>\n{\n if (!subject || !authConfig?.authorize)\n {\n return requestedEvents;\n }\n\n const allowed = await authConfig.authorize(subject, requestedEvents);\n\n if (allowed.length === 0)\n {\n return null;\n }\n\n return allowed;\n}\n","/**\n * SSE Token Manager\n *\n * Auth-agnostic token issuance and verification for SSE connections.\n * Issues one-time-use tokens with TTL for Token Exchange pattern.\n *\n * @example\n * ```typescript\n * const manager = new SSETokenManager({ ttl: 30000 });\n *\n * // Issue token for authenticated user\n * const token = await manager.issue('user-123');\n *\n * // Verify and consume token (one-time use)\n * const subject = await manager.verify(token); // 'user-123'\n * const again = await manager.verify(token); // null (already consumed)\n *\n * // Cleanup on shutdown\n * manager.destroy();\n * ```\n */\n\nimport { randomBytes } from 'crypto';\n\n/**\n * Minimal cache client interface (compatible with ioredis Redis | Cluster)\n */\ntype CacheClient = {\n set(key: string, value: string, ...args: any[]): Promise<any>;\n getdel?(key: string): Promise<string | null>;\n get(key: string): Promise<string | null>;\n del(key: string | string[]): Promise<number>;\n};\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Stored SSE token data\n */\nexport interface SSEToken\n{\n token: string;\n subject: string;\n expiresAt: number;\n}\n\n/**\n * Token storage interface\n *\n * Implement this for custom storage backends (e.g., Redis for multi-instance).\n */\nexport interface SSETokenStore\n{\n /** Store a token */\n set(token: string, data: SSEToken): Promise<void>;\n\n /** Get and delete a token (one-time use) */\n consume(token: string): Promise<SSEToken | null>;\n\n /** Remove expired tokens */\n cleanup(): Promise<void>;\n}\n\n/**\n * SSETokenManager configuration\n */\nexport interface SSETokenManagerConfig\n{\n /**\n * Token time-to-live in milliseconds\n * @default 30000\n */\n ttl?: number;\n\n /**\n * Custom token store (default: in-memory Map)\n */\n store?: SSETokenStore;\n\n /**\n * Cleanup interval in milliseconds\n * @default 60000\n */\n cleanupInterval?: number;\n}\n\n// ============================================================================\n// InMemoryTokenStore\n// ============================================================================\n\nclass InMemoryTokenStore implements SSETokenStore\n{\n private tokens = new Map<string, SSEToken>();\n\n async set(token: string, data: SSEToken): Promise<void>\n {\n this.tokens.set(token, data);\n }\n\n async consume(token: string): Promise<SSEToken | null>\n {\n const data = this.tokens.get(token);\n if (!data)\n {\n return null;\n }\n\n this.tokens.delete(token);\n return data;\n }\n\n async cleanup(): Promise<void>\n {\n const now = Date.now();\n\n for (const [token, data] of this.tokens)\n {\n if (data.expiresAt <= now)\n {\n this.tokens.delete(token);\n }\n }\n }\n}\n\n// ============================================================================\n// CacheTokenStore (Redis/Valkey)\n// ============================================================================\n\n/**\n * Redis/Valkey-backed token store for multi-instance deployments.\n *\n * Uses SET EX for automatic TTL expiry and GETDEL for atomic one-time consumption.\n * No cleanup needed — Redis handles expiration automatically.\n *\n * @example\n * ```typescript\n * import { getCache } from '@spfn/core/cache';\n *\n * const cache = getCache();\n * if (cache) {\n * const store = new CacheTokenStore(cache);\n * const manager = new SSETokenManager({ store });\n * }\n * ```\n */\nexport class CacheTokenStore implements SSETokenStore\n{\n private prefix = 'sse:token:';\n\n constructor(private cache: CacheClient) {}\n\n async set(token: string, data: SSEToken): Promise<void>\n {\n const ttlSeconds = Math.max(1, Math.ceil((data.expiresAt - Date.now()) / 1000));\n await this.cache.set(\n this.prefix + token,\n JSON.stringify(data),\n 'EX',\n ttlSeconds,\n );\n }\n\n async consume(token: string): Promise<SSEToken | null>\n {\n const key = this.prefix + token;\n\n // GETDEL (Redis 6.2+) for atomic consume, fallback to GET+DEL\n let raw: string | null = null;\n\n if (this.cache.getdel)\n {\n raw = await this.cache.getdel(key);\n }\n else\n {\n raw = await this.cache.get(key);\n if (raw)\n {\n await this.cache.del(key);\n }\n }\n\n if (!raw)\n {\n return null;\n }\n\n return JSON.parse(raw) as SSEToken;\n }\n\n async cleanup(): Promise<void>\n {\n // No-op: Redis TTL handles expiration automatically\n }\n}\n\n// ============================================================================\n// SSETokenManager\n// ============================================================================\n\nexport class SSETokenManager\n{\n private store: SSETokenStore;\n private ttl: number;\n private cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(config?: SSETokenManagerConfig)\n {\n this.ttl = config?.ttl ?? 30000;\n this.store = config?.store ?? new InMemoryTokenStore();\n\n const cleanupInterval = config?.cleanupInterval ?? 60000;\n this.cleanupTimer = setInterval(() => void this.store.cleanup(), cleanupInterval);\n this.cleanupTimer.unref();\n }\n\n /**\n * Issue a new one-time-use token for the given subject\n */\n async issue(subject: string): Promise<string>\n {\n const token = randomBytes(32).toString('hex');\n\n await this.store.set(token, {\n token,\n subject,\n expiresAt: Date.now() + this.ttl,\n });\n\n return token;\n }\n\n /**\n * Verify and consume a token\n * @returns subject string if valid, null if invalid/expired/already consumed\n */\n async verify(token: string): Promise<string | null>\n {\n const data = await this.store.consume(token);\n\n if (!data || data.expiresAt <= Date.now())\n {\n return null;\n }\n\n return data.subject;\n }\n\n /**\n * Cleanup timer and resources\n */\n destroy(): void\n {\n if (this.cleanupTimer)\n {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n }\n}\n","import { logger } from \"@spfn/core/logger\";\n\nexport const serverLogger = logger.child('@spfn/core:server');","/**\n * Shutdown Manager\n *\n * Manages graceful shutdown with drain behavior.\n * All tracked operations must complete before shutdown proceeds.\n *\n * Features:\n * - Hook registry: Multiple modules can register independent cleanup handlers\n * - Operation tracking: Long-running tasks are awaited during shutdown (drain)\n * - State management: isShuttingDown() for rejecting new work\n */\n\nimport { serverLogger } from './logger';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ShutdownHookOptions\n{\n /**\n * Timeout for this hook in milliseconds\n * If the hook exceeds this time, it is skipped and the next hook runs\n * @default 10000 (10s)\n */\n timeout?: number;\n\n /**\n * Execution order (lower runs first)\n * @default 100\n */\n order?: number;\n}\n\ninterface ShutdownHook\n{\n name: string;\n handler: () => Promise<void>;\n timeout: number;\n order: number;\n}\n\ninterface TrackedOperation\n{\n name: string;\n startedAt: number;\n}\n\ntype ShutdownState = 'running' | 'draining' | 'closed';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_HOOK_TIMEOUT = 10_000;\nconst DEFAULT_HOOK_ORDER = 100;\nconst DRAIN_POLL_INTERVAL = 500;\n\n// ============================================================================\n// ShutdownManager\n// ============================================================================\n\nexport class ShutdownManager\n{\n private state: ShutdownState = 'running';\n private hooks: ShutdownHook[] = [];\n private operations = new Map<string, TrackedOperation>();\n private operationCounter = 0;\n\n /**\n * Register a shutdown hook\n *\n * Hooks run in order during shutdown, after all tracked operations drain.\n * Each hook has its own timeout — failure does not block subsequent hooks.\n *\n * @example\n * shutdown.onShutdown('ai-service', async () => {\n * await aiService.cancelPending();\n * }, { timeout: 30000, order: 10 });\n */\n onShutdown(\n name: string,\n handler: () => Promise<void>,\n options?: ShutdownHookOptions\n ): void\n {\n this.hooks.push({\n name,\n handler,\n timeout: options?.timeout ?? DEFAULT_HOOK_TIMEOUT,\n order: options?.order ?? DEFAULT_HOOK_ORDER,\n });\n\n // Keep sorted by order\n this.hooks.sort((a, b) => a.order - b.order);\n\n serverLogger.debug(`Shutdown hook registered: ${name}`, {\n order: options?.order ?? DEFAULT_HOOK_ORDER,\n timeout: `${options?.timeout ?? DEFAULT_HOOK_TIMEOUT}ms`,\n });\n }\n\n /**\n * Track a long-running operation\n *\n * During shutdown (drain phase), the process waits for ALL tracked\n * operations to complete before proceeding with cleanup.\n *\n * If shutdown has already started, the operation is rejected immediately.\n *\n * @returns The operation result (pass-through)\n *\n * @example\n * const result = await shutdown.trackOperation(\n * 'ai-generate',\n * aiService.generate(prompt)\n * );\n */\n async trackOperation<T>(name: string, operation: Promise<T>): Promise<T>\n {\n if (this.state !== 'running')\n {\n throw new Error(`Cannot start operation '${name}': server is shutting down`);\n }\n\n const id = `${name}-${++this.operationCounter}`;\n\n this.operations.set(id, {\n name,\n startedAt: Date.now(),\n });\n\n serverLogger.debug(`Operation tracked: ${id}`, {\n activeOperations: this.operations.size,\n });\n\n try\n {\n return await operation;\n }\n finally\n {\n this.operations.delete(id);\n\n serverLogger.debug(`Operation completed: ${id}`, {\n activeOperations: this.operations.size,\n });\n }\n }\n\n /**\n * Whether the server is shutting down\n *\n * Use this to reject new work early (e.g., return 503 in route handlers).\n */\n isShuttingDown(): boolean\n {\n return this.state !== 'running';\n }\n\n /**\n * Number of currently active tracked operations\n */\n getActiveOperationCount(): number\n {\n return this.operations.size;\n }\n\n /**\n * Mark shutdown as started immediately\n *\n * Call this at the very beginning of the shutdown sequence so that:\n * - Health check returns 503 right away\n * - trackOperation() rejects new work\n * - isShuttingDown() returns true\n */\n beginShutdown(): void\n {\n if (this.state !== 'running')\n {\n return;\n }\n this.state = 'draining';\n serverLogger.info('Shutdown manager: state set to draining');\n }\n\n /**\n * Execute the full shutdown sequence\n *\n * 1. State → draining (reject new operations)\n * 2. Wait for all tracked operations to complete (drain)\n * 3. Run shutdown hooks in order\n * 4. State → closed\n *\n * @param drainTimeout - Max time to wait for operations to drain (ms)\n */\n async execute(drainTimeout: number): Promise<void>\n {\n // beginShutdown() may have already been called\n if (this.state === 'closed')\n {\n serverLogger.warn('ShutdownManager.execute() called but already closed');\n return;\n }\n\n this.state = 'draining';\n serverLogger.info('Shutdown manager: draining started', {\n activeOperations: this.operations.size,\n registeredHooks: this.hooks.length,\n drainTimeout: `${drainTimeout}ms`,\n });\n\n // Phase 1: Drain — wait for all tracked operations to complete\n await this.drain(drainTimeout);\n\n // Phase 2: Run shutdown hooks in order\n await this.executeHooks();\n\n this.state = 'closed';\n serverLogger.info('Shutdown manager: all hooks executed');\n }\n\n // ========================================================================\n // Private\n // ========================================================================\n\n /**\n * Wait for all tracked operations to complete, up to drainTimeout\n */\n private async drain(drainTimeout: number): Promise<void>\n {\n if (this.operations.size === 0)\n {\n serverLogger.info('Shutdown manager: no active operations, drain skipped');\n return;\n }\n\n serverLogger.info(`Shutdown manager: waiting for ${this.operations.size} operations to drain...`);\n\n const deadline = Date.now() + drainTimeout;\n\n while (this.operations.size > 0 && Date.now() < deadline)\n {\n const remaining = deadline - Date.now();\n const ops = Array.from(this.operations.values()).map(op => ({\n name: op.name,\n elapsed: `${Math.round((Date.now() - op.startedAt) / 1000)}s`,\n }));\n\n serverLogger.info('Shutdown manager: drain in progress', {\n activeOperations: this.operations.size,\n remainingTimeout: `${Math.round(remaining / 1000)}s`,\n operations: ops,\n });\n\n await sleep(Math.min(DRAIN_POLL_INTERVAL, remaining));\n }\n\n if (this.operations.size > 0)\n {\n const abandoned = Array.from(this.operations.values()).map(op => op.name);\n serverLogger.warn('Shutdown manager: drain timeout — abandoning operations', {\n abandoned,\n });\n }\n else\n {\n serverLogger.info('Shutdown manager: all operations drained successfully');\n }\n }\n\n /**\n * Execute registered shutdown hooks in order\n */\n private async executeHooks(): Promise<void>\n {\n if (this.hooks.length === 0)\n {\n return;\n }\n\n serverLogger.info(`Shutdown manager: executing ${this.hooks.length} hooks...`);\n\n for (const hook of this.hooks)\n {\n serverLogger.debug(`Shutdown hook [${hook.name}] starting (timeout: ${hook.timeout}ms)`);\n\n try\n {\n await withTimeout(\n hook.handler(),\n hook.timeout,\n `Shutdown hook '${hook.name}' timeout after ${hook.timeout}ms`\n );\n serverLogger.info(`Shutdown hook [${hook.name}] completed`);\n }\n catch (error)\n {\n serverLogger.error(\n `Shutdown hook [${hook.name}] failed`,\n error as Error\n );\n // Continue with next hook — don't block shutdown\n }\n }\n }\n}\n\n// ============================================================================\n// Singleton\n// ============================================================================\n\nlet instance: ShutdownManager | null = null;\n\n/**\n * Get the global ShutdownManager instance\n *\n * Available after server starts. Use this to register shutdown hooks\n * or track long-running operations.\n *\n * @example\n * import { getShutdownManager } from '@spfn/core/server';\n *\n * const shutdown = getShutdownManager();\n *\n * // Register cleanup\n * shutdown.onShutdown('my-service', async () => {\n * await myService.close();\n * });\n *\n * // Track long operation\n * await shutdown.trackOperation('ai-task', longRunningPromise);\n */\nexport function getShutdownManager(): ShutdownManager\n{\n if (!instance)\n {\n instance = new ShutdownManager();\n }\n return instance;\n}\n\n/**\n * Reset the singleton (for testing)\n * @internal\n */\nexport function resetShutdownManager(): void\n{\n instance = null;\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void>\n{\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeout: number,\n message: string\n): Promise<T>\n{\n let timeoutId: NodeJS.Timeout | undefined;\n\n return Promise.race([\n promise.finally(() =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n }),\n new Promise<never>((_, reject) =>\n {\n timeoutId = setTimeout(() =>\n {\n reject(new Error(message));\n }, timeout);\n }),\n ]);\n}\n","import type { Hono, Handler, MiddlewareHandler } from 'hono';\nimport type { Server } from 'http';\nimport { Agent, setGlobalDispatcher } from 'undici';\nimport { getDatabase } from '@spfn/core/db';\nimport { getCache } from '@spfn/core/cache';\nimport { env } from '@spfn/core/config';\nimport { getShutdownManager } from './shutdown-manager';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface ServiceStatus\n{\n status: string;\n error?: string;\n}\n\ninterface HealthCheckResponse\n{\n status: 'ok' | 'degraded';\n timestamp: string;\n services?: {\n database: ServiceStatus;\n redis: ServiceStatus;\n };\n}\n\ninterface StartupConfig\n{\n middleware: {\n logger: boolean;\n cors: boolean;\n errorHandler: boolean;\n custom: number;\n };\n healthCheck: {\n enabled: boolean;\n path?: string;\n detailed?: boolean;\n };\n hooks: {\n beforeRoutes: boolean;\n afterRoutes: boolean;\n };\n timeout: {\n request: string;\n keepAlive: string;\n headers: string;\n };\n shutdown: {\n timeout: string;\n };\n}\n\n// ============================================================================\n// Functions\n// ============================================================================\n\nexport function createHealthCheckHandler(detailed: boolean): Handler\n{\n return async (c) =>\n {\n // Return 503 immediately during shutdown (for k8s readiness probe)\n const shutdownManager = getShutdownManager();\n if (shutdownManager.isShuttingDown())\n {\n return c.json({\n status: 'shutting_down',\n timestamp: new Date().toISOString(),\n }, 503);\n }\n\n const response: HealthCheckResponse = {\n status: 'ok',\n timestamp: new Date().toISOString(),\n };\n\n if (detailed)\n {\n let dbStatus: string = 'unknown';\n let dbError: string | undefined;\n\n // Try to get database instance\n try\n {\n const db = getDatabase();\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 catch (error)\n {\n // Database not initialized\n dbStatus = 'not_initialized';\n dbError = 'Database not available';\n }\n\n const redis = getCache();\n let redisStatus: string = redis ? 'unknown' : 'not_initialized';\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 =\n (dbStatus === 'error' || dbStatus === 'not_initialized') ||\n (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 ?? env.SERVER_TIMEOUT,\n keepAlive: config?.keepAlive ?? env.SERVER_KEEPALIVE_TIMEOUT,\n headers: config?.headers ?? env.SERVER_HEADERS_TIMEOUT,\n };\n}\n\nexport function getShutdownTimeout(config?: { timeout?: number }): number\n{\n return config?.timeout ?? env.SHUTDOWN_TIMEOUT;\n}\n\nexport function getFetchTimeoutConfig(config?: {\n connect?: number;\n headers?: number;\n body?: number;\n}): {\n connect: number;\n headers: number;\n body: number;\n}\n{\n return {\n connect: config?.connect ?? env.FETCH_CONNECT_TIMEOUT,\n headers: config?.headers ?? env.FETCH_HEADERS_TIMEOUT,\n body: config?.body ?? env.FETCH_BODY_TIMEOUT,\n };\n}\n\nexport function applyGlobalFetchTimeouts(timeouts: {\n connect: number;\n headers: number;\n body: number;\n}): void\n{\n const agent = new Agent({\n connect: { timeout: timeouts.connect },\n headersTimeout: timeouts.headers,\n bodyTimeout: timeouts.body,\n });\n setGlobalDispatcher(agent);\n}\n\nexport function buildMiddlewareOrder(config: {\n middleware?: {\n logger?: boolean;\n cors?: boolean;\n errorHandler?: boolean;\n };\n use?: MiddlewareHandler[];\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?: MiddlewareHandler[];\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): StartupConfig\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 ?? (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 ?? env.SHUTDOWN_TIMEOUT}ms`,\n },\n };\n}\n","/**\n * Create Hono Server\n *\n * Creates and configures a Hono application instance.\n */\n\nimport { Hono, type Context } from 'hono';\nimport { cors } from 'hono/cors';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\n\nimport { registerRoutes, type RegisteredRoute } from '@spfn/core/route';\nimport { ErrorHandler, RequestLogger } from '@spfn/core/middleware';\nimport { createSSEHandler } from '../event/sse/handler';\nimport { SSETokenManager, CacheTokenStore } from '../event/sse/token-manager';\nimport { createHealthCheckHandler } from './helpers';\nimport { serverLogger } from './logger';\n\nimport type { ServerConfig, AppFactory } from './types';\n\n// Extend Hono context with error handler flag\ndeclare module 'hono'\n{\n interface ContextVariableMap\n {\n errorHandlerEnabled?: boolean;\n }\n}\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');\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 // Determine which path exists to avoid duplicate checks\n const actualPath = existsSync(appPath) ? appPath : appJsPath;\n const appModule = await import(actualPath);\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 // Register routes (if provided via config)\n if (config?.routes)\n {\n const routes = registerRoutes(app, config.routes, config.middlewares);\n logRegisteredRoutes(routes, config?.debug ?? false);\n }\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 if (Array.isArray(config?.use))\n {\n config.use.forEach(mw => app.use('*', mw));\n }\n\n // 4. Health check endpoint\n registerHealthCheckEndpoint(app, config);\n\n // 5. beforeRoutes hook from config\n await executeBeforeRoutesHook(app, config);\n\n // 6. Load routes\n await loadAppRoutes(app, config);\n\n // 7. Register SSE endpoint (if events router provided)\n await registerSSEEndpoint(app, config);\n\n // 8. afterRoutes hook from config\n await executeAfterRoutesHook(app, config);\n\n // 9. Error handler\n if (enableErrorHandler)\n {\n app.onError(ErrorHandler({ onError: config?.middleware?.onError }));\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)\n {\n // Only apply cors if config.cors is not explicitly false\n // This handles both config.cors = undefined and config.cors = {...options}\n const corsOptions = config?.cors !== false ? config?.cors : undefined;\n app.use('*', cors(corsOptions));\n }\n}\n\nfunction registerHealthCheckEndpoint(app: Hono, config?: ServerConfig): void\n{\n const healthCheckConfig = config?.healthCheck ?? {};\n const healthCheckEnabled = healthCheckConfig.enabled !== false;\n const healthCheckPath = healthCheckConfig.path ?? '/health';\n const healthCheckDetailed = healthCheckConfig.detailed\n ?? process.env.NODE_ENV === 'development';\n\n if (healthCheckEnabled)\n {\n app.get(healthCheckPath, createHealthCheckHandler(healthCheckDetailed));\n serverLogger.debug(`Health check endpoint enabled at ${healthCheckPath}`);\n }\n}\n\nasync function executeBeforeRoutesHook(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (config?.lifecycle?.beforeRoutes)\n {\n await config.lifecycle.beforeRoutes(app);\n }\n}\n\nasync function loadAppRoutes(app: Hono, config?: ServerConfig): Promise<void>\n{\n const debug = isDebugMode(config);\n\n // Register define-route based routes (if provided)\n if (config?.routes)\n {\n const routes = registerRoutes(app, config.routes, config.middlewares);\n logRegisteredRoutes(routes, debug);\n }\n else if (debug)\n {\n serverLogger.warn('⚠️ No routes configured. Use defineServerConfig().routes() to register routes.');\n }\n}\n\n/**\n * Log registered routes in a formatted table\n */\nfunction logRegisteredRoutes(routes: RegisteredRoute[], debug: boolean): void\n{\n if (routes.length === 0)\n {\n if (debug)\n {\n serverLogger.warn('⚠️ No routes registered');\n }\n return;\n }\n\n // Sort routes by path for better readability\n const sortedRoutes = [...routes].sort((a, b) => a.path.localeCompare(b.path));\n\n // Calculate max method length for alignment\n const maxMethodLen = Math.max(...sortedRoutes.map(r => r.method.length));\n\n // Build route list string\n const routeLines = sortedRoutes.map(r =>\n ` ${r.method.padEnd(maxMethodLen)} ${r.path}`\n ).join('\\n');\n\n serverLogger.info(`✓ Routes registered (${routes.length}):\\n${routeLines}`);\n}\n\nasync function executeAfterRoutesHook(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (config?.lifecycle?.afterRoutes)\n {\n await config.lifecycle.afterRoutes(app);\n }\n}\n\n/**\n * Register SSE endpoint for event streaming\n *\n * When auth is enabled:\n * - POST /events/token — issues one-time SSE token (protected by config.middlewares)\n * - GET /events/stream?token=...&events=... — SSE stream (token verified)\n */\nasync function registerSSEEndpoint(app: Hono, config?: ServerConfig): Promise<void>\n{\n if (!config?.events)\n {\n return;\n }\n\n const eventsConfig = config.eventsConfig ?? {};\n const streamPath = eventsConfig.path ?? '/events/stream';\n const authConfig = eventsConfig.auth;\n const debug = isDebugMode(config);\n\n let tokenManager: SSETokenManager | undefined;\n\n if (authConfig?.enabled)\n {\n // Auto-detect cache for token store (multi-instance support)\n let store = authConfig.store;\n if (!store)\n {\n try\n {\n const { getCache } = await import('@spfn/core/cache');\n const cache = getCache();\n if (cache)\n {\n store = new CacheTokenStore(cache as any);\n if (debug)\n {\n serverLogger.info('SSE token store: cache (Redis/Valkey)');\n }\n }\n }\n catch\n {\n // Cache module not available, use in-memory\n }\n }\n\n const externalManager = typeof authConfig.tokenManager === 'function'\n ? authConfig.tokenManager()\n : authConfig.tokenManager;\n\n tokenManager = externalManager ?? new SSETokenManager({\n ttl: authConfig.tokenTtl,\n store,\n });\n\n // Derive token path: /events/stream → /events/token\n const tokenPath = streamPath.replace(/\\/[^/]+$/, '/token');\n\n // Apply config.middlewares (e.g., authenticate) to token endpoint\n const mwHandlers = (config.middlewares ?? []).map(mw => mw.handler);\n const getSubject = authConfig.getSubject\n ?? ((c: Context) => (c.get('auth') as Record<string, string> | undefined)?.userId ?? null);\n\n app.post(tokenPath, ...mwHandlers, async (c: Context) =>\n {\n const subject = getSubject(c);\n if (!subject)\n {\n return c.json({ error: 'Unable to identify subject' }, 401);\n }\n\n const token = await tokenManager!.issue(subject);\n return c.json({ token });\n });\n\n if (debug)\n {\n serverLogger.info(`✓ SSE token endpoint registered at POST ${tokenPath}`);\n }\n }\n\n // Register SSE stream handler\n app.get(streamPath, createSSEHandler(config.events, eventsConfig, tokenManager));\n\n if (debug)\n {\n const eventNames = config.events.eventNames as string[];\n serverLogger.info(`✓ SSE endpoint registered at ${streamPath}`, {\n events: eventNames,\n auth: !!authConfig?.enabled,\n });\n }\n}\n\n/**\n * Determine if debug mode is enabled\n */\nfunction isDebugMode(config?: ServerConfig): boolean\n{\n return config?.debug ?? process.env.NODE_ENV === 'development';\n}","/**\n * pg-boss Wrapper\n *\n * Manages pg-boss instance lifecycle\n */\n\nimport PgBoss from 'pg-boss';\nimport { logger } from '@spfn/core/logger';\n\nconst jobLogger = logger.child('@spfn/core:job');\n\n/**\n * Check if connection string uses SSL without certificate verification\n *\n * pg library verifies certificates by default even with sslmode=require.\n * For require/prefer modes (no explicit verification), we disable cert checking\n * to support self-signed certificates.\n */\nfunction requiresSSLWithoutVerification(connectionString: string): boolean\n{\n try\n {\n const url = new URL(connectionString);\n const sslmode = url.searchParams.get('sslmode');\n return sslmode === 'require' || sslmode === 'prefer';\n }\n catch\n {\n return false;\n }\n}\n\n/**\n * Remove sslmode parameter from connection string URL\n *\n * pg driver interprets sslmode=require as verify-full, which overrides\n * the ssl option object. Stripping it lets us control SSL via the ssl option only.\n */\nfunction stripSslModeFromUrl(connectionString: string): string\n{\n const url = new URL(connectionString);\n url.searchParams.delete('sslmode');\n return url.toString();\n}\n\n/**\n * globalThis keys for cross-module-cache singleton (ESM/CJS share same instance)\n */\nconst BOSS_KEY = Symbol.for('spfn:boss-instance');\nconst CONFIG_KEY = Symbol.for('spfn:boss-config');\n\nconst g = globalThis as any;\n\nfunction getBossInstance(): PgBoss | null\n{\n return g[BOSS_KEY] ?? null;\n}\n\nfunction setBossInstance(instance: PgBoss | null): void\n{\n g[BOSS_KEY] = instance;\n}\n\nfunction getBossConfig(): BossConfig | null\n{\n return g[CONFIG_KEY] ?? null;\n}\n\nfunction setBossConfig(config: BossConfig | null): void\n{\n g[CONFIG_KEY] = config;\n}\n\n/**\n * Options for pg-boss initialization\n *\n * @example\n * ```typescript\n * await initBoss({\n * connectionString: process.env.DATABASE_URL,\n * schema: 'spfn_queue',\n * clearOnStart: process.env.NODE_ENV === 'development',\n * });\n * ```\n */\nexport interface BossOptions\n{\n /**\n * PostgreSQL connection string\n *\n * @example 'postgresql://user:password@localhost:5432/mydb'\n */\n connectionString: string;\n\n /**\n * Schema name for pg-boss tables\n *\n * pg-boss creates its own tables in this schema.\n *\n * @default 'spfn_queue'\n */\n schema?: string;\n\n /**\n * Maintenance interval in seconds\n *\n * pg-boss runs maintenance tasks (cleanup, archiving) at this interval.\n *\n * @default 120\n */\n maintenanceIntervalSeconds?: number;\n\n /**\n * Monitor state changes interval in seconds\n *\n * When set, pg-boss emits state change events at this interval.\n *\n * @default undefined (disabled)\n */\n monitorIntervalSeconds?: number;\n\n /**\n * Clear all pending/scheduled jobs on startup\n *\n * Useful for development mode to start with a clean queue.\n * Should be false in production.\n *\n * @default false\n */\n clearOnStart?: boolean;\n}\n\n/**\n * @deprecated Use BossOptions instead\n */\nexport type BossConfig = BossOptions;\n\n/**\n * Initialize pg-boss with the given configuration\n *\n * Must be called before registerJobs(). Typically handled by defineServerConfig().\n *\n * @param options - pg-boss configuration options\n * @returns The pg-boss instance\n *\n * @example\n * ```typescript\n * const boss = await initBoss({\n * connectionString: process.env.DATABASE_URL!,\n * schema: 'spfn_queue',\n * });\n * ```\n */\nexport async function initBoss(options: BossOptions): Promise<PgBoss>\n{\n const existing = getBossInstance();\n if (existing)\n {\n jobLogger.warn('pg-boss already initialized, returning existing instance');\n return existing;\n }\n\n jobLogger.info('Initializing pg-boss...');\n\n setBossConfig(options);\n\n const needsSSL = requiresSSLWithoutVerification(options.connectionString);\n\n const pgBossOptions: PgBoss.ConstructorOptions = {\n // pg 드라이버가 URL의 sslmode=require를 verify-full로 해석해서\n // ssl 옵션을 무시하므로, URL에서 sslmode를 빼고 ssl 객체만 전달\n connectionString: needsSSL\n ? stripSslModeFromUrl(options.connectionString)\n : options.connectionString,\n schema: options.schema ?? 'spfn_queue',\n maintenanceIntervalSeconds: options.maintenanceIntervalSeconds ?? 120,\n };\n\n if (needsSSL)\n {\n pgBossOptions.ssl = { rejectUnauthorized: false };\n }\n\n // Only set monitorIntervalSeconds if explicitly provided (must be >= 1)\n if (options.monitorIntervalSeconds !== undefined && options.monitorIntervalSeconds >= 1)\n {\n pgBossOptions.monitorIntervalSeconds = options.monitorIntervalSeconds;\n }\n\n const boss = new PgBoss(pgBossOptions);\n\n // Event handlers\n boss.on('error', (error) =>\n {\n jobLogger.error('pg-boss error:', error);\n });\n\n await boss.start();\n\n setBossInstance(boss);\n\n jobLogger.info('pg-boss started successfully');\n\n return boss;\n}\n\n/**\n * Get the current pg-boss instance\n */\nexport function getBoss(): PgBoss | null\n{\n return getBossInstance();\n}\n\n/**\n * Stop pg-boss gracefully\n */\nexport async function stopBoss(): Promise<void>\n{\n const boss = getBossInstance();\n if (!boss)\n {\n return;\n }\n\n jobLogger.info('Stopping pg-boss...');\n\n try\n {\n await boss.stop({ graceful: true, timeout: 30000 });\n jobLogger.info('pg-boss stopped gracefully');\n }\n catch (error)\n {\n jobLogger.error('Error stopping pg-boss:', error);\n throw error;\n }\n finally\n {\n setBossInstance(null);\n setBossConfig(null);\n }\n}\n\n/**\n * Check if pg-boss is initialized and running\n */\nexport function isBossRunning(): boolean\n{\n return getBossInstance() !== null;\n}\n\n/**\n * Check if jobs should be cleared on start\n */\nexport function shouldClearOnStart(): boolean\n{\n return getBossConfig()?.clearOnStart ?? false;\n}\n","/**\n * Job Router\n *\n * Groups job definitions for registration with the server\n */\n\nimport type { JobDef, JobRouter, JobRouterEntry } from './types';\n\n/**\n * Type guard to check if value is a JobDef\n */\nexport function isJobDef(value: unknown): value is JobDef<any>\n{\n return (\n value !== null &&\n typeof value === 'object' &&\n 'name' in value &&\n 'handler' in value &&\n 'send' in value &&\n 'run' in value\n );\n}\n\n/**\n * Type guard to check if value is a JobRouter\n */\nexport function isJobRouter(value: unknown): value is JobRouter<any>\n{\n return (\n value !== null &&\n typeof value === 'object' &&\n 'jobs' in value &&\n '_jobs' in value\n );\n}\n\n/**\n * Define a job router to group jobs together\n *\n * @example\n * ```typescript\n * // Flat structure\n * export const jobRouter = defineJobRouter({\n * sendWelcomeEmail,\n * dailyReport,\n * initCache,\n * });\n *\n * // Nested structure\n * export const jobRouter = defineJobRouter({\n * email: defineJobRouter({\n * sendWelcome: sendWelcomeEmailJob,\n * sendReset: sendResetPasswordJob,\n * }),\n * reports: defineJobRouter({\n * daily: dailyReportJob,\n * weekly: weeklyReportJob,\n * }),\n * });\n *\n * // Mixed\n * export const jobRouter = defineJobRouter({\n * initCache, // flat\n * email: defineJobRouter({ ... }), // nested\n * });\n * ```\n */\nexport function defineJobRouter<\n TJobs extends Record<string, JobRouterEntry>\n>(jobs: TJobs): JobRouter<TJobs>\n{\n return {\n jobs,\n _jobs: jobs,\n };\n}\n\n/**\n * Collect all JobDefs from a JobRouter (including nested)\n */\nexport function collectJobs(\n router: JobRouter<any>,\n prefix = ''\n): JobDef<any>[]\n{\n const jobs: JobDef<any>[] = [];\n\n for (const [key, value] of Object.entries(router.jobs))\n {\n const name = prefix ? `${prefix}.${key}` : key;\n\n if (isJobRouter(value))\n {\n // Nested router - recurse\n jobs.push(...collectJobs(value, name));\n }\n else if (isJobDef(value))\n {\n jobs.push(value);\n }\n }\n\n return jobs;\n}\n","/**\n * Job Registration\n *\n * Registers jobs with pg-boss\n */\n\nimport type PgBoss from 'pg-boss';\nimport { logger } from '@spfn/core/logger';\nimport type { JobDef, JobOptions, JobRouter } from './types';\nimport type { EventDef } from '@spfn/core/event';\nimport { collectJobs } from './job-router';\nimport { getBoss, shouldClearOnStart } from './boss';\n\nconst jobLogger = logger.child('@spfn/core:job');\n\n/**\n * Get the pg-boss queue name for an event\n */\nexport function getEventQueueName(eventName: string): string\n{\n return `event:${eventName}`;\n}\n\n/**\n * Build default pg-boss options for a job\n */\nfunction getDefaultJobOptions(options?: JobOptions): PgBoss.SendOptions\n{\n return {\n retryLimit: options?.retryLimit ?? 3,\n retryDelay: options?.retryDelay ?? 1000,\n expireInSeconds: options?.expireInSeconds ?? 300,\n };\n}\n\n/**\n * Register all jobs from a JobRouter with pg-boss\n *\n * This function:\n * 1. Collects all jobs from the router (including nested routers)\n * 2. Optionally clears existing jobs (if clearOnStart is enabled)\n * 3. Registers each job's worker handler with pg-boss\n * 4. Sets up cron schedules for scheduled jobs\n * 5. Queues runOnce jobs\n * 6. Connects event subscriptions to job queues\n *\n * @param router - JobRouter containing job definitions\n *\n * @example\n * ```typescript\n * // Define jobs\n * const sendEmail = job('send-email')\n * .input(Type.Object({ to: Type.String() }))\n * .handler(async (input) => { ... });\n *\n * const dailyReport = job('daily-report')\n * .cron('0 9 * * *')\n * .handler(async () => { ... });\n *\n * // Create router\n * const jobRouter = defineJobRouter({ sendEmail, dailyReport });\n *\n * // Initialize pg-boss first\n * await initBoss({ connectionString: process.env.DATABASE_URL! });\n *\n * // Register jobs\n * await registerJobs(jobRouter);\n * ```\n */\nexport async function registerJobs(router: JobRouter<any>): Promise<void>\n{\n const boss = getBoss();\n if (!boss)\n {\n throw new Error(\n 'pg-boss not initialized. Call initBoss() before registerJobs()'\n );\n }\n\n const jobs = collectJobs(router);\n const clearOnStart = shouldClearOnStart();\n\n jobLogger.info(`Registering ${jobs.length} job(s)...`);\n\n // Clear existing jobs if requested (useful for development)\n if (clearOnStart)\n {\n jobLogger.info('Clearing existing jobs before registration...');\n for (const job of jobs)\n {\n // Clear job queue\n await boss.deleteAllJobs(job.name);\n\n // Also clear event queue if subscribed\n if (job.subscribedEvent)\n {\n const eventQueue = getEventQueueName(job.subscribedEvent);\n await boss.deleteAllJobs(eventQueue);\n }\n }\n jobLogger.info('Existing jobs cleared');\n }\n\n for (const job of jobs)\n {\n await registerJob(job);\n }\n\n jobLogger.info('All jobs registered successfully');\n}\n\n/**\n * Create queue if not exists (required for pg-boss v11+)\n */\nasync function ensureQueue(boss: PgBoss, queueName: string): Promise<void>\n{\n await boss.createQueue(queueName);\n}\n\n/**\n * Register worker handler for a job\n */\nasync function registerWorker(\n boss: PgBoss,\n job: JobDef<any>,\n queueName: string\n): Promise<void>\n{\n // Ensure queue exists before registering worker\n await ensureQueue(boss, queueName);\n\n await boss.work(\n queueName,\n { batchSize: 1 },\n async (jobs) =>\n {\n for (const pgBossJob of jobs)\n {\n jobLogger.debug(`[Job:${job.name}] Executing...`, { jobId: pgBossJob.id });\n\n const startTime = Date.now();\n\n try\n {\n if (job.inputSchema)\n {\n await (job.handler as (input: unknown) => Promise<void>)(pgBossJob.data);\n }\n else\n {\n await (job.handler as () => Promise<void>)();\n }\n\n const duration = Date.now() - startTime;\n jobLogger.info(`[Job:${job.name}] Completed in ${duration}ms`, {\n jobId: pgBossJob.id,\n duration,\n });\n }\n catch (error)\n {\n const duration = Date.now() - startTime;\n jobLogger.error(`[Job:${job.name}] Failed after ${duration}ms`, {\n jobId: pgBossJob.id,\n duration,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n }\n );\n}\n\n/**\n * Connect event to pg-boss queue\n */\nfunction connectEventToQueue(\n boss: PgBoss,\n job: JobDef<any>,\n queueName: string\n): void\n{\n if (!job._subscribedEventDef)\n {\n return;\n }\n\n const eventDef = job._subscribedEventDef as EventDef<any>;\n eventDef._registerJobQueue(queueName, async (queue, payload) =>\n {\n await boss.send(queue, payload as object, getDefaultJobOptions(job.options));\n });\n\n jobLogger.debug(`[Job:${job.name}] Connected to event: ${job.subscribedEvent}`);\n}\n\n/**\n * Register cron schedule for a job\n */\nasync function registerCronSchedule(boss: PgBoss, job: JobDef<any>): Promise<void>\n{\n if (!job.cronExpression)\n {\n return;\n }\n\n jobLogger.debug(`[Job:${job.name}] Scheduling cron: ${job.cronExpression}`);\n\n // Ensure queue exists for cron jobs (uses job.name as queue)\n await ensureQueue(boss, job.name);\n\n await boss.schedule(\n job.name,\n job.cronExpression,\n {},\n getDefaultJobOptions(job.options)\n );\n\n jobLogger.info(`[Job:${job.name}] Cron scheduled: ${job.cronExpression}`);\n}\n\n/**\n * Queue a runOnce job\n */\nasync function queueRunOnceJob(boss: PgBoss, job: JobDef<any>): Promise<void>\n{\n if (!job.runOnce)\n {\n return;\n }\n\n jobLogger.debug(`[Job:${job.name}] Queuing runOnce job`);\n\n // Ensure queue exists for runOnce jobs (uses job.name as queue)\n await ensureQueue(boss, job.name);\n\n await boss.send(\n job.name,\n {},\n {\n ...getDefaultJobOptions(job.options),\n singletonKey: `runOnce:${job.name}`,\n }\n );\n\n jobLogger.info(`[Job:${job.name}] runOnce job queued`);\n}\n\n/**\n * Register a single job with pg-boss\n */\nasync function registerJob(job: JobDef<any>): Promise<void>\n{\n const boss = getBoss();\n if (!boss)\n {\n throw new Error('pg-boss not initialized');\n }\n\n const queueName = job.subscribedEvent\n ? getEventQueueName(job.subscribedEvent)\n : job.name;\n\n jobLogger.debug(`Registering job: ${job.name}`, {\n queueName,\n subscribedEvent: job.subscribedEvent,\n });\n\n await registerWorker(boss, job, queueName);\n connectEventToQueue(boss, job, queueName);\n await registerCronSchedule(boss, job);\n await queueRunOnceJob(boss, job);\n\n jobLogger.debug(`Job registered: ${job.name}`);\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';\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}","/**\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 type { Hono } from 'hono';\nimport type { Server } from 'http';\nimport { join } from 'path';\n\nimport { closeCache, initCache } from '@spfn/core/cache';\nimport { closeDatabase, initDatabase, getDatabase } from '@spfn/core/db';\nimport { initBoss, stopBoss, registerJobs } from '../job';\nimport { serverLogger } from './logger';\nimport { printBanner } from './banner';\nimport { createServer } from './create-server';\nimport { loadEnv } from '../env/loader';\nimport {\n applyServerTimeouts,\n applyGlobalFetchTimeouts,\n buildMiddlewareOrder,\n buildStartupConfig,\n getFetchTimeoutConfig,\n getShutdownTimeout,\n getTimeoutConfig,\n} from './helpers';\nimport { getShutdownManager, resetShutdownManager } from './shutdown-manager';\n\nimport type { ServerConfig, ServerInstance } from './types';\nimport { validateServerConfig } from './validation';\nimport { env } from '@spfn/core/config';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_MAX_LISTENERS = 15;\n\nconst TIMEOUTS = {\n SERVER_CLOSE: 5000,\n DATABASE_CLOSE: 5000,\n REDIS_CLOSE: 5000,\n PRODUCTION_ERROR_SHUTDOWN: 10000,\n} as const;\n\nconst CONFIG_FILE_PATHS = [\n '.spfn/server/server.config.mjs',\n '.spfn/server/server.config',\n 'src/server/server.config',\n 'src/server/server.config.ts',\n] as const;\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface InfrastructureConfig\n{\n database: boolean;\n redis: boolean;\n}\n\n/**\n * Shutdown state manager to prevent race conditions\n */\ninterface ShutdownState\n{\n isShuttingDown: boolean;\n}\n\n// ============================================================================\n// Module State\n// ============================================================================\n\n/**\n * Track whether process-level shutdown handlers have been registered\n * Process handlers should only be registered once\n */\nlet processHandlersRegistered = false;\n\n// ============================================================================\n// Main Entry Point\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 loadEnv();\n\n const finalConfig = await loadAndMergeConfig(config);\n const { host, port, debug } = finalConfig;\n\n validateServerConfig(finalConfig);\n\n // Validate required config values\n if (!host || !port)\n {\n throw new Error('Server host and port are required');\n }\n\n if (debug)\n {\n logMiddlewareOrder(finalConfig);\n }\n\n // Create shutdown state for this server instance\n const shutdownState: ShutdownState = {\n isShuttingDown: false,\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 const fetchTimeouts = getFetchTimeoutConfig(finalConfig.fetchTimeout);\n applyGlobalFetchTimeouts(fetchTimeouts);\n\n logServerTimeouts(timeouts);\n printBanner({\n mode: debug ? 'Development' : 'Production',\n host,\n port,\n });\n\n logServerStarted(debug, host, port, finalConfig, timeouts);\n\n const shutdownServer = createShutdownHandler(server as Server, finalConfig, shutdownState);\n const shutdown = createGracefulShutdown(shutdownServer, finalConfig, shutdownState);\n\n // Register process-level handlers\n registerProcessHandlers(shutdown);\n\n const serverInstance: ServerInstance = {\n server,\n app,\n config: finalConfig,\n close: async () =>\n {\n serverLogger.info('Manual server shutdown requested');\n await shutdownServer();\n },\n };\n\n // Execute afterStart hook from config\n if (finalConfig.lifecycle?.afterStart)\n {\n serverLogger.debug('Executing afterStart hook...');\n try\n {\n await finalConfig.lifecycle.afterStart(serverInstance);\n }\n catch (error)\n {\n serverLogger.error('afterStart hook failed', error as Error);\n // Don't throw - server is already running\n // Just log the error and continue\n }\n }\n\n return serverInstance;\n }\n catch (error)\n {\n const err = error as Error;\n serverLogger.error('Server initialization failed', err);\n\n await cleanupOnFailure(finalConfig);\n\n throw error;\n }\n}\n\n// ============================================================================\n// Configuration Loading\n// ============================================================================\n\nasync function loadAndMergeConfig(config?: ServerConfig): Promise<ServerConfig>\n{\n const cwd = process.cwd();\n let fileConfig: ServerConfig = {};\n let loadedConfigPath: string | null = null;\n\n // Try loading config files in priority order\n for (const configPath of CONFIG_FILE_PATHS)\n {\n const fullPath = join(cwd, configPath);\n if (existsSync(fullPath))\n {\n try\n {\n const configModule = await import(fullPath);\n fileConfig = configModule.default ?? {};\n loadedConfigPath = configPath;\n break;\n }\n catch (error)\n {\n serverLogger.error(`Failed to load config from ${configPath} - file exists but import failed`, error as Error);\n // Continue trying other config files instead of failing\n }\n }\n }\n\n if (loadedConfigPath)\n {\n serverLogger.debug(`Loaded configuration from ${loadedConfigPath}`);\n }\n else\n {\n serverLogger.debug('No configuration file found, using defaults');\n }\n\n return {\n ...fileConfig,\n ...config,\n port: config?.port ?? fileConfig?.port ?? env.PORT,\n host: config?.host ?? fileConfig?.host ?? env.HOST,\n };\n}\n\n// ============================================================================\n// Infrastructure Management\n// ============================================================================\n\n/**\n * Determine which infrastructure components should be initialized\n */\nfunction getInfrastructureConfig(config: ServerConfig): InfrastructureConfig\n{\n return {\n database: config.infrastructure?.database !== false,\n redis: config.infrastructure?.redis !== false,\n };\n}\n\nasync function initializeInfrastructure(config: ServerConfig): Promise<void>\n{\n if (config.lifecycle?.beforeInfrastructure)\n {\n serverLogger.debug('Executing beforeInfrastructure hook...');\n await config.lifecycle.beforeInfrastructure(config);\n }\n\n const infraConfig = getInfrastructureConfig(config);\n\n if (infraConfig.database)\n {\n serverLogger.debug('Initializing database...');\n await initDatabase(config.database);\n }\n else\n {\n serverLogger.debug('Database initialization disabled');\n }\n\n if (infraConfig.redis)\n {\n serverLogger.debug('Initializing Redis...');\n await initCache();\n }\n else\n {\n serverLogger.debug('Redis initialization disabled');\n }\n\n if (config.lifecycle?.afterInfrastructure)\n {\n serverLogger.debug('Executing afterInfrastructure hook...');\n await config.lifecycle.afterInfrastructure();\n }\n\n // Initialize jobs if configured\n if (config.jobs)\n {\n const dbUrl = env.DATABASE_URL;\n if (!dbUrl)\n {\n throw new Error(\n 'Jobs require database connection. ' +\n 'Ensure DATABASE_URL is set or database is enabled.'\n );\n }\n\n serverLogger.debug('Initializing pg-boss...');\n await initBoss({\n connectionString: dbUrl,\n ...config.jobsConfig,\n });\n\n serverLogger.debug('Registering jobs...');\n await registerJobs(config.jobs);\n }\n\n // Initialize workflows if configured\n if (config.workflows)\n {\n const infraConfig = getInfrastructureConfig(config);\n if (!infraConfig.database)\n {\n throw new Error(\n 'Workflows require database connection. ' +\n 'Ensure database is enabled in infrastructure config.'\n );\n }\n\n serverLogger.debug('Initializing workflow engine...');\n config.workflows._init(\n getDatabase(),\n config.workflowsConfig\n );\n serverLogger.info('Workflow engine initialized');\n }\n}\n\n// ============================================================================\n// HTTP Server Management\n// ============================================================================\n\nfunction startHttpServer(app: Hono, host: string, port: number): ReturnType<typeof serve>\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 logMiddlewareOrder(config: ServerConfig): void\n{\n const middlewareOrder = buildMiddlewareOrder(config);\n serverLogger.debug('Middleware execution order', {\n order: middlewareOrder,\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\n// ============================================================================\n// Graceful Shutdown\n// ============================================================================\n\nfunction createShutdownHandler(\n server: Server,\n config: ServerConfig,\n shutdownState: ShutdownState\n): () => Promise<void>\n{\n return async () =>\n {\n // Prevent re-entry\n if (shutdownState.isShuttingDown)\n {\n serverLogger.debug('Shutdown already in progress for this instance, skipping');\n return;\n }\n\n shutdownState.isShuttingDown = true;\n\n const shutdownTimeout = getShutdownTimeout(config.shutdown);\n const shutdownManager = getShutdownManager();\n\n // Immediately mark as draining so health check returns 503\n // and trackOperation() rejects new work\n shutdownManager.beginShutdown();\n\n // ── Phase 1: Stop accepting new connections ──\n serverLogger.info('Phase 1: Closing HTTP server (stop accepting new connections)...');\n await closeHttpServer(server);\n\n // ── Phase 2: Stop pg-boss (stop accepting new jobs) ──\n if (config.jobs)\n {\n serverLogger.info('Phase 2: Stopping pg-boss...');\n try\n {\n await stopBoss();\n serverLogger.info('pg-boss stopped');\n }\n catch (error)\n {\n serverLogger.error('pg-boss stop failed', error as Error);\n }\n }\n\n // ── Phase 3: Drain — wait for all tracked operations to complete ──\n // Use 80% of remaining shutdown timeout for drain + hooks\n const drainTimeout = Math.floor(shutdownTimeout * 0.8);\n serverLogger.info(`Phase 3: Draining tracked operations (timeout: ${drainTimeout}ms)...`);\n await shutdownManager.execute(drainTimeout);\n\n // ── Phase 4: Execute beforeShutdown lifecycle hook (backward compat) ──\n if (config.lifecycle?.beforeShutdown)\n {\n serverLogger.info('Phase 4: Executing beforeShutdown lifecycle hook...');\n try\n {\n await config.lifecycle.beforeShutdown();\n }\n catch (error)\n {\n serverLogger.error('beforeShutdown lifecycle hook failed', error as Error);\n }\n }\n\n // ── Phase 5: Close infrastructure (DB, Redis) ──\n serverLogger.info('Phase 5: Closing infrastructure...');\n const infraConfig = getInfrastructureConfig(config);\n\n if (infraConfig.database)\n {\n await closeInfrastructure(closeDatabase, 'Database', TIMEOUTS.DATABASE_CLOSE);\n }\n\n if (infraConfig.redis)\n {\n await closeInfrastructure(closeCache, 'Redis', TIMEOUTS.REDIS_CLOSE);\n }\n\n serverLogger.info('Server shutdown completed');\n };\n}\n\n/**\n * Close HTTP server with timeout\n */\nasync function closeHttpServer(server: Server): Promise<void>\n{\n let timeoutId: NodeJS.Timeout | undefined;\n\n await Promise.race([\n new Promise<void>((resolve, reject) =>\n {\n server.close((err) =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n\n if (err)\n {\n serverLogger.error('HTTP server close error', err);\n reject(err);\n }\n else\n {\n serverLogger.info('HTTP server closed');\n resolve();\n }\n });\n }),\n new Promise<void>((_, reject) =>\n {\n timeoutId = setTimeout(() =>\n {\n reject(new Error(`HTTP server close timeout after ${TIMEOUTS.SERVER_CLOSE}ms`));\n }, TIMEOUTS.SERVER_CLOSE);\n }),\n ]).catch((error) =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n serverLogger.warn('HTTP server close timeout, forcing shutdown', error as Error);\n });\n}\n\n/**\n * Close infrastructure component with timeout\n */\nasync function closeInfrastructure(\n closeFn: () => Promise<void>,\n name: string,\n timeout: number\n): Promise<void>\n{\n let timeoutId: NodeJS.Timeout | undefined;\n\n try\n {\n await Promise.race([\n closeFn().then(() =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n }),\n new Promise<void>((_, reject) =>\n {\n timeoutId = setTimeout(() =>\n {\n reject(new Error(`${name} close timeout after ${timeout}ms`));\n }, timeout);\n }),\n ]);\n serverLogger.info(`${name} connections closed successfully`);\n }\n catch (error)\n {\n if (timeoutId) clearTimeout(timeoutId);\n serverLogger.error(`${name} close failed or timed out`, error as Error);\n // Continue with shutdown even if close fails\n }\n}\n\nfunction createGracefulShutdown(\n shutdownServer: () => Promise<void>,\n config: ServerConfig,\n shutdownState: ShutdownState\n): (signal: string) => Promise<void>\n{\n return async (signal: string) =>\n {\n // Prevent re-entry\n if (shutdownState.isShuttingDown)\n {\n serverLogger.warn(`${signal} received but shutdown already in progress, ignoring`);\n return;\n }\n\n serverLogger.info(`${signal} received, starting graceful shutdown...`);\n\n const shutdownTimeout = getShutdownTimeout(config.shutdown);\n let timeoutId: NodeJS.Timeout | undefined;\n\n try\n {\n await Promise.race([\n shutdownServer().then(() =>\n {\n if (timeoutId) clearTimeout(timeoutId);\n }),\n new Promise<never>((_, reject) =>\n {\n timeoutId = setTimeout(() =>\n {\n reject(new Error(`Graceful shutdown timeout after ${shutdownTimeout}ms`));\n }, shutdownTimeout);\n }),\n ]);\n\n if (timeoutId) clearTimeout(timeoutId);\n serverLogger.info('Graceful shutdown completed successfully');\n process.exit(0);\n }\n catch (error)\n {\n if (timeoutId) clearTimeout(timeoutId);\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\n// ============================================================================\n// Error Handlers\n// ============================================================================\n\n/**\n * Handle process errors - log and continue, don't kill the server\n */\nfunction handleProcessError(errorType: string): void\n{\n serverLogger.warn(`${errorType} occurred - server continues running. Check logs above for details.`);\n}\n\nfunction registerProcessHandlers(\n shutdown: (signal: string) => Promise<void>\n): void\n{\n // Prevent duplicate registration\n if (processHandlersRegistered)\n {\n serverLogger.debug('Process handlers already registered, skipping');\n return;\n }\n\n processHandlersRegistered = true;\n\n // Increase max listeners to prevent warnings in development with hot reload\n const currentMax = process.getMaxListeners();\n if (currentMax < DEFAULT_MAX_LISTENERS)\n {\n process.setMaxListeners(DEFAULT_MAX_LISTENERS);\n }\n\n process.on('SIGTERM', () =>\n {\n shutdown('SIGTERM').catch((error) =>\n {\n serverLogger.error('SIGTERM handler failed', error as Error);\n process.exit(1);\n });\n });\n\n process.on('SIGINT', () =>\n {\n shutdown('SIGINT').catch((error) =>\n {\n serverLogger.error('SIGINT handler failed', error as Error);\n process.exit(1);\n });\n });\n\n process.on('uncaughtException', (error) =>\n {\n // Enhanced logging for EADDRINUSE errors\n if (error.message?.includes('EADDRINUSE'))\n {\n serverLogger.error('Port conflict detected - detailed trace:', error, {\n code: (error as any).code,\n port: (error as any).port,\n address: (error as any).address,\n syscall: (error as any).syscall,\n });\n }\n else\n {\n serverLogger.error('Uncaught exception', error);\n }\n\n handleProcessError('UNCAUGHT_EXCEPTION');\n });\n\n process.on('unhandledRejection', (reason, promise) =>\n {\n // Enhanced error logging with promise context extraction\n if (reason instanceof Error)\n {\n // Import formatUnhandledRejection dynamically to avoid circular deps\n import('../logger/formatters').then(({ formatUnhandledRejection }) =>\n {\n const { error, context } = formatUnhandledRejection(reason, promise);\n\n serverLogger.error('Unhandled promise rejection', error, context);\n }).catch(() =>\n {\n // Fallback if formatUnhandledRejection fails\n serverLogger.error('Unhandled promise rejection', reason, {\n promise,\n });\n });\n }\n else\n {\n serverLogger.error('Unhandled promise rejection', {\n reason,\n promise,\n });\n }\n\n handleProcessError('UNHANDLED_REJECTION');\n });\n\n serverLogger.debug('Process-level shutdown handlers registered successfully');\n}\n\n// ============================================================================\n// Cleanup\n// ============================================================================\n\nasync function cleanupOnFailure(config: ServerConfig): Promise<void>\n{\n try\n {\n serverLogger.debug('Cleaning up after initialization failure...');\n\n // Only cleanup resources that were enabled for initialization\n const infraConfig = getInfrastructureConfig(config);\n\n if (infraConfig.database)\n {\n await closeInfrastructure(closeDatabase, 'Database', TIMEOUTS.DATABASE_CLOSE);\n }\n\n if (infraConfig.redis)\n {\n await closeInfrastructure(closeCache, 'Redis', TIMEOUTS.REDIS_CLOSE);\n }\n\n resetShutdownManager();\n serverLogger.debug('Cleanup completed');\n }\n catch (cleanupError)\n {\n serverLogger.error('Cleanup failed', cleanupError as Error);\n }\n}","/**\n * Server Config Builder\n *\n * Provides a fluent API for building server configuration\n */\n\nimport type { MiddlewareHandler } from 'hono';\nimport type { ServerConfig } from './types';\nimport type { Router, NamedMiddleware } from '@spfn/core/route';\nimport type { JobRouter, BossOptions } from '../job';\nimport type { EventRouterDef } from '../event/router';\nimport type { SSEHandlerConfig, SSEAuthConfig } from '../event/sse/types';\nimport { serverLogger } from './logger';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype Lifecycle = NonNullable<ServerConfig['lifecycle']>;\ntype LifecycleKey = keyof Lifecycle;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nfunction collectHooks<K extends LifecycleKey>(\n lifecycles: Lifecycle[],\n key: K\n): NonNullable<Lifecycle[K]>[]\n{\n return lifecycles\n .map(lc => lc[key])\n .filter((hook): hook is NonNullable<Lifecycle[K]> => hook !== undefined);\n}\n\nfunction createMergedHook<T extends (...args: any[]) => void | Promise<void>>(\n hooks: T[]\n): T | undefined\n{\n if (hooks.length === 0)\n {\n return undefined;\n }\n\n return (async (...args: Parameters<T>) =>\n {\n for (const hook of hooks)\n {\n await hook(...args);\n }\n }) as T;\n}\n\nexport class ServerConfigBuilder\n{\n private config: ServerConfig = {};\n private lifecycles: NonNullable<ServerConfig['lifecycle']>[] = [];\n\n /**\n * Set server port\n */\n port(port: number): this\n {\n this.config.port = port;\n return this;\n }\n\n /**\n * Set server hostname\n */\n host(host: string): this\n {\n this.config.host = host;\n return this;\n }\n\n /**\n * Set CORS configuration\n */\n cors(cors: ServerConfig['cors']): this\n {\n this.config.cors = cors;\n return this;\n }\n\n /**\n * Configure built-in middleware\n */\n middleware(middleware: ServerConfig['middleware']): this\n {\n this.config.middleware = middleware;\n return this;\n }\n\n /**\n * Add custom middleware\n */\n use(handlers: MiddlewareHandler[]): this\n {\n this.config.use = handlers;\n return this;\n }\n\n /**\n * Add named middlewares for route-level skip control\n */\n middlewares(middlewares: ServerConfig['middlewares']): this\n {\n this.config.middlewares = middlewares;\n return this;\n }\n\n /**\n * Register define-route based router\n *\n * Automatically applies:\n * - Global middlewares from router._globalMiddlewares (via .use())\n * - Package routers from router._packageRouters (via .packages())\n *\n * @example\n * ```typescript\n * const appRouter = defineRouter({\n * getUser: route.get('/users/:id')...\n * })\n * .packages([authRouter, cmsAppRouter])\n * .use([authMiddleware]);\n *\n * export default defineServerConfig()\n * .routes(appRouter) // middlewares auto-applied\n * .build();\n * ```\n */\n routes(router: Router<any>): this\n {\n this.config.routes = router;\n\n // Collect all global middlewares from router and package routers\n const allGlobalMiddlewares: NamedMiddleware[] = [];\n\n // Add main router's global middlewares\n if (router._globalMiddlewares?.length > 0)\n {\n allGlobalMiddlewares.push(...router._globalMiddlewares);\n }\n\n // Add package routers' global middlewares\n if (router._packageRouters?.length > 0)\n {\n for (const pkgRouter of router._packageRouters)\n {\n if (pkgRouter._globalMiddlewares?.length > 0)\n {\n allGlobalMiddlewares.push(...pkgRouter._globalMiddlewares);\n }\n }\n }\n\n // Merge with existing middlewares\n if (allGlobalMiddlewares.length > 0)\n {\n this.config.middlewares = [\n ...(this.config.middlewares || []),\n ...allGlobalMiddlewares,\n ];\n }\n\n return this;\n }\n\n /**\n * Register background jobs router\n *\n * @example\n * ```typescript\n * import { job, defineJobRouter } from '@spfn/core/job';\n *\n * const sendEmail = job('send-email')\n * .input(Type.Object({ to: Type.String() }))\n * .handler(async (input) => { ... });\n *\n * const jobRouter = defineJobRouter({ sendEmail });\n *\n * export default defineServerConfig()\n * .routes(appRouter)\n * .jobs(jobRouter)\n * .build();\n * ```\n */\n jobs(router: JobRouter<any>, config?: Omit<BossOptions, 'connectionString'>): this\n {\n this.config.jobs = router;\n if (config)\n {\n this.config.jobsConfig = config;\n }\n return this;\n }\n\n /**\n * Register event router for SSE (Server-Sent Events)\n *\n * Enables real-time event streaming to frontend clients.\n * Events defined with defineEvent() can be subscribed by:\n * - Backend: .subscribe() for internal handlers\n * - Jobs: .on(event) for background processing\n * - Frontend: SSE stream for real-time updates\n *\n * @example\n * ```typescript\n * import { defineEvent, defineEventRouter } from '@spfn/core/event';\n *\n * const userCreated = defineEvent('user.created', Type.Object({\n * userId: Type.String(),\n * }));\n *\n * const eventRouter = defineEventRouter({ userCreated });\n *\n * export default defineServerConfig()\n * .routes(appRouter)\n * .events(eventRouter) // → GET /events/stream\n * .build();\n *\n * // Custom path\n * .events(eventRouter, { path: '/sse' })\n * ```\n */\n events<TRouter extends EventRouterDef<any>>(\n router: TRouter,\n config?: Omit<SSEHandlerConfig, 'auth'> & { path?: string; auth?: SSEAuthConfig<TRouter> }\n ): this\n {\n this.config.events = router;\n if (config)\n {\n // SSEAuthConfig<TRouter> is assignable to SSEHandlerAuthConfig at runtime\n this.config.eventsConfig = config as SSEHandlerConfig & { path?: string };\n }\n return this;\n }\n\n /**\n * Enable/disable debug mode\n */\n debug(enabled: boolean): this\n {\n this.config.debug = enabled;\n return this;\n }\n\n /**\n * Configure database settings\n */\n database(database: ServerConfig['database']): this\n {\n this.config.database = database;\n return this;\n }\n\n /**\n * Configure server timeout settings\n */\n timeout(timeout: ServerConfig['timeout']): this\n {\n this.config.timeout = timeout;\n return this;\n }\n\n /**\n * Configure graceful shutdown settings\n */\n shutdown(shutdown: ServerConfig['shutdown']): this\n {\n this.config.shutdown = shutdown;\n return this;\n }\n\n /**\n * Configure health check endpoint\n */\n healthCheck(healthCheck: ServerConfig['healthCheck']): this\n {\n this.config.healthCheck = healthCheck;\n return this;\n }\n\n /**\n * Configure infrastructure initialization\n */\n infrastructure(infrastructure: ServerConfig['infrastructure']): this\n {\n this.config.infrastructure = infrastructure;\n return this;\n }\n\n /**\n * Register workflow router for workflow orchestration\n *\n * Automatically initializes the workflow engine after database is ready.\n *\n * @example\n * ```typescript\n * import { defineWorkflowRouter } from '@spfn/workflow';\n *\n * const workflowRouter = defineWorkflowRouter([\n * provisionTenant,\n * deprovisionTenant,\n * ]);\n *\n * export default defineServerConfig()\n * .routes(appRouter)\n * .workflows(workflowRouter)\n * .build();\n * ```\n */\n workflows(\n router: ServerConfig['workflows'],\n config?: ServerConfig['workflowsConfig']\n ): this\n {\n this.config.workflows = router;\n if (config)\n {\n this.config.workflowsConfig = config;\n }\n return this;\n }\n\n /**\n * Configure lifecycle hooks\n * Can be called multiple times - hooks will be executed in registration order\n */\n lifecycle(lifecycle: ServerConfig['lifecycle']): this\n {\n if (lifecycle)\n {\n this.lifecycles.push(lifecycle);\n }\n return this;\n }\n\n /**\n * Build and return the final configuration\n */\n build(): ServerConfig\n {\n if (this.lifecycles.length > 0)\n {\n serverLogger.info('Merging lifecycles', { count: this.lifecycles.length });\n this.config.lifecycle = this.mergeLifecycles();\n }\n\n return this.config;\n }\n\n private mergeLifecycles(): Lifecycle\n {\n return {\n beforeInfrastructure: createMergedHook(\n collectHooks(this.lifecycles, 'beforeInfrastructure')\n ),\n afterInfrastructure: createMergedHook(\n collectHooks(this.lifecycles, 'afterInfrastructure')\n ),\n beforeRoutes: createMergedHook(\n collectHooks(this.lifecycles, 'beforeRoutes')\n ),\n afterRoutes: createMergedHook(\n collectHooks(this.lifecycles, 'afterRoutes')\n ),\n afterStart: createMergedHook(\n collectHooks(this.lifecycles, 'afterStart')\n ),\n beforeShutdown: createMergedHook(\n collectHooks(this.lifecycles, 'beforeShutdown')\n ),\n };\n }\n}\n\n/**\n * Create a new server configuration builder\n *\n * @example\n * ```typescript\n * // server.config.ts\n * import { defineServerConfig, route, defineRouter } from '@spfn/core/server';\n * import { Type } from '@sinclair/typebox';\n *\n * const appRouter = defineRouter({\n * getUser: route.get('/users/:id')\n * .input({ params: Type.Object({ id: Type.String() }) })\n * .handler(async (c) => {\n * const { params } = await c.data();\n * return { id: params.id, name: 'John' };\n * }),\n * });\n *\n * export default defineServerConfig()\n * .port(3000)\n * .routes(appRouter)\n * .middleware({ logger: true, cors: true })\n * .debug(true)\n * .build();\n * ```\n */\nexport function defineServerConfig(): ServerConfigBuilder\n{\n return new ServerConfigBuilder();\n}"]}
|
|
@@ -153,6 +153,29 @@ interface SSEHandlerAuthConfig {
|
|
|
153
153
|
* Custom token store (e.g., Redis for multi-instance)
|
|
154
154
|
*/
|
|
155
155
|
store?: SSETokenStore;
|
|
156
|
+
/**
|
|
157
|
+
* External token manager instance or lazy resolver.
|
|
158
|
+
*
|
|
159
|
+
* When provided, the SSE system uses this manager instead of creating its own.
|
|
160
|
+
* Useful for sharing a single token manager with auth package's one-time token system.
|
|
161
|
+
*
|
|
162
|
+
* Use a function when the manager is not available at module load time
|
|
163
|
+
* (e.g. initialized in a lifecycle hook that runs after config evaluation).
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* import { getOneTimeTokenManager } from '@spfn/auth/server';
|
|
168
|
+
*
|
|
169
|
+
* // Lazy resolver (recommended — avoids timing issues)
|
|
170
|
+
* .events(eventRouter, {
|
|
171
|
+
* auth: {
|
|
172
|
+
* enabled: true,
|
|
173
|
+
* tokenManager: () => getOneTimeTokenManager(),
|
|
174
|
+
* },
|
|
175
|
+
* })
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
tokenManager?: SSETokenManager | (() => SSETokenManager);
|
|
156
179
|
/**
|
|
157
180
|
* Extract subject (user ID) from Hono context
|
|
158
181
|
* @default (c) => c.get('auth')?.userId ?? null
|
|
@@ -199,6 +222,7 @@ interface SSEAuthConfig<TRouter extends EventRouterDef<any>> {
|
|
|
199
222
|
enabled?: boolean;
|
|
200
223
|
tokenTtl?: number;
|
|
201
224
|
store?: SSETokenStore;
|
|
225
|
+
tokenManager?: SSETokenManager | (() => SSETokenManager);
|
|
202
226
|
getSubject?: (c: Context) => string | null;
|
|
203
227
|
authorize?: (subject: string, events: InferEventNames<TRouter>[]) => Promise<InferEventNames<TRouter>[]> | InferEventNames<TRouter>[];
|
|
204
228
|
filter?: {
|
package/docs/database.md
CHANGED
|
@@ -221,6 +221,30 @@ await runWithTransaction(async () => {
|
|
|
221
221
|
});
|
|
222
222
|
```
|
|
223
223
|
|
|
224
|
+
### After-Commit Hooks
|
|
225
|
+
|
|
226
|
+
Schedule side effects to run only after the transaction commits.
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { onAfterCommit } from '@spfn/core/db';
|
|
230
|
+
|
|
231
|
+
async function submitRequest(spaceId: string, chatId: string)
|
|
232
|
+
{
|
|
233
|
+
const publication = await publicationRepo.create({ spaceId, chatId });
|
|
234
|
+
await requestRepo.updateStatusAtomically(requestId, 'submitted');
|
|
235
|
+
|
|
236
|
+
// Runs after commit, fire-and-forget
|
|
237
|
+
onAfterCommit(() => generateArticle(spaceId, chatId, publication.id));
|
|
238
|
+
|
|
239
|
+
return publication;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
- Inside transaction: queued, executed after root commit
|
|
244
|
+
- Outside transaction: executed immediately
|
|
245
|
+
- Nested transactions: callbacks bubble up to root
|
|
246
|
+
- Errors are logged, never thrown
|
|
247
|
+
|
|
224
248
|
### Get Current Transaction
|
|
225
249
|
|
|
226
250
|
Access the current transaction context.
|