@spfn/core 0.1.0-alpha.41 → 0.1.0-alpha.42

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.
@@ -59,8 +59,12 @@ declare class ContractClient {
59
59
  use(interceptor: RequestInterceptor): void;
60
60
  /**
61
61
  * Make a type-safe API call using a contract
62
+ *
63
+ * @param basePath - Base path from file-based routing (e.g., '/organizations')
64
+ * @param contract - Route contract
65
+ * @param options - Call options (params, query, body, headers)
62
66
  */
63
- call<TContract extends RouteContract>(contract: TContract, options?: CallOptions<TContract>): Promise<InferContract<TContract>['response']>;
67
+ call<TContract extends RouteContract>(basePath: string, contract: TContract, options?: CallOptions<TContract>): Promise<InferContract<TContract>['response']>;
64
68
  /**
65
69
  * Create a new client with merged configuration
66
70
  */
@@ -28,11 +28,15 @@ var ContractClient = class _ContractClient {
28
28
  }
29
29
  /**
30
30
  * Make a type-safe API call using a contract
31
+ *
32
+ * @param basePath - Base path from file-based routing (e.g., '/organizations')
33
+ * @param contract - Route contract
34
+ * @param options - Call options (params, query, body, headers)
31
35
  */
32
- async call(contract, options) {
36
+ async call(basePath, contract, options) {
33
37
  const baseUrl = options?.baseUrl || this.config.baseUrl;
34
38
  const urlPath = _ContractClient.buildUrl(
35
- contract.path,
39
+ basePath + contract.path,
36
40
  options?.params
37
41
  );
38
42
  const queryString = _ContractClient.buildQuery(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/contract-client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Contract-Based API Client\n *\n * Type-safe HTTP client that works with RouteContract for full end-to-end type safety\n */\nimport type { RouteContract, InferContract } from '../route';\n\nexport type RequestInterceptor = (\n url: string,\n init: RequestInit\n) => Promise<RequestInit> | RequestInit;\n\nexport interface ClientConfig\n{\n /**\n * API base URL (e.g., http://localhost:4000)\n */\n baseUrl?: string;\n\n /**\n * Default headers to include in all requests\n */\n headers?: Record<string, string>;\n\n /**\n * Request timeout in milliseconds\n */\n timeout?: number;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\nexport interface CallOptions<TContract extends RouteContract>\n{\n params?: InferContract<TContract>['params'];\n query?: InferContract<TContract>['query'];\n body?: InferContract<TContract>['body'];\n headers?: Record<string, string>;\n baseUrl?: string;\n}\n\n/**\n * API Client Error\n */\nexport class ApiClientError extends Error\n{\n constructor(\n message: string,\n public readonly status: number,\n public readonly url: string,\n public readonly response?: unknown,\n public readonly errorType?: 'timeout' | 'network' | 'http'\n )\n {\n super(message);\n this.name = 'ApiClientError';\n }\n}\n\n/**\n * Contract-based API Client\n */\nexport class ContractClient\n{\n private readonly config: Required<ClientConfig>;\n private readonly interceptors: RequestInterceptor[] = [];\n\n constructor(config: ClientConfig = {})\n {\n this.config = {\n baseUrl: config.baseUrl || process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000',\n headers: config.headers || {},\n timeout: config.timeout || 30000,\n fetch: config.fetch || globalThis.fetch.bind(globalThis),\n };\n }\n\n /**\n * Add request interceptor\n */\n use(interceptor: RequestInterceptor): void\n {\n this.interceptors.push(interceptor);\n }\n\n /**\n * Make a type-safe API call using a contract\n */\n async call<TContract extends RouteContract>(\n contract: TContract,\n options?: CallOptions<TContract>\n ): Promise<InferContract<TContract>['response']>\n {\n const baseUrl = options?.baseUrl || this.config.baseUrl;\n const urlPath = ContractClient.buildUrl(\n contract.path,\n options?.params as Record<string, string | number> | undefined\n );\n const queryString = ContractClient.buildQuery(\n options?.query as Record<string, string | string[] | number | boolean> | undefined\n );\n const url = `${baseUrl}${urlPath}${queryString}`;\n\n const method = ContractClient.getHttpMethod(contract, options);\n\n const headers: Record<string, string> = {\n ...this.config.headers,\n ...options?.headers,\n };\n\n const isFormData = ContractClient.isFormData(options?.body);\n\n if (options?.body !== undefined && !isFormData && !headers['Content-Type'])\n {\n headers['Content-Type'] = 'application/json';\n }\n\n let init: RequestInit = {\n method,\n headers,\n };\n\n if (options?.body !== undefined)\n {\n init.body = isFormData ? (options.body as FormData) : JSON.stringify(options.body);\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n init.signal = controller.signal;\n\n for (const interceptor of this.interceptors)\n {\n init = await interceptor(url, init);\n }\n\n const response = await this.config.fetch(url, init).catch((error) =>\n {\n clearTimeout(timeoutId);\n\n if (error instanceof Error && error.name === 'AbortError')\n {\n throw new ApiClientError(\n `Request timed out after ${this.config.timeout}ms`,\n 0,\n url,\n undefined,\n 'timeout'\n );\n }\n\n if (error instanceof Error)\n {\n throw new ApiClientError(\n `Network error: ${error.message}`,\n 0,\n url,\n undefined,\n 'network'\n );\n }\n\n throw error;\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok)\n {\n const errorBody = await response.json().catch(() => null);\n throw new ApiClientError(\n `${method} ${urlPath} failed: ${response.status} ${response.statusText}`,\n response.status,\n url,\n errorBody,\n 'http'\n );\n }\n\n const data = await response.json();\n return data as InferContract<TContract>['response'];\n }\n\n /**\n * Create a new client with merged configuration\n */\n withConfig(config: Partial<ClientConfig>): ContractClient\n {\n return new ContractClient({\n baseUrl: config.baseUrl || this.config.baseUrl,\n headers: { ...this.config.headers, ...config.headers },\n timeout: config.timeout || this.config.timeout,\n fetch: config.fetch || this.config.fetch,\n });\n }\n\n private static buildUrl(path: string, params?: Record<string, string | number>): string\n {\n if (!params) return path;\n\n let url = path;\n for (const [key, value] of Object.entries(params))\n {\n url = url.replace(`:${key}`, String(value));\n }\n\n return url;\n }\n\n private static buildQuery(query?: Record<string, string | string[] | number | boolean>): string\n {\n if (!query || Object.keys(query).length === 0) return '';\n\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query))\n {\n if (Array.isArray(value))\n {\n value.forEach((v) => params.append(key, String(v)));\n }\n else if (value !== undefined && value !== null)\n {\n params.append(key, String(value));\n }\n }\n\n const queryString = params.toString();\n return queryString ? `?${queryString}` : '';\n }\n\n private static getHttpMethod<TContract extends RouteContract>(\n contract: TContract,\n options?: CallOptions<TContract>\n ): string\n {\n if ('method' in contract && typeof contract.method === 'string')\n {\n return contract.method.toUpperCase();\n }\n\n if (options?.body !== undefined)\n {\n return 'POST';\n }\n\n return 'GET';\n }\n\n private static isFormData(body: unknown): body is FormData\n {\n return body instanceof FormData;\n }\n}\n\n/**\n * Create a new contract-based API client\n */\nexport function createClient(config?: ClientConfig): ContractClient\n{\n return new ContractClient(config);\n}\n\n/**\n * Global client singleton instance\n */\nlet _clientInstance: ContractClient = new ContractClient();\n\n/**\n * Configure the global client instance\n *\n * Call this in your app initialization to set default configuration\n * for all auto-generated API calls.\n *\n * @example\n * ```ts\n * // In app initialization (layout.tsx, _app.tsx, etc)\n * import { configureClient } from '@spfn/core/client';\n *\n * configureClient({\n * baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000',\n * timeout: 60000,\n * headers: {\n * 'X-App-Version': '1.0.0'\n * }\n * });\n *\n * // Add interceptors\n * import { client } from '@spfn/core/client';\n * client.use(async (url, init) => {\n * // Add auth header\n * return {\n * ...init,\n * headers: {\n * ...init.headers,\n * Authorization: `Bearer ${getToken()}`\n * }\n * };\n * });\n * ```\n */\nexport function configureClient(config: ClientConfig): void\n{\n _clientInstance = new ContractClient(config);\n}\n\n/**\n * Global client singleton with Proxy\n *\n * This client can be configured using configureClient() before use.\n * Used by auto-generated API client code.\n */\nexport const client = new Proxy({} as ContractClient, {\n get(_target, prop)\n {\n return _clientInstance[prop as keyof ContractClient];\n }\n});\n\n/**\n * Type guard for timeout errors\n *\n * @example\n * ```ts\n * try {\n * await api.users.getById({ params: { id: '123' } });\n * } catch (error) {\n * if (isTimeoutError(error)) {\n * console.error('Request timed out, retrying...');\n * // Implement retry logic\n * }\n * }\n * ```\n */\nexport function isTimeoutError(error: unknown): error is ApiClientError\n{\n return error instanceof ApiClientError && error.errorType === 'timeout';\n}\n\n/**\n * Type guard for network errors\n *\n * @example\n * ```ts\n * try {\n * await api.users.list();\n * } catch (error) {\n * if (isNetworkError(error)) {\n * showOfflineMessage();\n * }\n * }\n * ```\n */\nexport function isNetworkError(error: unknown): error is ApiClientError\n{\n return error instanceof ApiClientError && error.errorType === 'network';\n}\n\n/**\n * Type guard for HTTP errors (4xx, 5xx)\n *\n * @example\n * ```ts\n * try {\n * await api.users.create({ body: userData });\n * } catch (error) {\n * if (isHttpError(error)) {\n * if (error.status === 401) {\n * redirectToLogin();\n * } else if (error.status === 404) {\n * showNotFoundMessage();\n * }\n * }\n * }\n * ```\n */\nexport function isHttpError(error: unknown): error is ApiClientError\n{\n return error instanceof ApiClientError && error.errorType === 'http';\n}\n"]}
1
+ {"version":3,"sources":["../../src/client/contract-client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Contract-Based API Client\n *\n * Type-safe HTTP client that works with RouteContract for full end-to-end type safety\n */\nimport type { RouteContract, InferContract } from '../route';\n\nexport type RequestInterceptor = (\n url: string,\n init: RequestInit\n) => Promise<RequestInit> | RequestInit;\n\nexport interface ClientConfig\n{\n /**\n * API base URL (e.g., http://localhost:4000)\n */\n baseUrl?: string;\n\n /**\n * Default headers to include in all requests\n */\n headers?: Record<string, string>;\n\n /**\n * Request timeout in milliseconds\n */\n timeout?: number;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\nexport interface CallOptions<TContract extends RouteContract>\n{\n params?: InferContract<TContract>['params'];\n query?: InferContract<TContract>['query'];\n body?: InferContract<TContract>['body'];\n headers?: Record<string, string>;\n baseUrl?: string;\n}\n\n/**\n * API Client Error\n */\nexport class ApiClientError extends Error\n{\n constructor(\n message: string,\n public readonly status: number,\n public readonly url: string,\n public readonly response?: unknown,\n public readonly errorType?: 'timeout' | 'network' | 'http'\n )\n {\n super(message);\n this.name = 'ApiClientError';\n }\n}\n\n/**\n * Contract-based API Client\n */\nexport class ContractClient\n{\n private readonly config: Required<ClientConfig>;\n private readonly interceptors: RequestInterceptor[] = [];\n\n constructor(config: ClientConfig = {})\n {\n this.config = {\n baseUrl: config.baseUrl || process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000',\n headers: config.headers || {},\n timeout: config.timeout || 30000,\n fetch: config.fetch || globalThis.fetch.bind(globalThis),\n };\n }\n\n /**\n * Add request interceptor\n */\n use(interceptor: RequestInterceptor): void\n {\n this.interceptors.push(interceptor);\n }\n\n /**\n * Make a type-safe API call using a contract\n *\n * @param basePath - Base path from file-based routing (e.g., '/organizations')\n * @param contract - Route contract\n * @param options - Call options (params, query, body, headers)\n */\n async call<TContract extends RouteContract>(\n basePath: string,\n contract: TContract,\n options?: CallOptions<TContract>\n ): Promise<InferContract<TContract>['response']>\n {\n const baseUrl = options?.baseUrl || this.config.baseUrl;\n const urlPath = ContractClient.buildUrl(\n basePath + contract.path,\n options?.params as Record<string, string | number> | undefined\n );\n const queryString = ContractClient.buildQuery(\n options?.query as Record<string, string | string[] | number | boolean> | undefined\n );\n const url = `${baseUrl}${urlPath}${queryString}`;\n\n const method = ContractClient.getHttpMethod(contract, options);\n\n const headers: Record<string, string> = {\n ...this.config.headers,\n ...options?.headers,\n };\n\n const isFormData = ContractClient.isFormData(options?.body);\n\n if (options?.body !== undefined && !isFormData && !headers['Content-Type'])\n {\n headers['Content-Type'] = 'application/json';\n }\n\n let init: RequestInit = {\n method,\n headers,\n };\n\n if (options?.body !== undefined)\n {\n init.body = isFormData ? (options.body as FormData) : JSON.stringify(options.body);\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n init.signal = controller.signal;\n\n for (const interceptor of this.interceptors)\n {\n init = await interceptor(url, init);\n }\n\n const response = await this.config.fetch(url, init).catch((error) =>\n {\n clearTimeout(timeoutId);\n\n if (error instanceof Error && error.name === 'AbortError')\n {\n throw new ApiClientError(\n `Request timed out after ${this.config.timeout}ms`,\n 0,\n url,\n undefined,\n 'timeout'\n );\n }\n\n if (error instanceof Error)\n {\n throw new ApiClientError(\n `Network error: ${error.message}`,\n 0,\n url,\n undefined,\n 'network'\n );\n }\n\n throw error;\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok)\n {\n const errorBody = await response.json().catch(() => null);\n throw new ApiClientError(\n `${method} ${urlPath} failed: ${response.status} ${response.statusText}`,\n response.status,\n url,\n errorBody,\n 'http'\n );\n }\n\n const data = await response.json();\n return data as InferContract<TContract>['response'];\n }\n\n /**\n * Create a new client with merged configuration\n */\n withConfig(config: Partial<ClientConfig>): ContractClient\n {\n return new ContractClient({\n baseUrl: config.baseUrl || this.config.baseUrl,\n headers: { ...this.config.headers, ...config.headers },\n timeout: config.timeout || this.config.timeout,\n fetch: config.fetch || this.config.fetch,\n });\n }\n\n private static buildUrl(path: string, params?: Record<string, string | number>): string\n {\n if (!params) return path;\n\n let url = path;\n for (const [key, value] of Object.entries(params))\n {\n url = url.replace(`:${key}`, String(value));\n }\n\n return url;\n }\n\n private static buildQuery(query?: Record<string, string | string[] | number | boolean>): string\n {\n if (!query || Object.keys(query).length === 0) return '';\n\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query))\n {\n if (Array.isArray(value))\n {\n value.forEach((v) => params.append(key, String(v)));\n }\n else if (value !== undefined && value !== null)\n {\n params.append(key, String(value));\n }\n }\n\n const queryString = params.toString();\n return queryString ? `?${queryString}` : '';\n }\n\n private static getHttpMethod<TContract extends RouteContract>(\n contract: TContract,\n options?: CallOptions<TContract>\n ): string\n {\n if ('method' in contract && typeof contract.method === 'string')\n {\n return contract.method.toUpperCase();\n }\n\n if (options?.body !== undefined)\n {\n return 'POST';\n }\n\n return 'GET';\n }\n\n private static isFormData(body: unknown): body is FormData\n {\n return body instanceof FormData;\n }\n}\n\n/**\n * Create a new contract-based API client\n */\nexport function createClient(config?: ClientConfig): ContractClient\n{\n return new ContractClient(config);\n}\n\n/**\n * Global client singleton instance\n */\nlet _clientInstance: ContractClient = new ContractClient();\n\n/**\n * Configure the global client instance\n *\n * Call this in your app initialization to set default configuration\n * for all auto-generated API calls.\n *\n * @example\n * ```ts\n * // In app initialization (layout.tsx, _app.tsx, etc)\n * import { configureClient } from '@spfn/core/client';\n *\n * configureClient({\n * baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000',\n * timeout: 60000,\n * headers: {\n * 'X-App-Version': '1.0.0'\n * }\n * });\n *\n * // Add interceptors\n * import { client } from '@spfn/core/client';\n * client.use(async (url, init) => {\n * // Add auth header\n * return {\n * ...init,\n * headers: {\n * ...init.headers,\n * Authorization: `Bearer ${getToken()}`\n * }\n * };\n * });\n * ```\n */\nexport function configureClient(config: ClientConfig): void\n{\n _clientInstance = new ContractClient(config);\n}\n\n/**\n * Global client singleton with Proxy\n *\n * This client can be configured using configureClient() before use.\n * Used by auto-generated API client code.\n */\nexport const client = new Proxy({} as ContractClient, {\n get(_target, prop)\n {\n return _clientInstance[prop as keyof ContractClient];\n }\n});\n\n/**\n * Type guard for timeout errors\n *\n * @example\n * ```ts\n * try {\n * await api.users.getById({ params: { id: '123' } });\n * } catch (error) {\n * if (isTimeoutError(error)) {\n * console.error('Request timed out, retrying...');\n * // Implement retry logic\n * }\n * }\n * ```\n */\nexport function isTimeoutError(error: unknown): error is ApiClientError\n{\n return error instanceof ApiClientError && error.errorType === 'timeout';\n}\n\n/**\n * Type guard for network errors\n *\n * @example\n * ```ts\n * try {\n * await api.users.list();\n * } catch (error) {\n * if (isNetworkError(error)) {\n * showOfflineMessage();\n * }\n * }\n * ```\n */\nexport function isNetworkError(error: unknown): error is ApiClientError\n{\n return error instanceof ApiClientError && error.errorType === 'network';\n}\n\n/**\n * Type guard for HTTP errors (4xx, 5xx)\n *\n * @example\n * ```ts\n * try {\n * await api.users.create({ body: userData });\n * } catch (error) {\n * if (isHttpError(error)) {\n * if (error.status === 401) {\n * redirectToLogin();\n * } else if (error.status === 404) {\n * showNotFoundMessage();\n * }\n * }\n * }\n * ```\n */\nexport function isHttpError(error: unknown): error is ApiClientError\n{\n return error instanceof ApiClientError && error.errorType === 'http';\n}\n"]}
@@ -352,7 +352,7 @@ function generateMethodCode(mapping, options) {
352
352
  code += `options: { ${params.join(", ")} }`;
353
353
  }
354
354
  code += `) => `;
355
- code += `client.call(${mapping.contractName}`;
355
+ code += `client.call('${mapping.path}', ${mapping.contractName}`;
356
356
  if (params.length > 0) {
357
357
  code += `, options`;
358
358
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/codegen/contract-scanner.ts","../../src/codegen/route-scanner.ts","../../src/codegen/client-generator.ts","../../src/logger/adapters/pino.ts","../../src/logger/types.ts","../../src/logger/formatters.ts","../../src/logger/logger.ts","../../src/logger/transports/console.ts","../../src/logger/transports/file.ts","../../src/logger/config.ts","../../src/logger/adapters/custom.ts","../../src/logger/adapter-factory.ts","../../src/codegen/watch-generate.ts","../../src/codegen/orchestrator.ts","../../src/codegen/generators/contract-generator.ts","../../src/codegen/config-loader.ts"],"names":["join","newPath","existsSync","mkdirSync","unlinkSync","chokidarWatch","readFileSync"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Contract Scanner\n *\n * Scans server/contracts directory and extracts exported contracts\n */\n\nimport { readdir, stat } from 'fs/promises';\nimport { join } from 'path';\nimport * as ts from 'typescript';\nimport { readFileSync } from 'fs';\nimport type { RouteContractMapping, HttpMethod } from './types.js';\n\n/**\n * Scan routes directory for contract.ts files and extract contract exports\n *\n * @param routesDir - Path to server/routes directory\n * @returns Array of contract-to-route mappings\n */\nexport async function scanContracts(routesDir: string): Promise<RouteContractMapping[]>\n{\n const contractFiles = await scanContractFiles(routesDir);\n const mappings: RouteContractMapping[] = [];\n\n for (let i = 0; i < contractFiles.length; i++)\n {\n const filePath = contractFiles[i];\n const exports = extractContractExports(filePath);\n\n // Calculate base path from file location: routes/posts/contract.ts → /posts\n const basePath = getBasePathFromFile(filePath, routesDir);\n\n for (let j = 0; j < exports.length; j++)\n {\n const contractExport = exports[j];\n\n // Combine base path with contract path: /posts + / → /posts\n const fullPath = combinePaths(basePath, contractExport.path);\n\n mappings.push({\n method: contractExport.method,\n path: fullPath,\n contractName: contractExport.name,\n contractImportPath: getImportPathFromRoutes(filePath, routesDir),\n routeFile: '', // Not needed anymore\n contractFile: filePath\n });\n }\n }\n\n return mappings;\n}\n\n/**\n * Recursively scan for contract.ts files in routes directory\n */\nasync function scanContractFiles(dir: string, files: string[] = []): Promise<string[]>\n{\n try\n {\n const entries = await readdir(dir);\n\n for (let i = 0; i < entries.length; i++)\n {\n const entry = entries[i];\n const fullPath = join(dir, entry);\n const fileStat = await stat(fullPath);\n\n if (fileStat.isDirectory())\n {\n await scanContractFiles(fullPath, files);\n }\n else if (entry === 'contract.ts')\n {\n files.push(fullPath);\n }\n }\n }\n catch (error)\n {\n // Directory doesn't exist or not readable\n }\n\n return files;\n}\n\n/**\n * Contract export information\n */\ninterface ContractExport\n{\n name: string;\n method: HttpMethod;\n path: string;\n}\n\n/**\n * Extract contract exports from a TypeScript file\n *\n * Looks for exports with structure:\n * export const xxxContract = {\n * method: 'GET',\n * path: '/users',\n * ...\n * }\n */\nfunction extractContractExports(filePath: string): ContractExport[]\n{\n const sourceCode = readFileSync(filePath, 'utf-8');\n const sourceFile = ts.createSourceFile(\n filePath,\n sourceCode,\n ts.ScriptTarget.Latest,\n true\n );\n\n const exports: ContractExport[] = [];\n\n function visit(node: ts.Node): void\n {\n // Look for: export const xxxContract = { ... }\n if (ts.isVariableStatement(node))\n {\n // Check if it has export modifier\n const hasExport = node.modifiers?.some(\n m => m.kind === ts.SyntaxKind.ExportKeyword\n );\n\n if (hasExport && node.declarationList.declarations.length > 0)\n {\n const declaration = node.declarationList.declarations[0];\n\n if (\n ts.isVariableDeclaration(declaration) &&\n ts.isIdentifier(declaration.name) &&\n declaration.initializer &&\n ts.isObjectLiteralExpression(declaration.initializer)\n )\n {\n const name = declaration.name.text;\n\n // Check if name looks like a contract\n if (isContractName(name))\n {\n const contractData = extractContractData(declaration.initializer);\n\n if (contractData.method && contractData.path)\n {\n exports.push({\n name,\n method: contractData.method,\n path: contractData.path\n });\n }\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return exports;\n}\n\n/**\n * Extract method and path from contract object literal\n */\nfunction extractContractData(objectLiteral: ts.ObjectLiteralExpression): {\n method?: HttpMethod;\n path?: string;\n}\n{\n const result: { method?: HttpMethod; path?: string } = {};\n\n for (let i = 0; i < objectLiteral.properties.length; i++)\n {\n const prop = objectLiteral.properties[i];\n\n if (\n ts.isPropertyAssignment(prop) &&\n ts.isIdentifier(prop.name)\n )\n {\n const propName = prop.name.text;\n\n if (propName === 'method')\n {\n // Handle both 'GET' and 'GET' as const\n let value: string | undefined;\n if (ts.isStringLiteral(prop.initializer))\n {\n value = prop.initializer.text;\n }\n else if (ts.isAsExpression(prop.initializer) && ts.isStringLiteral(prop.initializer.expression))\n {\n value = prop.initializer.expression.text;\n }\n if (value) result.method = value as HttpMethod;\n }\n else if (propName === 'path')\n {\n // Handle both '/path' and '/path' as const\n let value: string | undefined;\n if (ts.isStringLiteral(prop.initializer))\n {\n value = prop.initializer.text;\n }\n else if (ts.isAsExpression(prop.initializer) && ts.isStringLiteral(prop.initializer.expression))\n {\n value = prop.initializer.expression.text;\n }\n if (value) result.path = value;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Check if a name looks like a contract\n */\nfunction isContractName(name: string): boolean\n{\n return (\n name.indexOf('Contract') !== -1 ||\n name.indexOf('contract') !== -1 ||\n name.endsWith('Schema') ||\n name.endsWith('schema')\n );\n}\n\n/**\n * Get base URL path from contract file location\n *\n * @example\n * routes/posts/contract.ts → /posts\n * routes/users/[id]/contract.ts → /users/:id\n * routes/index/contract.ts → /\n */\nfunction getBasePathFromFile(filePath: string, routesDir: string): string\n{\n // Get relative path from routes dir\n let relativePath = filePath.replace(routesDir, '');\n\n // Remove leading slash\n if (relativePath.startsWith('/'))\n {\n relativePath = relativePath.slice(1);\n }\n\n // Remove /contract.ts\n relativePath = relativePath.replace('/contract.ts', '');\n\n // Handle index → /\n if (relativePath === 'index' || relativePath === '')\n {\n return '/';\n }\n\n // Split into segments\n const segments = relativePath.split('/');\n const transformed: string[] = [];\n\n for (let i = 0; i < segments.length; i++)\n {\n const seg = segments[i];\n\n // Skip 'index' segments (routes/index/contract.ts → /, routes/posts/index/contract.ts → /posts)\n if (seg === 'index')\n {\n continue;\n }\n\n // Dynamic parameter: [id] → :id\n if (seg.startsWith('[') && seg.endsWith(']'))\n {\n transformed.push(':' + seg.slice(1, -1));\n }\n // Static segment\n else\n {\n transformed.push(seg);\n }\n }\n\n // If no segments remain, return root\n if (transformed.length === 0)\n {\n return '/';\n }\n\n return '/' + transformed.join('/');\n}\n\n/**\n * Combine base path with contract path\n *\n * @example\n * combinePaths('/posts', '/') → /posts\n * combinePaths('/posts', '/:id') → /posts/:id\n * combinePaths('/', '/health') → /health\n */\nfunction combinePaths(basePath: string, contractPath: string): string\n{\n // Normalize paths\n basePath = basePath || '/';\n contractPath = contractPath || '/';\n\n // Remove trailing slash from base\n if (basePath.endsWith('/') && basePath !== '/')\n {\n basePath = basePath.slice(0, -1);\n }\n\n // If contract path is absolute, use it as is\n if (contractPath.startsWith('/') && contractPath !== '/')\n {\n // If base is /, just use contract path\n if (basePath === '/')\n {\n return contractPath;\n }\n // Otherwise combine: /posts + /sub → /posts/sub\n return basePath + contractPath;\n }\n\n // Contract path is / or relative\n if (contractPath === '/')\n {\n return basePath;\n }\n\n // Combine: /posts + id → /posts/id\n return basePath + '/' + contractPath;\n}\n\n/**\n * Get import path for contract file\n *\n * @example\n * routes/posts/contract.ts → @/server/routes/posts/contract\n * routes/users/[id]/contract.ts → @/server/routes/users/[id]/contract\n */\nfunction getImportPathFromRoutes(filePath: string, routesDir: string): string\n{\n // Get relative path from routes dir\n let relativePath = filePath.replace(routesDir, '');\n\n // Remove leading slash\n if (relativePath.startsWith('/'))\n {\n relativePath = relativePath.slice(1);\n }\n\n // Remove .ts extension\n if (relativePath.endsWith('.ts'))\n {\n relativePath = relativePath.slice(0, -3);\n }\n\n // Return as module path\n return '@/server/routes/' + relativePath;\n}","/**\n * Route Scanner Utilities\n *\n * Helper functions for grouping and organizing route-contract mappings\n */\n\nimport type { RouteContractMapping } from './types.js';\n\n/**\n * Group mappings by resource\n */\nexport function groupByResource(mappings: RouteContractMapping[]): Record<string, RouteContractMapping[]>\n{\n const grouped: Record<string, RouteContractMapping[]> = {};\n\n for (let i = 0; i < mappings.length; i++)\n {\n const mapping = mappings[i];\n const resource = extractResourceName(mapping.path);\n\n if (!grouped[resource])\n {\n grouped[resource] = [];\n }\n\n grouped[resource].push(mapping);\n }\n\n return grouped;\n}\n\n/**\n * Extract resource name from path\n *\n * Examples:\n * - /users → users\n * - /users/:id → users\n * - /users/:id/posts → usersPosts\n * - /videos/upload-and-analyze → videosUploadAndAnalyze\n */\nfunction extractResourceName(path: string): string\n{\n // Remove leading slash\n const segments = path.slice(1).split('/').filter(s => s && s !== '*');\n\n // Remove dynamic segments\n const staticSegments: string[] = [];\n for (let i = 0; i < segments.length; i++)\n {\n const seg = segments[i];\n if (!seg.startsWith(':'))\n {\n staticSegments.push(seg);\n }\n }\n\n // Join with camelCase\n if (staticSegments.length === 0)\n {\n return 'root';\n }\n\n // Convert first segment (handle hyphens)\n const first = toCamelCase(staticSegments[0], false);\n\n if (staticSegments.length === 1)\n {\n return first;\n }\n\n // Convert to camelCase: users/posts → usersPosts, videos/upload-and-analyze → videosUploadAndAnalyze\n const result: string[] = [first];\n for (let i = 1; i < staticSegments.length; i++)\n {\n const seg = staticSegments[i];\n result.push(toCamelCase(seg, true));\n }\n\n return result.join('');\n}\n\n/**\n * Convert string to camelCase, handling hyphens\n *\n * @param str - Input string\n * @param capitalize - Capitalize first letter\n * @returns camelCase string\n *\n * Examples:\n * - toCamelCase('upload-and-analyze', true) → 'UploadAndAnalyze'\n * - toCamelCase('upload-and-analyze', false) → 'uploadAndAnalyze'\n * - toCamelCase('users', false) → 'users'\n */\nfunction toCamelCase(str: string, capitalize: boolean): string\n{\n // Split by hyphen or underscore\n const parts = str.split(/[-_]/);\n\n if (parts.length === 1)\n {\n // No hyphens/underscores\n return capitalize\n ? str.charAt(0).toUpperCase() + str.slice(1)\n : str;\n }\n\n // Convert to camelCase\n const result: string[] = [];\n for (let i = 0; i < parts.length; i++)\n {\n const part = parts[i];\n if (i === 0 && !capitalize)\n {\n result.push(part);\n }\n else\n {\n result.push(part.charAt(0).toUpperCase() + part.slice(1));\n }\n }\n\n return result.join('');\n}","/**\n * Client Code Generator\n *\n * Generates type-safe API client code from route-contract mappings\n */\n\nimport { mkdir, writeFile } from 'fs/promises';\nimport { dirname } from 'path';\nimport { groupByResource } from './route-scanner.js';\nimport type { ClientGenerationOptions, GenerationStats, RouteContractMapping } from './types.js';\n\n/**\n * Generate API client code\n */\nexport async function generateClient(\n mappings: RouteContractMapping[],\n options: ClientGenerationOptions\n): Promise<GenerationStats>\n{\n const startTime = Date.now();\n\n // Group by resource\n const grouped = groupByResource(mappings);\n const resourceNames = Object.keys(grouped);\n\n // Generate code\n const code = generateClientCode(mappings, grouped, options);\n\n // Ensure output directory exists\n await mkdir(dirname(options.outputPath), { recursive: true });\n\n // Write file\n await writeFile(options.outputPath, code, 'utf-8');\n\n // Calculate stats\n return {\n routesScanned: mappings.length,\n contractsFound: mappings.length,\n contractFiles: countUniqueContractFiles(mappings),\n resourcesGenerated: resourceNames.length,\n methodsGenerated: mappings.length,\n duration: Date.now() - startTime\n };\n}\n\n/**\n * Generate the actual client code\n */\nfunction generateClientCode(\n mappings: RouteContractMapping[],\n grouped: Record<string, RouteContractMapping[]>,\n options: ClientGenerationOptions\n): string\n{\n let code = '';\n\n // Header\n code += generateHeader();\n\n // Imports\n code += generateImports(mappings, options);\n\n // API object\n code += generateApiObject(grouped, options);\n\n // Footer\n code += generateFooter();\n\n return code;\n}\n\n/**\n * Generate file header\n */\nfunction generateHeader(): string\n{\n return `/**\n * Auto-generated API Client\n *\n * Generated by @spfn/core codegen\n * DO NOT EDIT MANUALLY\n *\n * @generated ${new Date().toISOString()}\n */\n\n`;\n}\n\n/**\n * Generate imports section\n */\nfunction generateImports(mappings: RouteContractMapping[], options: ClientGenerationOptions): string\n{\n let code = '';\n\n code += `import { client } from '@spfn/core/client';\\n`;\n\n if (options.includeTypes !== false)\n {\n code += `import type { InferContract } from '@spfn/core';\\n`;\n }\n\n code += `\\n`;\n\n // Contract imports (group by import path)\n const importGroups = groupContractsByImportPath(mappings);\n const importPaths = Object.keys(importGroups);\n\n for (let i = 0; i < importPaths.length; i++)\n {\n const importPath = importPaths[i];\n const contracts = importGroups[importPath];\n\n code += `import { ${contracts.join(', ')} } from '${importPath}';\\n`;\n }\n\n code += `\\n`;\n\n return code;\n}\n\n/**\n * Group contracts by their import path\n */\nfunction groupContractsByImportPath(mappings: RouteContractMapping[]): Record<string, string[]>\n{\n const groups: Record<string, Set<string>> = {};\n\n for (let i = 0; i < mappings.length; i++)\n {\n const mapping = mappings[i];\n const path = mapping.contractImportPath;\n\n if (!groups[path])\n {\n groups[path] = new Set();\n }\n\n groups[path].add(mapping.contractName);\n }\n\n // Convert Set to Array\n const result: Record<string, string[]> = {};\n const keys = Object.keys(groups);\n\n for (let i = 0; i < keys.length; i++)\n {\n const key = keys[i];\n result[key] = Array.from(groups[key]);\n }\n\n return result;\n}\n\n/**\n * Generate API object with all methods\n */\nfunction generateApiObject(\n grouped: Record<string, RouteContractMapping[]>,\n options: ClientGenerationOptions\n): string\n{\n let code = '';\n\n code += `/**\n * Type-safe API client\n */\nexport const api = {\\n`;\n\n const resourceNames = Object.keys(grouped);\n\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n\n code += ` ${resourceName}: {\\n`;\n\n for (let j = 0; j < routes.length; j++)\n {\n const route = routes[j];\n code += generateMethodCode(route, options);\n }\n\n code += ` }`;\n\n if (i < resourceNames.length - 1)\n {\n code += `,`;\n }\n\n code += `\\n`;\n }\n\n code += `} as const;\\n\\n`;\n\n return code;\n}\n\n/**\n * Generate a single method\n */\nfunction generateMethodCode(mapping: RouteContractMapping, options: ClientGenerationOptions): string\n{\n const methodName = generateMethodName(mapping);\n const contractType = `typeof ${mapping.contractName}`;\n const hasParams = mapping.path.includes(':');\n const hasQuery = false; // TODO: detect from contract\n const hasBody = ['POST', 'PUT', 'PATCH'].indexOf(mapping.method) !== -1;\n\n let code = '';\n\n // JSDoc\n if (options.includeJsDoc !== false)\n {\n code += ` /**\\n`;\n code += ` * ${mapping.method} ${mapping.path}\\n`;\n code += ` */\\n`;\n }\n\n // Method signature\n code += ` ${methodName}: (`;\n\n // Parameters\n const params: string[] = [];\n\n if (hasParams)\n {\n params.push(`params: InferContract<${contractType}>['params']`);\n }\n\n if (hasQuery)\n {\n params.push(`query?: InferContract<${contractType}>['query']`);\n }\n\n if (hasBody)\n {\n params.push(`body: InferContract<${contractType}>['body']`);\n }\n\n if (params.length > 0)\n {\n code += `options: { ${params.join(', ')} }`;\n }\n\n code += `) => `;\n\n // Return type\n code += `client.call(${mapping.contractName}`;\n\n if (params.length > 0)\n {\n code += `, options`;\n }\n\n code += `),\\n`;\n\n return code;\n}\n\n/**\n * Generate method name from route\n */\nfunction generateMethodName(mapping: RouteContractMapping): string\n{\n const method = mapping.method.toLowerCase();\n\n // For index routes\n if (mapping.path === '/' || mapping.path.match(/^\\/[\\w-]+$/))\n {\n // Simple path like /users -> get, create, update\n if (method === 'get')\n {\n return 'list';\n }\n if (method === 'post')\n {\n return 'create';\n }\n }\n\n // For dynamic routes like /users/:id\n if (mapping.path.includes(':'))\n {\n if (method === 'get')\n {\n return 'getById';\n }\n if (method === 'put' || method === 'patch')\n {\n return 'update';\n }\n if (method === 'delete')\n {\n return 'delete';\n }\n }\n\n // Default: method name\n return method;\n}\n\n/**\n * Generate footer\n */\nfunction generateFooter(): string\n{\n return `/**\n * Export client instance for advanced usage\n *\n * Use this to add interceptors or customize the client:\n *\n * @example\n * \\`\\`\\`ts\n * import { client } from './api';\n * import { createAuthInterceptor } from '@spfn/auth/nextjs';\n * import { NextJSCookieProvider } from '@spfn/auth/nextjs';\n *\n * client.use(createAuthInterceptor({\n * cookieProvider: new NextJSCookieProvider(),\n * encryptionKey: process.env.ENCRYPTION_KEY!\n * }));\n * \\`\\`\\`\n */\nexport { client };\n`;\n}\n\n/**\n * Count unique contract files\n */\nfunction countUniqueContractFiles(mappings: RouteContractMapping[]): number\n{\n const files = new Set<string>();\n\n for (let i = 0; i < mappings.length; i++)\n {\n if (mappings[i].contractFile)\n {\n files.add(mappings[i].contractFile as string);\n }\n }\n\n return files.size;\n}","/**\n * Pino Logger Adapter\n *\n * High-performance logger adapter using Pino with pretty-print for development and JSON for production.\n */\n\nimport pino from 'pino';\nimport type { LoggerAdapter, AdapterConfig, LogLevel } from './types';\n\n/**\n * Pino Logger Adapter\n */\nexport class PinoAdapter implements LoggerAdapter\n{\n private logger: pino.Logger;\n\n constructor(config: AdapterConfig)\n {\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n // Development: use simple console output without transport\n // Production: use JSON output\n this.logger = pino({\n level: config.level,\n\n // 기본 필드\n base: config.module ? { module: config.module } : undefined,\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const childLogger = new PinoAdapter({ level: this.logger.level as LogLevel, module });\n childLogger.logger = this.logger.child({ module });\n return childLogger;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(context || {}, message);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(context || {}, message);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.warn(errorOrContext || {}, message);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.error(errorOrContext || {}, message);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.fatal(errorOrContext || {}, message);\n }\n }\n\n async close(): Promise<void>\n {\n // Pino는 자동으로 flush됨\n // 필요시 pino.final() 사용 가능\n }\n}","/**\n * Logger Type Definitions\n *\n * 로깅 시스템 타입 정의\n *\n * ✅ 구현 완료:\n * - LogLevel 타입 정의\n * - LogMetadata 인터페이스\n * - Transport 인터페이스\n * - 환경별 설정 타입\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현체)\n * - src/logger/config.ts (설정)\n */\n\n/**\n * 로그 레벨\n * debug < info < warn < error < fatal\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * 로그 레벨 우선순위\n */\nexport const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n fatal: 4,\n};\n\n/**\n * 로그 메타데이터\n */\nexport interface LogMetadata\n{\n timestamp: Date;\n level: LogLevel;\n message: string;\n module?: string;\n error?: Error;\n context?: Record<string, unknown>;\n}\n\n/**\n * Transport 인터페이스\n * 모든 Transport는 이 인터페이스를 구현해야 함\n */\nexport interface Transport\n{\n /**\n * Transport 이름\n */\n name: string;\n\n /**\n * 최소 로그 레벨 (이 레벨 이상만 처리)\n */\n level: LogLevel;\n\n /**\n * 활성화 여부\n */\n enabled: boolean;\n\n /**\n * 로그 처리 함수\n */\n log(metadata: LogMetadata): Promise<void>;\n\n /**\n * Transport 종료 (리소스 정리)\n */\n close?(): Promise<void>;\n}\n\n/**\n * Logger 설정\n */\nexport interface LoggerConfig\n{\n /**\n * 기본 로그 레벨\n */\n level: LogLevel;\n\n /**\n * 모듈명 (context)\n */\n module?: string;\n\n /**\n * Transport 리스트\n */\n transports: Transport[];\n}\n\n/**\n * Transport 설정 (공통)\n */\nexport interface TransportConfig\n{\n level: LogLevel;\n enabled: boolean;\n}\n\n/**\n * Console Transport 설정\n */\nexport interface ConsoleTransportConfig extends TransportConfig\n{\n colorize?: boolean;\n}\n\n/**\n * File Transport 설정\n */\nexport interface FileTransportConfig extends TransportConfig\n{\n logDir: string;\n maxFileSize?: number; // bytes\n maxFiles?: number; // 최대 로그 파일 개수\n}\n\n/**\n * Slack Transport 설정\n */\nexport interface SlackTransportConfig extends TransportConfig\n{\n webhookUrl: string;\n channel?: string;\n username?: string;\n}\n\n/**\n * Email Transport 설정\n */\nexport interface EmailTransportConfig extends TransportConfig\n{\n from: string;\n to: string[];\n smtpHost: string;\n smtpPort: number;\n smtpUser?: string;\n smtpPassword?: string;\n}","/**\n * Logger Formatters\n *\n * Log formatting utilities for console, JSON, Slack, and Email outputs with sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata } from './types';\n\n/**\n * 민감 정보로 간주되는 키 목록\n * 이 키들을 포함하는 필드는 자동으로 마스킹됨\n */\nconst SENSITIVE_KEYS = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'accesstoken',\n 'access_token',\n 'refreshtoken',\n 'refresh_token',\n 'authorization',\n 'auth',\n 'cookie',\n 'session',\n 'sessionid',\n 'session_id',\n 'privatekey',\n 'private_key',\n 'creditcard',\n 'credit_card',\n 'cardnumber',\n 'card_number',\n 'cvv',\n 'ssn',\n 'pin',\n];\n\n/**\n * 마스킹된 값\n */\nconst MASKED_VALUE = '***MASKED***';\n\n/**\n * 키가 민감 정보를 포함하는지 확인\n */\nfunction isSensitiveKey(key: string): boolean\n{\n const lowerKey = key.toLowerCase();\n return SENSITIVE_KEYS.some(sensitive => lowerKey.includes(sensitive));\n}\n\n/**\n * 민감 정보 마스킹\n * Context 객체에서 민감한 정보(비밀번호, 토큰 등)를 마스킹\n *\n * @param data - 원본 데이터\n * @returns 마스킹된 데이터\n */\nexport function maskSensitiveData(data: unknown): unknown\n{\n // null, undefined 처리\n if (data === null || data === undefined)\n {\n return data;\n }\n\n // 배열 처리\n if (Array.isArray(data))\n {\n return data.map(item => maskSensitiveData(item));\n }\n\n // 객체 처리\n if (typeof data === 'object')\n {\n const masked: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data))\n {\n if (isSensitiveKey(key))\n {\n // 민감 정보 키는 마스킹\n masked[key] = MASKED_VALUE;\n }\n else if (typeof value === 'object' && value !== null)\n {\n // 중첩된 객체는 재귀 처리\n masked[key] = maskSensitiveData(value);\n }\n else\n {\n // 일반 값은 그대로 유지\n masked[key] = value;\n }\n }\n\n return masked;\n }\n\n // 기본 타입은 그대로 반환\n return data;\n}\n\n/**\n * ANSI 컬러 코드\n */\nconst COLORS = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n\n // 로그 레벨 컬러\n debug: '\\x1b[36m', // cyan\n info: '\\x1b[32m', // green\n warn: '\\x1b[33m', // yellow\n error: '\\x1b[31m', // red\n fatal: '\\x1b[35m', // magenta\n\n // 추가 컬러\n gray: '\\x1b[90m',\n};\n\n/**\n * 로그 레벨을 컬러 문자열로 변환\n */\nexport function colorizeLevel(level: LogLevel): string\n{\n const color = COLORS[level];\n const levelStr = level.toUpperCase().padEnd(5);\n return `${color}${levelStr}${COLORS.reset}`;\n}\n\n/**\n * 타임스탬프 포맷 (ISO 8601)\n */\nexport function formatTimestamp(date: Date): string\n{\n return date.toISOString();\n}\n\n/**\n * 타임스탬프 포맷 (사람이 읽기 쉬운 형식)\n */\nexport function formatTimestampHuman(date: Date): string\n{\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n const seconds = String(date.getSeconds()).padStart(2, '0');\n const ms = String(date.getMilliseconds()).padStart(3, '0');\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`;\n}\n\n/**\n * 에러 객체를 문자열로 변환 (스택 트레이스 포함)\n */\nexport function formatError(error: Error): string\n{\n const lines: string[] = [];\n\n lines.push(`${error.name}: ${error.message}`);\n\n if (error.stack)\n {\n const stackLines = error.stack.split('\\n').slice(1);\n lines.push(...stackLines);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Context 객체를 문자열로 변환\n */\nexport function formatContext(context: Record<string, unknown>): string\n{\n try\n {\n return JSON.stringify(context, null, 2);\n }\n catch (error)\n {\n return '[Context serialization failed]';\n }\n}\n\n/**\n * 콘솔용 컬러 포맷\n */\nexport function formatConsole(metadata: LogMetadata, colorize = true): string\n{\n const parts: string[] = [];\n\n // [타임스탬프]\n const timestamp = formatTimestampHuman(metadata.timestamp);\n if (colorize)\n {\n parts.push(`${COLORS.gray}[${timestamp}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${timestamp}]`);\n }\n\n // [module=value]\n if (metadata.module)\n {\n if (colorize)\n {\n parts.push(`${COLORS.dim}[module=${metadata.module}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[module=${metadata.module}]`);\n }\n }\n\n // Context를 각각 [key=value] 형태로 추가\n if (metadata.context && Object.keys(metadata.context).length > 0)\n {\n Object.entries(metadata.context).forEach(([key, value]) =>\n {\n const valueStr = typeof value === 'string' ? value : String(value);\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Slack 메시지 포맷\n */\nexport function formatSlack(metadata: LogMetadata): string\n{\n const emoji = {\n debug: ':bug:',\n info: ':information_source:',\n warn: ':warning:',\n error: ':x:',\n fatal: ':fire:',\n };\n\n const parts: string[] = [];\n\n parts.push(`${emoji[metadata.level]} *${metadata.level.toUpperCase()}*`);\n\n if (metadata.module)\n {\n parts.push(`\\`[${metadata.module}]\\``);\n }\n\n parts.push(metadata.message);\n\n let message = parts.join(' ');\n\n if (metadata.context)\n {\n message += '\\n```\\n' + JSON.stringify(metadata.context, null, 2) + '\\n```';\n }\n\n if (metadata.error)\n {\n message += '\\n```\\n' + formatError(metadata.error) + '\\n```';\n }\n\n return message;\n}\n\n/**\n * Email 제목 생성\n */\nexport function formatEmailSubject(metadata: LogMetadata): string\n{\n const prefix = `[${metadata.level.toUpperCase()}]`;\n const module = metadata.module ? `[${metadata.module}]` : '';\n\n return `${prefix}${module} ${metadata.message}`;\n}\n\n/**\n * Email 본문 생성 (HTML)\n */\nexport function formatEmailBody(metadata: LogMetadata): string\n{\n const parts: string[] = [];\n\n parts.push('<html>');\n parts.push('<body style=\"font-family: monospace; padding: 20px;\">');\n\n // 헤더\n parts.push(`<h2 style=\"color: ${getEmailColor(metadata.level)};\">`);\n parts.push(`${metadata.level.toUpperCase()}`);\n parts.push('</h2>');\n\n // 시간\n parts.push('<p>');\n parts.push(`<strong>Timestamp:</strong> ${formatTimestamp(metadata.timestamp)}`);\n parts.push('</p>');\n\n // 모듈\n if (metadata.module)\n {\n parts.push('<p>');\n parts.push(`<strong>Module:</strong> ${metadata.module}`);\n parts.push('</p>');\n }\n\n // 메시지\n parts.push('<p>');\n parts.push(`<strong>Message:</strong> ${metadata.message}`);\n parts.push('</p>');\n\n // Context\n if (metadata.context)\n {\n parts.push('<h3>Context</h3>');\n parts.push('<pre style=\"background: #f4f4f4; padding: 10px; border-radius: 4px;\">');\n parts.push(JSON.stringify(metadata.context, null, 2));\n parts.push('</pre>');\n }\n\n // 에러\n if (metadata.error)\n {\n parts.push('<h3>Error Stack Trace</h3>');\n parts.push('<pre style=\"background: #fff0f0; padding: 10px; border-radius: 4px;\">');\n parts.push(formatError(metadata.error));\n parts.push('</pre>');\n }\n\n parts.push('</body>');\n parts.push('</html>');\n\n return parts.join('\\n');\n}\n\n/**\n * Email 레벨별 컬러\n */\nfunction getEmailColor(level: LogLevel): string\n{\n const colors: Record<LogLevel, string> = {\n debug: '#00BCD4',\n info: '#4CAF50',\n warn: '#FF9800',\n error: '#F44336',\n fatal: '#9C27B0',\n };\n\n return colors[level];\n}","/**\n * Logger Class\n *\n * Central logging class with multiple transports, child loggers, and sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata, LoggerConfig, Transport } from './types';\nimport { LOG_LEVEL_PRIORITY } from './types';\nimport { maskSensitiveData } from './formatters';\n\n/**\n * Logger class\n */\nexport class Logger\n{\n private readonly config: LoggerConfig;\n private readonly module?: string;\n\n constructor(config: LoggerConfig)\n {\n this.config = config;\n this.module = config.module;\n }\n\n /**\n * Get current log level\n */\n get level(): LogLevel\n {\n return this.config.level;\n }\n\n /**\n * Create child logger (per module)\n */\n child(module: string): Logger\n {\n return new Logger({\n ...this.config,\n module,\n });\n }\n\n /**\n * Debug log\n */\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.log('debug', message, undefined, context);\n }\n\n /**\n * Info log\n */\n info(message: string, context?: Record<string, unknown>): void\n {\n this.log('info', message, undefined, context);\n }\n\n /**\n * Warn log\n */\n warn(message: string, context?: Record<string, unknown>): void;\n warn(message: string, error: Error, context?: Record<string, unknown>): void;\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('warn', message, errorOrContext, context);\n }\n else\n {\n this.log('warn', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Error log\n */\n error(message: string, context?: Record<string, unknown>): void;\n error(message: string, error: Error, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('error', message, errorOrContext, context);\n }\n else\n {\n this.log('error', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Fatal log\n */\n fatal(message: string, context?: Record<string, unknown>): void;\n fatal(message: string, error: Error, context?: Record<string, unknown>): void;\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('fatal', message, errorOrContext, context);\n }\n else\n {\n this.log('fatal', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Log processing (internal)\n */\n private log(level: LogLevel, message: string, error?: Error, context?: Record<string, unknown>): void\n {\n // Early return if log level is below configured level\n // This prevents unnecessary metadata creation and processing\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level])\n {\n return;\n }\n\n const metadata: LogMetadata = {\n timestamp: new Date(),\n level,\n message,\n module: this.module,\n error,\n // Mask sensitive information in context to prevent credential leaks\n context: context ? maskSensitiveData(context) as Record<string, unknown> : undefined,\n };\n\n // Pass to all enabled Transports\n this.processTransports(metadata);\n }\n\n /**\n * Process Transports\n */\n private processTransports(metadata: LogMetadata): void\n {\n const promises = this.config.transports\n .filter(transport => transport.enabled)\n .map(transport => this.safeTransportLog(transport, metadata));\n\n // Async processing to prevent Transport errors from blocking logs\n Promise.all(promises).catch(error =>\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport error: ${errorMessage}\\n`);\n });\n }\n\n /**\n * Transport log (error-safe)\n */\n private async safeTransportLog(transport: Transport, metadata: LogMetadata): Promise<void>\n {\n try\n {\n await transport.log(metadata);\n }\n catch (error)\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport \"${transport.name}\" failed: ${errorMessage}\\n`);\n }\n }\n\n /**\n * Close all Transports\n */\n async close(): Promise<void>\n {\n const closePromises = this.config.transports\n .filter(transport => transport.close)\n .map(transport => transport.close!());\n\n await Promise.all(closePromises);\n }\n}","/**\n * Console Transport\n *\n * 콘솔 출력 Transport\n *\n * ✅ 구현 완료:\n * - 콘솔 출력 (stdout/stderr)\n * - 컬러 출력 지원\n * - 로그 레벨별 스트림 분리 (warn/error/fatal → stderr)\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (Transport 인터페이스)\n * - src/logger/formatters.ts (포맷터)\n * - src/logger/config.ts (설정)\n */\n\nimport type { Transport, LogMetadata, LogLevel, ConsoleTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatConsole } from '../formatters';\n\n/**\n * Console Transport\n */\nexport class ConsoleTransport implements Transport\n{\n public readonly name = 'console';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private colorize: boolean;\n\n constructor(config: ConsoleTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.colorize = config.colorize ?? true;\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // 포맷팅\n const message = formatConsole(metadata, this.colorize);\n\n // warn/error/fatal은 stderr로, 나머지는 stdout으로\n if (metadata.level === 'warn' || metadata.level === 'error' || metadata.level === 'fatal')\n {\n console.error(message);\n }\n else\n {\n console.log(message);\n }\n }\n}","/**\n * File Transport\n *\n * File output transport with date and size-based rotation, automatic cleanup.\n */\n\nimport { createWriteStream, existsSync, mkdirSync, statSync, readdirSync, unlinkSync, renameSync } from 'fs';\nimport type { WriteStream } from 'fs';\nimport { join } from 'path';\nimport type { Transport, LogMetadata, LogLevel, FileTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatJSON } from '../formatters';\n\n/**\n * File Transport\n */\nexport class FileTransport implements Transport\n{\n public readonly name = 'file';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private readonly logDir: string;\n private readonly maxFileSize: number;\n private readonly maxFiles: number;\n private currentStream: WriteStream | null = null;\n private currentFilename: string | null = null;\n\n constructor(config: FileTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.logDir = config.logDir;\n this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024; // 10MB\n this.maxFiles = config.maxFiles ?? 10;\n\n // 로그 디렉토리가 없으면 생성\n if (!existsSync(this.logDir))\n {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // JSON 포맷으로 변환\n const message = formatJSON(metadata);\n\n // 파일명: YYYY-MM-DD.log\n const filename = this.getLogFilename(metadata.timestamp);\n\n // 날짜가 변경되면 스트림 교체\n if (this.currentFilename !== filename)\n {\n await this.rotateStream(filename);\n await this.cleanOldFiles(); // 오래된 파일 정리\n }\n // 파일 크기 체크 및 로테이션\n else if (this.currentFilename)\n {\n await this.checkAndRotateBySize();\n }\n\n // 스트림에 쓰기\n if (this.currentStream)\n {\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.write(message + '\\n', 'utf-8', (error: Error | null | undefined) =>\n {\n if (error)\n {\n // 파일 쓰기 실패 시 stderr로 출력 (fallback)\n process.stderr.write(`[FileTransport] Failed to write log: ${error.message}\\n`);\n reject(error);\n }\n else\n {\n resolve();\n }\n });\n });\n }\n }\n\n /**\n * 스트림 교체 (날짜 변경 시)\n */\n private async rotateStream(filename: string): Promise<void>\n {\n // 기존 스트림 닫기\n if (this.currentStream)\n {\n await this.closeStream();\n }\n\n // 새 스트림 생성\n const filepath = join(this.logDir, filename);\n\n this.currentStream = createWriteStream(filepath, {\n flags: 'a', // append mode\n encoding: 'utf-8',\n });\n\n this.currentFilename = filename;\n\n // 스트림 에러 핸들링\n this.currentStream.on('error', (error) =>\n {\n process.stderr.write(`[FileTransport] Stream error: ${error.message}\\n`);\n // 에러 발생 시 스트림 초기화\n this.currentStream = null;\n this.currentFilename = null;\n });\n }\n\n /**\n * 현재 스트림 닫기\n */\n private async closeStream(): Promise<void>\n {\n if (!this.currentStream)\n {\n return;\n }\n\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.end((error: Error | null | undefined) =>\n {\n if (error)\n {\n reject(error);\n }\n else\n {\n this.currentStream = null;\n this.currentFilename = null;\n resolve();\n }\n });\n });\n }\n\n /**\n * 파일 크기 체크 및 크기 기반 로테이션\n */\n private async checkAndRotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n const filepath = join(this.logDir, this.currentFilename);\n\n // 파일이 존재하지 않으면 스킵\n if (!existsSync(filepath))\n {\n return;\n }\n\n try\n {\n const stats = statSync(filepath);\n\n // 파일 크기가 maxFileSize를 초과하면 로테이션\n if (stats.size >= this.maxFileSize)\n {\n await this.rotateBySize();\n }\n }\n catch (error)\n {\n // 파일 stat 실패 시 무시\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 크기 기반 로테이션 수행\n * 예: 2025-01-01.log -> 2025-01-01.1.log, 2025-01-01.1.log -> 2025-01-01.2.log\n */\n private async rotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n // 기존 스트림 닫기\n await this.closeStream();\n\n const baseName = this.currentFilename.replace(/\\.log$/, '');\n const files = readdirSync(this.logDir);\n\n // 현재 날짜의 로그 파일들 찾기 (예: 2025-01-01.log, 2025-01-01.1.log, ...)\n const relatedFiles = files\n .filter(file => file.startsWith(baseName) && file.endsWith('.log'))\n .sort()\n .reverse(); // 역순 정렬로 높은 번호부터 처리\n\n // 기존 파일들을 번호 증가시켜 이동 (예: .1.log -> .2.log)\n for (const file of relatedFiles)\n {\n const match = file.match(/\\.(\\d+)\\.log$/);\n if (match)\n {\n const oldNum = parseInt(match[1], 10);\n const newNum = oldNum + 1;\n const oldPath = join(this.logDir, file);\n const newPath = join(this.logDir, `${baseName}.${newNum}.log`);\n\n try\n {\n renameSync(oldPath, newPath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}\\n`);\n }\n }\n }\n\n // 현재 파일을 .1.log로 이동\n const currentPath = join(this.logDir, this.currentFilename);\n const newPath = join(this.logDir, `${baseName}.1.log`);\n\n try\n {\n if (existsSync(currentPath))\n {\n renameSync(currentPath, newPath);\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}\\n`);\n }\n\n // 새 스트림 생성 (동일한 파일명으로)\n await this.rotateStream(this.currentFilename);\n }\n\n /**\n * 오래된 로그 파일 정리\n * maxFiles 개수를 초과하는 로그 파일 삭제\n */\n private async cleanOldFiles(): Promise<void>\n {\n try\n {\n // 디렉토리가 존재하지 않으면 스킵\n if (!existsSync(this.logDir))\n {\n return;\n }\n\n const files = readdirSync(this.logDir);\n\n // .log로 끝나는 파일만 필터링 후 수정 시간 기준 정렬\n const logFiles = files\n .filter(file => file.endsWith('.log'))\n .map(file =>\n {\n const filepath = join(this.logDir, file);\n const stats = statSync(filepath);\n return { file, mtime: stats.mtime };\n })\n .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); // 최신 파일이 앞으로\n\n // maxFiles를 초과하는 오래된 파일들 삭제\n if (logFiles.length > this.maxFiles)\n {\n const filesToDelete = logFiles.slice(this.maxFiles);\n\n for (const { file } of filesToDelete)\n {\n const filepath = join(this.logDir, file);\n try\n {\n unlinkSync(filepath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to delete old file \"${file}\": ${errorMessage}\\n`);\n }\n }\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 날짜별 로그 파일명 생성\n */\n private getLogFilename(date: Date): string\n {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}.log`;\n }\n\n async close(): Promise<void>\n {\n // 스트림 정리\n await this.closeStream();\n }\n}","/**\n * Logger Configuration\n *\n * Environment-based logger configuration with validation for console, file, Slack, and Email transports.\n */\n\nimport { existsSync, accessSync, constants, mkdirSync, writeFileSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type {\n LogLevel,\n ConsoleTransportConfig,\n FileTransportConfig,\n SlackTransportConfig,\n EmailTransportConfig,\n} from './types';\n\n/**\n * Check if file logging is enabled (for self-hosted)\n */\nexport function isFileLoggingEnabled(): boolean\n{\n return process.env.LOGGER_FILE_ENABLED === 'true';\n}\n\n/**\n * Get default log level by environment\n */\nexport function getDefaultLogLevel(): LogLevel\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment)\n {\n return 'debug';\n }\n\n if (isProduction)\n {\n return 'info';\n }\n\n // Test environment\n return 'warn';\n}\n\n/**\n * Console Transport configuration\n */\nexport function getConsoleConfig(): ConsoleTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'debug',\n enabled: true,\n colorize: !isProduction, // Dev: colored output, Production: plain text\n };\n}\n\n/**\n * File Transport configuration\n */\nexport function getFileConfig(): FileTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'info',\n enabled: isProduction, // File logging in production only\n logDir: process.env.LOG_DIR || './logs',\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n };\n}\n\n/**\n * Slack Transport configuration\n */\nexport function getSlackConfig(): SlackTransportConfig | null\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return null; // Disabled if not configured\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'error', // Send error and above to Slack\n enabled: isProduction, // Enabled in production only\n webhookUrl,\n channel: process.env.SLACK_CHANNEL,\n username: process.env.SLACK_USERNAME || 'Logger Bot',\n };\n}\n\n/**\n * Email Transport configuration\n */\nexport function getEmailConfig(): EmailTransportConfig | null\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // Disabled if required settings are missing\n if (!smtpHost || !smtpPort || !emailFrom || !emailTo)\n {\n return null;\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'fatal', // Send fatal level only via email\n enabled: isProduction, // Enabled in production only\n from: emailFrom,\n to: emailTo.split(',').map(email => email.trim()),\n smtpHost,\n smtpPort: parseInt(smtpPort, 10),\n smtpUser: process.env.SMTP_USER,\n smtpPassword: process.env.SMTP_PASSWORD,\n };\n}\n\n/**\n * Validate directory path and write permissions\n */\nfunction validateDirectoryWritable(dirPath: string): void\n{\n // Check if directory exists\n if (!existsSync(dirPath))\n {\n // Try to create directory\n try\n {\n mkdirSync(dirPath, { recursive: true });\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to create log directory \"${dirPath}\": ${errorMessage}`);\n }\n }\n\n // Check write permission\n try\n {\n accessSync(dirPath, constants.W_OK);\n }\n catch\n {\n throw new Error(`Log directory \"${dirPath}\" is not writable. Please check permissions.`);\n }\n\n // Try to write a test file\n const testFile = join(dirPath, '.logger-write-test');\n try\n {\n writeFileSync(testFile, 'test', 'utf-8');\n unlinkSync(testFile);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Cannot write to log directory \"${dirPath}\": ${errorMessage}`);\n }\n}\n\n/**\n * Validate file transport configuration\n */\nfunction validateFileConfig(): void\n{\n if (!isFileLoggingEnabled())\n {\n return; // File logging disabled, skip validation\n }\n\n const logDir = process.env.LOG_DIR;\n\n // Check if LOG_DIR is set\n if (!logDir)\n {\n throw new Error(\n 'LOG_DIR environment variable is required when LOGGER_FILE_ENABLED=true. ' +\n 'Example: LOG_DIR=/var/log/myapp'\n );\n }\n\n // Validate directory\n validateDirectoryWritable(logDir);\n}\n\n/**\n * Validate Slack transport configuration\n */\nfunction validateSlackConfig(): void\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return; // Slack disabled, skip validation\n }\n\n // Validate webhook URL format\n if (!webhookUrl.startsWith('https://hooks.slack.com/'))\n {\n throw new Error(\n `Invalid SLACK_WEBHOOK_URL: \"${webhookUrl}\". ` +\n 'Slack webhook URLs must start with \"https://hooks.slack.com/\"'\n );\n }\n}\n\n/**\n * Validate Email transport configuration\n */\nfunction validateEmailConfig(): void\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // If any email config is set, all required fields must be present\n const hasAnyEmailConfig = smtpHost || smtpPort || emailFrom || emailTo;\n if (!hasAnyEmailConfig)\n {\n return; // Email disabled, skip validation\n }\n\n // Validate all required fields\n const missingFields: string[] = [];\n if (!smtpHost) missingFields.push('SMTP_HOST');\n if (!smtpPort) missingFields.push('SMTP_PORT');\n if (!emailFrom) missingFields.push('EMAIL_FROM');\n if (!emailTo) missingFields.push('EMAIL_TO');\n\n if (missingFields.length > 0)\n {\n throw new Error(\n `Email transport configuration incomplete. Missing: ${missingFields.join(', ')}. ` +\n 'Either set all required fields or remove all email configuration.'\n );\n }\n\n // Validate SMTP port is a number\n const port = parseInt(smtpPort!, 10);\n if (isNaN(port) || port < 1 || port > 65535)\n {\n throw new Error(\n `Invalid SMTP_PORT: \"${smtpPort}\". Must be a number between 1 and 65535.`\n );\n }\n\n // Validate email format (basic check)\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(emailFrom!))\n {\n throw new Error(`Invalid EMAIL_FROM format: \"${emailFrom}\"`);\n }\n\n // Validate email recipients\n const recipients = emailTo!.split(',').map(e => e.trim());\n for (const email of recipients)\n {\n if (!emailRegex.test(email))\n {\n throw new Error(`Invalid email address in EMAIL_TO: \"${email}\"`);\n }\n }\n}\n\n/**\n * Validate environment variables\n */\nfunction validateEnvironment(): void\n{\n const nodeEnv = process.env.NODE_ENV;\n\n if (!nodeEnv)\n {\n process.stderr.write(\n '[Logger] Warning: NODE_ENV is not set. Defaulting to test environment.\\n'\n );\n }\n // Allow any NODE_ENV value (development, production, test, staging, local, etc.)\n // No validation needed - users can use custom environments\n}\n\n/**\n * Validate all logger configuration\n * Throws an error if configuration is invalid\n */\nexport function validateConfig(): void\n{\n try\n {\n validateEnvironment();\n validateFileConfig();\n validateSlackConfig();\n validateEmailConfig();\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n throw new Error(`[Logger] Configuration validation failed: ${error.message}`);\n }\n throw error;\n }\n}","/**\n * Custom Logger Adapter\n *\n * 자체 구현한 Logger를 사용하는 Adapter\n *\n * ✅ 구현 완료:\n * - 기존 Logger 클래스 래핑\n * - Transport 시스템 (Console, File)\n * - Child logger 지원\n *\n * 💡 용도:\n * - Pino 의존성 제거 필요시\n * - 커스텀 Transport 필요시\n * - 완전한 제어가 필요한 경우\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현)\n * - src/logger/adapters/types.ts (인터페이스)\n */\n\nimport { Logger } from '../logger';\nimport { ConsoleTransport } from '../transports/console';\nimport { FileTransport } from '../transports/file';\nimport { getConsoleConfig, getFileConfig } from '../config';\nimport type { LoggerAdapter, AdapterConfig } from './types';\nimport type { Transport } from '../types';\n\n/**\n * Transport 초기화\n */\nfunction initializeTransports(): Transport[]\n{\n const transports: Transport[] = [];\n\n // Console Transport (항상 활성화)\n const consoleConfig = getConsoleConfig();\n transports.push(new ConsoleTransport(consoleConfig));\n\n // File Transport (프로덕션에서만 활성화)\n const fileConfig = getFileConfig();\n if (fileConfig.enabled)\n {\n transports.push(new FileTransport(fileConfig));\n }\n\n return transports;\n}\n\n/**\n * Custom Logger Adapter\n */\nexport class CustomAdapter implements LoggerAdapter\n{\n private logger: Logger;\n\n constructor(config: AdapterConfig)\n {\n this.logger = new Logger({\n level: config.level,\n module: config.module,\n transports: initializeTransports(),\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const adapter = new CustomAdapter({ level: this.logger.level, module });\n adapter.logger = this.logger.child(module);\n return adapter;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(message, context);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn(message, errorOrContext, context);\n }\n else\n {\n this.logger.warn(message, errorOrContext);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error(message, errorOrContext, context);\n }\n else\n {\n this.logger.error(message, errorOrContext);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal(message, errorOrContext, context);\n }\n else\n {\n this.logger.fatal(message, errorOrContext);\n }\n }\n\n async close(): Promise<void>\n {\n await this.logger.close();\n }\n}","/**\n * Logger Adapter Factory\n *\n * Adapter creation and initialization logic\n */\n\nimport { PinoAdapter } from './adapters/pino.js';\nimport { CustomAdapter } from './adapters/custom.js';\nimport { getDefaultLogLevel, validateConfig } from './config.js';\nimport type { LoggerAdapter } from './adapters/types.js';\n\n/**\n * Adapter type\n */\ntype AdapterType = 'pino' | 'custom';\n\n/**\n * Create adapter instance\n */\nfunction createAdapter(type: AdapterType): LoggerAdapter\n{\n const level = getDefaultLogLevel();\n\n switch (type)\n {\n case 'pino':\n return new PinoAdapter({ level });\n\n case 'custom':\n return new CustomAdapter({ level });\n\n default:\n return new PinoAdapter({ level });\n }\n}\n\n/**\n * Read adapter type from environment variable\n */\nfunction getAdapterType(): AdapterType\n{\n const adapterEnv = process.env.LOGGER_ADAPTER as AdapterType;\n\n if (adapterEnv === 'custom' || adapterEnv === 'pino')\n {\n return adapterEnv;\n }\n\n // Default: pino\n return 'pino';\n}\n\n/**\n * Initialize logger with configuration validation\n */\nfunction initializeLogger(): LoggerAdapter\n{\n // Validate configuration before creating logger\n validateConfig();\n\n // Create and return logger instance\n return createAdapter(getAdapterType());\n}\n\n/**\n * Singleton Logger instance\n */\nexport const logger: LoggerAdapter = initializeLogger();","/**\n * Contract Watcher & Client Generator\n *\n * Watches contract files and regenerates client code\n */\n\nimport { join } from 'path';\nimport { watch as chokidarWatch } from 'chokidar';\nimport { scanContracts } from './contract-scanner.js';\nimport { generateClient } from './client-generator.js';\nimport { logger } from '../logger';\nimport type { GenerationStats } from './types.js';\n\nconst codegenLogger = logger.child('codegen');\n\nexport interface WatchGenerateOptions {\n /** Routes directory (default: src/server/routes) */\n routesDir?: string;\n\n /** Output path for generated client (default: src/lib/api.ts) */\n outputPath?: string;\n\n /** Base URL for API client */\n baseUrl?: string;\n\n /** Enable debug logging */\n debug?: boolean;\n\n /** Watch mode (default: true) */\n watch?: boolean;\n}\n\n/**\n * Generate client once\n */\nasync function generateOnce(options: WatchGenerateOptions): Promise<GenerationStats | null> {\n const cwd = process.cwd();\n const routesDir = options.routesDir ?? join(cwd, 'src', 'server', 'routes');\n const outputPath = options.outputPath ?? join(cwd, 'src', 'lib', 'api.ts');\n\n try {\n // Scan contracts\n const contracts = await scanContracts(routesDir);\n\n if (contracts.length === 0)\n {\n if (options.debug)\n {\n codegenLogger.warn('No contracts found');\n }\n return null;\n }\n\n // Generate client\n const stats: GenerationStats = await generateClient(contracts, {\n routesDir,\n outputPath,\n baseUrl: options.baseUrl,\n includeTypes: true,\n includeJsDoc: true\n });\n\n // Log stats\n if (options.debug)\n {\n codegenLogger.info('Client generated', {\n endpoints: stats.methodsGenerated,\n resources: stats.resourcesGenerated,\n duration: stats.duration\n });\n }\n\n return stats;\n }\n catch (error)\n {\n codegenLogger.error(\n 'Generation failed',\n error instanceof Error ? error : new Error(String(error))\n );\n return null;\n }\n}\n\n/**\n * Watch contracts and generate client code\n */\nexport async function watchAndGenerate(options: WatchGenerateOptions = {}): Promise<void> {\n const cwd = process.cwd();\n const routesDir = options.routesDir ?? join(cwd, 'src', 'server', 'routes');\n const outputPath = options.outputPath ?? join(cwd, 'src', 'lib', 'api.ts');\n const watchMode = options.watch !== false;\n\n if (options.debug)\n {\n codegenLogger.info('Contract Watcher Started', { routesDir, outputPath, watch: watchMode });\n }\n\n // Initial generation\n await generateOnce(options);\n\n // Watch mode\n if (watchMode) {\n let isGenerating = false;\n let pendingRegeneration = false;\n\n const watcher = chokidarWatch(routesDir, {\n ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50\n }\n });\n\n const regenerate = async () => {\n if (isGenerating) {\n pendingRegeneration = true;\n return;\n }\n\n isGenerating = true;\n pendingRegeneration = false;\n\n if (options.debug) {\n codegenLogger.info('Contracts changed, regenerating...');\n }\n\n await generateOnce(options);\n\n isGenerating = false;\n\n if (pendingRegeneration) {\n await regenerate();\n }\n };\n\n watcher\n .on('add', regenerate)\n .on('change', regenerate)\n .on('unlink', regenerate);\n\n // Keep process alive\n process.on('SIGINT', () => {\n watcher.close();\n process.exit(0);\n });\n\n // Keep the process alive\n await new Promise(() => {});\n }\n}\n\n// Auto-run if executed directly\nif (import.meta.url === `file://${process.argv[1]}`) {\n watchAndGenerate({ debug: true });\n}","/**\n * Codegen Orchestrator\n *\n * Manages multiple code generators and coordinates their execution\n */\n\nimport { watch as chokidarWatch } from 'chokidar';\nimport { join, relative } from 'path';\nimport mm from 'micromatch';\nimport type { Generator, GeneratorOptions } from './generator.js';\nimport { logger } from '../logger';\n\nconst orchestratorLogger = logger.child('orchestrator');\n\nexport interface OrchestratorOptions\n{\n /** List of generators to orchestrate */\n generators: Generator[];\n\n /** Project root directory */\n cwd?: string;\n\n /** Enable debug logging */\n debug?: boolean;\n}\n\nexport class CodegenOrchestrator\n{\n private readonly generators: Generator[];\n private readonly cwd: string;\n private readonly debug: boolean;\n private isGenerating = false;\n private pendingRegenerations = new Set<string>();\n\n constructor(options: OrchestratorOptions)\n {\n this.generators = options.generators;\n this.cwd = options.cwd ?? process.cwd();\n this.debug = options.debug ?? false;\n }\n\n /**\n * Run all generators once\n */\n async generateAll(): Promise<void>\n {\n if (this.debug)\n {\n orchestratorLogger.info('Running all generators', {\n count: this.generators.length,\n names: this.generators.map(g => g.name)\n });\n }\n\n for (const generator of this.generators)\n {\n try\n {\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug\n };\n\n await generator.generate(genOptions);\n\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Generated successfully`);\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] Generation failed`, err);\n }\n }\n }\n\n /**\n * Start watch mode\n */\n async watch(): Promise<void>\n {\n // Initial generation\n await this.generateAll();\n\n // Collect all watch patterns from generators\n const allPatterns = this.generators.flatMap(g => g.watchPatterns);\n\n if (allPatterns.length === 0)\n {\n orchestratorLogger.warn('No watch patterns defined, exiting watch mode');\n return;\n }\n\n // Extract directories to watch from patterns\n // For pattern like \"watched/**/*.ts\", watch \"watched\" directory\n const dirsToWatch = new Set<string>();\n for (const pattern of allPatterns)\n {\n // Extract base directory from glob pattern (e.g., \"src/**/*.ts\" -> \"src\")\n const baseDir = pattern.split('**')[0].replace(/\\/$/, '') || '.';\n dirsToWatch.add(join(this.cwd, baseDir));\n }\n\n const watchDirs = Array.from(dirsToWatch);\n\n if (this.debug)\n {\n orchestratorLogger.info('Starting watch mode', {\n patterns: allPatterns,\n watchDirs,\n cwd: this.cwd\n });\n }\n\n const watcher = chokidarWatch(watchDirs, {\n ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50\n }\n });\n\n const handleChange = async (absolutePath: string, event: 'add' | 'change' | 'unlink') =>\n {\n // Convert absolute path to relative path for pattern matching\n const filePath = relative(this.cwd, absolutePath);\n\n if (this.isGenerating)\n {\n this.pendingRegenerations.add(absolutePath);\n return;\n }\n\n this.isGenerating = true;\n this.pendingRegenerations.clear();\n\n if (this.debug)\n {\n orchestratorLogger.info(`File ${event}`, { file: filePath });\n }\n\n // Find matching generators\n for (const generator of this.generators)\n {\n const matches = generator.watchPatterns.some(pattern =>\n mm.isMatch(filePath, pattern)\n );\n\n if (matches)\n {\n try\n {\n if (generator.onFileChange)\n {\n // Use custom handler\n await generator.onFileChange(filePath, event);\n }\n else\n {\n // Fallback to full regeneration\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug\n };\n await generator.generate(genOptions);\n }\n\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Regenerated`);\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] Regeneration failed`, err);\n }\n }\n }\n\n this.isGenerating = false;\n\n // Process pending regenerations\n if (this.pendingRegenerations.size > 0)\n {\n const next = Array.from(this.pendingRegenerations)[0];\n await handleChange(next, 'change');\n }\n };\n\n watcher\n .on('add', (path) => handleChange(path, 'add'))\n .on('change', (path) => handleChange(path, 'change'))\n .on('unlink', (path) => handleChange(path, 'unlink'));\n\n // Cleanup on exit\n process.on('SIGINT', () =>\n {\n if (this.debug)\n {\n orchestratorLogger.info('Shutting down watch mode');\n }\n watcher.close();\n process.exit(0);\n });\n\n // Keep process alive\n await new Promise(() => {});\n }\n}\n","/**\n * Contract Generator\n *\n * Generates type-safe API client from contract definitions\n */\n\nimport { join } from 'path';\nimport type { Generator, GeneratorOptions } from '../generator.js';\nimport { scanContracts } from '../contract-scanner.js';\nimport { generateClient } from '../client-generator.js';\nimport { logger } from '../../logger';\n\nconst contractLogger = logger.child('contract-gen');\n\nexport interface ContractGeneratorConfig\n{\n /** Routes directory (default: src/server/routes) */\n routesDir?: string;\n\n /** Output path (default: src/lib/api.ts) */\n outputPath?: string;\n\n /** Base URL for API client */\n baseUrl?: string;\n}\n\nexport function createContractGenerator(config: ContractGeneratorConfig = {}): Generator\n{\n return {\n name: 'contract',\n watchPatterns: [config.routesDir ?? 'src/server/routes/**/*.ts'],\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const cwd = options.cwd;\n const routesDir = config.routesDir ?? join(cwd, 'src', 'server', 'routes');\n const outputPath = config.outputPath ?? join(cwd, 'src', 'lib', 'api.ts');\n\n try\n {\n // Scan contracts\n const contracts = await scanContracts(routesDir);\n\n if (contracts.length === 0)\n {\n if (options.debug)\n {\n contractLogger.warn('No contracts found');\n }\n return;\n }\n\n // Generate client\n const stats = await generateClient(contracts, {\n routesDir,\n outputPath,\n baseUrl: config.baseUrl,\n includeTypes: true,\n includeJsDoc: true\n });\n\n if (options.debug)\n {\n contractLogger.info('Client generated', {\n endpoints: stats.methodsGenerated,\n resources: stats.resourcesGenerated,\n duration: stats.duration\n });\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n contractLogger.error('Generation failed', err);\n throw err;\n }\n }\n };\n}","/**\n * Codegen Configuration Loader\n *\n * Loads codegen configuration from .spfnrc.json or package.json\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createJiti } from 'jiti';\nimport type { Generator } from './generator.js';\nimport { createContractGenerator, type ContractGeneratorConfig } from './generators/contract-generator.js';\nimport { logger } from '../logger';\n\nconst configLogger = logger.child('config');\n\nexport interface CodegenConfig\n{\n generators?: Array<\n | { path: string } // Custom generator via file path\n | ({ name: 'contract' } & ContractGeneratorConfig & { enabled?: boolean }) // Built-in contract generator\n >;\n}\n\n/**\n * Load codegen configuration from .spfnrc.json or package.json\n */\nexport function loadCodegenConfig(cwd: string): CodegenConfig\n{\n // 1. Check .spfnrc.json\n const rcPath = join(cwd, '.spfnrc.json');\n if (existsSync(rcPath))\n {\n try\n {\n const content = readFileSync(rcPath, 'utf-8');\n const config = JSON.parse(content);\n\n if (config.codegen)\n {\n configLogger.info('Loaded config from .spfnrc.json');\n return config.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse .spfnrc.json', error as Error);\n }\n }\n\n // 2. Check package.json\n const pkgPath = join(cwd, 'package.json');\n if (existsSync(pkgPath))\n {\n try\n {\n const content = readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n\n if (pkg.spfn?.codegen)\n {\n configLogger.info('Loaded config from package.json');\n return pkg.spfn.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse package.json', error as Error);\n }\n }\n\n // 3. Default configuration\n configLogger.info('Using default config');\n return {\n generators: [\n { name: 'contract', enabled: true }\n ]\n };\n}\n\n/**\n * Create generator instances from configuration\n */\nexport async function createGeneratorsFromConfig(config: CodegenConfig, cwd: string): Promise<Generator[]>\n{\n const generators: Generator[] = [];\n\n if (!config.generators || config.generators.length === 0)\n {\n return generators;\n }\n\n for (const generatorConfig of config.generators)\n {\n try\n {\n // Custom generator (via file path)\n if ('path' in generatorConfig)\n {\n const generatorPath = generatorConfig.path.startsWith('.')\n ? join(cwd, generatorConfig.path)\n : generatorConfig.path;\n\n configLogger.info(`Loading custom generator: ${generatorPath}`);\n\n let module: any;\n\n // Use jiti for .ts files, regular import for .js\n if (generatorPath.endsWith('.ts'))\n {\n const jiti = createJiti(cwd, {\n interopDefault: true\n });\n module = jiti(generatorPath);\n }\n else\n {\n module = await import(generatorPath);\n }\n\n const createGenerator = module.default || module.createGenerator || module;\n\n if (typeof createGenerator === 'function')\n {\n const generator = createGenerator();\n generators.push(generator);\n configLogger.info(`Custom generator loaded: ${generator.name}`);\n }\n else\n {\n configLogger.warn(`Invalid generator at ${generatorPath}: expected function`);\n }\n }\n // Built-in contract generator\n else if ('name' in generatorConfig && generatorConfig.name === 'contract')\n {\n if (generatorConfig.enabled !== false)\n {\n const contractConfig: ContractGeneratorConfig = {\n routesDir: generatorConfig.routesDir,\n outputPath: generatorConfig.outputPath,\n baseUrl: generatorConfig.baseUrl\n };\n\n generators.push(createContractGenerator(contractConfig));\n configLogger.info('Contract generator enabled');\n }\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.error('Failed to load generator', err);\n }\n }\n\n return generators;\n}"]}
1
+ {"version":3,"sources":["../../src/codegen/contract-scanner.ts","../../src/codegen/route-scanner.ts","../../src/codegen/client-generator.ts","../../src/logger/adapters/pino.ts","../../src/logger/types.ts","../../src/logger/formatters.ts","../../src/logger/logger.ts","../../src/logger/transports/console.ts","../../src/logger/transports/file.ts","../../src/logger/config.ts","../../src/logger/adapters/custom.ts","../../src/logger/adapter-factory.ts","../../src/codegen/watch-generate.ts","../../src/codegen/orchestrator.ts","../../src/codegen/generators/contract-generator.ts","../../src/codegen/config-loader.ts"],"names":["join","newPath","existsSync","mkdirSync","unlinkSync","chokidarWatch","readFileSync"],"mappings":";;;;;;;;;;AAkBA,eAAsB,cAAc,SAAA,EACpC;AACI,EAAA,MAAM,aAAA,GAAgB,MAAM,iBAAA,CAAkB,SAAS,CAAA;AACvD,EAAA,MAAM,WAAmC,EAAC;AAE1C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,aAAA,CAAc,QAAQ,CAAA,EAAA,EAC1C;AACI,IAAA,MAAM,QAAA,GAAW,cAAc,CAAC,CAAA;AAChC,IAAA,MAAM,OAAA,GAAU,uBAAuB,QAAQ,CAAA;AAG/C,IAAA,MAAM,QAAA,GAAW,mBAAA,CAAoB,QAAA,EAAU,SAAS,CAAA;AAExD,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EACpC;AACI,MAAA,MAAM,cAAA,GAAiB,QAAQ,CAAC,CAAA;AAGhC,MAAA,MAAM,QAAA,GAAW,YAAA,CAAa,QAAA,EAAU,cAAA,CAAe,IAAI,CAAA;AAE3D,MAAA,QAAA,CAAS,IAAA,CAAK;AAAA,QACV,QAAQ,cAAA,CAAe,MAAA;AAAA,QACvB,IAAA,EAAM,QAAA;AAAA,QACN,cAAc,cAAA,CAAe,IAAA;AAAA,QAC7B,kBAAA,EAAoB,uBAAA,CAAwB,QAAA,EAAU,SAAS,CAAA;AAAA,QAC/D,SAAA,EAAW,EAAA;AAAA;AAAA,QACX,YAAA,EAAc;AAAA,OACjB,CAAA;AAAA,IACL;AAAA,EACJ;AAEA,EAAA,OAAO,QAAA;AACX;AAKA,eAAe,iBAAA,CAAkB,GAAA,EAAa,KAAA,GAAkB,EAAC,EACjE;AACI,EAAA,IACA;AACI,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAG,CAAA;AAEjC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EACpC;AACI,MAAA,MAAM,KAAA,GAAQ,QAAQ,CAAC,CAAA;AACvB,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,EAAK,KAAK,CAAA;AAChC,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,QAAQ,CAAA;AAEpC,MAAA,IAAI,QAAA,CAAS,aAAY,EACzB;AACI,QAAA,MAAM,iBAAA,CAAkB,UAAU,KAAK,CAAA;AAAA,MAC3C,CAAA,MAAA,IACS,UAAU,aAAA,EACnB;AACI,QAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,MACvB;AAAA,IACJ;AAAA,EACJ,SACO,KAAA,EACP;AAAA,EAEA;AAEA,EAAA,OAAO,KAAA;AACX;AAsBA,SAAS,uBAAuB,QAAA,EAChC;AACI,EAAA,MAAM,UAAA,GAAa,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AACjD,EAAA,MAAM,UAAA,GAAgB,EAAA,CAAA,gBAAA;AAAA,IAClB,QAAA;AAAA,IACA,UAAA;AAAA,IACG,EAAA,CAAA,YAAA,CAAa,MAAA;AAAA,IAChB;AAAA,GACJ;AAEA,EAAA,MAAM,UAA4B,EAAC;AAEnC,EAAA,SAAS,MAAM,IAAA,EACf;AAEI,IAAA,IAAO,EAAA,CAAA,mBAAA,CAAoB,IAAI,CAAA,EAC/B;AAEI,MAAA,MAAM,SAAA,GAAY,KAAK,SAAA,EAAW,IAAA;AAAA,QAC9B,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,KAAY,EAAA,CAAA,UAAA,CAAW;AAAA,OAClC;AAEA,MAAA,IAAI,SAAA,IAAa,IAAA,CAAK,eAAA,CAAgB,YAAA,CAAa,SAAS,CAAA,EAC5D;AACI,QAAA,MAAM,WAAA,GAAc,IAAA,CAAK,eAAA,CAAgB,YAAA,CAAa,CAAC,CAAA;AAEvD,QAAA,IACO,EAAA,CAAA,qBAAA,CAAsB,WAAW,CAAA,IACjC,EAAA,CAAA,YAAA,CAAa,WAAA,CAAY,IAAI,CAAA,IAChC,WAAA,CAAY,WAAA,IACT,EAAA,CAAA,yBAAA,CAA0B,WAAA,CAAY,WAAW,CAAA,EAExD;AACI,UAAA,MAAM,IAAA,GAAO,YAAY,IAAA,CAAK,IAAA;AAG9B,UAAA,IAAI,cAAA,CAAe,IAAI,CAAA,EACvB;AACI,YAAA,MAAM,YAAA,GAAe,mBAAA,CAAoB,WAAA,CAAY,WAAW,CAAA;AAEhE,YAAA,IAAI,YAAA,CAAa,MAAA,IAAU,YAAA,CAAa,IAAA,EACxC;AACI,cAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,gBACT,IAAA;AAAA,gBACA,QAAQ,YAAA,CAAa,MAAA;AAAA,gBACrB,MAAM,YAAA,CAAa;AAAA,eACtB,CAAA;AAAA,YACL;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAEA,IAAG,EAAA,CAAA,YAAA,CAAa,MAAM,KAAK,CAAA;AAAA,EAC/B;AAEA,EAAA,KAAA,CAAM,UAAU,CAAA;AAChB,EAAA,OAAO,OAAA;AACX;AAKA,SAAS,oBAAoB,aAAA,EAI7B;AACI,EAAA,MAAM,SAAiD,EAAC;AAExD,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,aAAA,CAAc,UAAA,CAAW,QAAQ,CAAA,EAAA,EACrD;AACI,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,UAAA,CAAW,CAAC,CAAA;AAEvC,IAAA,IACO,wBAAqB,IAAI,CAAA,IACzB,EAAA,CAAA,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA,EAE7B;AACI,MAAA,MAAM,QAAA,GAAW,KAAK,IAAA,CAAK,IAAA;AAE3B,MAAA,IAAI,aAAa,QAAA,EACjB;AAEI,QAAA,IAAI,KAAA;AACJ,QAAA,IAAO,EAAA,CAAA,eAAA,CAAgB,IAAA,CAAK,WAAW,CAAA,EACvC;AACI,UAAA,KAAA,GAAQ,KAAK,WAAA,CAAY,IAAA;AAAA,QAC7B,CAAA,MAAA,IACY,kBAAe,IAAA,CAAK,WAAW,KAAQ,EAAA,CAAA,eAAA,CAAgB,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA,EAC9F;AACI,UAAA,KAAA,GAAQ,IAAA,CAAK,YAAY,UAAA,CAAW,IAAA;AAAA,QACxC;AACA,QAAA,IAAI,KAAA,SAAc,MAAA,GAAS,KAAA;AAAA,MAC/B,CAAA,MAAA,IACS,aAAa,MAAA,EACtB;AAEI,QAAA,IAAI,KAAA;AACJ,QAAA,IAAO,EAAA,CAAA,eAAA,CAAgB,IAAA,CAAK,WAAW,CAAA,EACvC;AACI,UAAA,KAAA,GAAQ,KAAK,WAAA,CAAY,IAAA;AAAA,QAC7B,CAAA,MAAA,IACY,kBAAe,IAAA,CAAK,WAAW,KAAQ,EAAA,CAAA,eAAA,CAAgB,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA,EAC9F;AACI,UAAA,KAAA,GAAQ,IAAA,CAAK,YAAY,UAAA,CAAW,IAAA;AAAA,QACxC;AACA,QAAA,IAAI,KAAA,SAAc,IAAA,GAAO,KAAA;AAAA,MAC7B;AAAA,IACJ;AAAA,EACJ;AAEA,EAAA,OAAO,MAAA;AACX;AAKA,SAAS,eAAe,IAAA,EACxB;AACI,EAAA,OACI,KAAK,OAAA,CAAQ,UAAU,CAAA,KAAM,EAAA,IAC7B,KAAK,OAAA,CAAQ,UAAU,CAAA,KAAM,EAAA,IAC7B,KAAK,QAAA,CAAS,QAAQ,CAAA,IACtB,IAAA,CAAK,SAAS,QAAQ,CAAA;AAE9B;AAUA,SAAS,mBAAA,CAAoB,UAAkB,SAAA,EAC/C;AAEI,EAAA,IAAI,YAAA,GAAe,QAAA,CAAS,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AAGjD,EAAA,IAAI,YAAA,CAAa,UAAA,CAAW,GAAG,CAAA,EAC/B;AACI,IAAA,YAAA,GAAe,YAAA,CAAa,MAAM,CAAC,CAAA;AAAA,EACvC;AAGA,EAAA,YAAA,GAAe,YAAA,CAAa,OAAA,CAAQ,cAAA,EAAgB,EAAE,CAAA;AAGtD,EAAA,IAAI,YAAA,KAAiB,OAAA,IAAW,YAAA,KAAiB,EAAA,EACjD;AACI,IAAA,OAAO,GAAA;AAAA,EACX;AAGA,EAAA,MAAM,QAAA,GAAW,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA;AACvC,EAAA,MAAM,cAAwB,EAAC;AAE/B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EACrC;AACI,IAAA,MAAM,GAAA,GAAM,SAAS,CAAC,CAAA;AAGtB,IAAA,IAAI,QAAQ,OAAA,EACZ;AACI,MAAA;AAAA,IACJ;AAGA,IAAA,IAAI,IAAI,UAAA,CAAW,GAAG,KAAK,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAC3C;AACI,MAAA,WAAA,CAAY,KAAK,GAAA,GAAM,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,IAC3C,CAAA,MAGA;AACI,MAAA,WAAA,CAAY,KAAK,GAAG,CAAA;AAAA,IACxB;AAAA,EACJ;AAGA,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAC3B;AACI,IAAA,OAAO,GAAA;AAAA,EACX;AAEA,EAAA,OAAO,GAAA,GAAM,WAAA,CAAY,IAAA,CAAK,GAAG,CAAA;AACrC;AAUA,SAAS,YAAA,CAAa,UAAkB,YAAA,EACxC;AAEI,EAAA,QAAA,GAAW,QAAA,IAAY,GAAA;AACvB,EAAA,YAAA,GAAe,YAAA,IAAgB,GAAA;AAG/B,EAAA,IAAI,QAAA,CAAS,QAAA,CAAS,GAAG,CAAA,IAAK,aAAa,GAAA,EAC3C;AACI,IAAA,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACnC;AAGA,EAAA,IAAI,YAAA,CAAa,UAAA,CAAW,GAAG,CAAA,IAAK,iBAAiB,GAAA,EACrD;AAEI,IAAA,IAAI,aAAa,GAAA,EACjB;AACI,MAAA,OAAO,YAAA;AAAA,IACX;AAEA,IAAA,OAAO,QAAA,GAAW,YAAA;AAAA,EACtB;AAGA,EAAA,IAAI,iBAAiB,GAAA,EACrB;AACI,IAAA,OAAO,QAAA;AAAA,EACX;AAGA,EAAA,OAAO,WAAW,GAAA,GAAM,YAAA;AAC5B;AASA,SAAS,uBAAA,CAAwB,UAAkB,SAAA,EACnD;AAEI,EAAA,IAAI,YAAA,GAAe,QAAA,CAAS,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AAGjD,EAAA,IAAI,YAAA,CAAa,UAAA,CAAW,GAAG,CAAA,EAC/B;AACI,IAAA,YAAA,GAAe,YAAA,CAAa,MAAM,CAAC,CAAA;AAAA,EACvC;AAGA,EAAA,IAAI,YAAA,CAAa,QAAA,CAAS,KAAK,CAAA,EAC/B;AACI,IAAA,YAAA,GAAe,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EAC3C;AAGA,EAAA,OAAO,kBAAA,GAAqB,YAAA;AAChC;;;ACjWO,SAAS,gBAAgB,QAAA,EAChC;AACI,EAAA,MAAM,UAAkD,EAAC;AAEzD,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EACrC;AACI,IAAA,MAAM,OAAA,GAAU,SAAS,CAAC,CAAA;AAC1B,IAAA,MAAM,QAAA,GAAW,mBAAA,CAAoB,OAAA,CAAQ,IAAI,CAAA;AAEjD,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAQ,CAAA,EACrB;AACI,MAAA,OAAA,CAAQ,QAAQ,IAAI,EAAC;AAAA,IACzB;AAEA,IAAA,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA;AAAA,EAClC;AAEA,EAAA,OAAO,OAAA;AACX;AAWA,SAAS,oBAAoB,IAAA,EAC7B;AAEI,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,IAAK,CAAA,KAAM,GAAG,CAAA;AAGpE,EAAA,MAAM,iBAA2B,EAAC;AAClC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EACrC;AACI,IAAA,MAAM,GAAA,GAAM,SAAS,CAAC,CAAA;AACtB,IAAA,IAAI,CAAC,GAAA,CAAI,UAAA,CAAW,GAAG,CAAA,EACvB;AACI,MAAA,cAAA,CAAe,KAAK,GAAG,CAAA;AAAA,IAC3B;AAAA,EACJ;AAGA,EAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAC9B;AACI,IAAA,OAAO,MAAA;AAAA,EACX;AAGA,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,cAAA,CAAe,CAAC,GAAG,KAAK,CAAA;AAElD,EAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAC9B;AACI,IAAA,OAAO,KAAA;AAAA,EACX;AAGA,EAAA,MAAM,MAAA,GAAmB,CAAC,KAAK,CAAA;AAC/B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,cAAA,CAAe,QAAQ,CAAA,EAAA,EAC3C;AACI,IAAA,MAAM,GAAA,GAAM,eAAe,CAAC,CAAA;AAC5B,IAAA,MAAA,CAAO,IAAA,CAAK,WAAA,CAAY,GAAA,EAAK,IAAI,CAAC,CAAA;AAAA,EACtC;AAEA,EAAA,OAAO,MAAA,CAAO,KAAK,EAAE,CAAA;AACzB;AAcA,SAAS,WAAA,CAAY,KAAa,UAAA,EAClC;AAEI,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AAE9B,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EACrB;AAEI,IAAA,OAAO,UAAA,GACD,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,CAAE,aAAY,GAAI,GAAA,CAAI,KAAA,CAAM,CAAC,CAAA,GACzC,GAAA;AAAA,EACV;AAGA,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAClC;AACI,IAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,IAAA,IAAI,CAAA,KAAM,CAAA,IAAK,CAAC,UAAA,EAChB;AACI,MAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,IACpB,CAAA,MAEA;AACI,MAAA,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,aAAY,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,IAC5D;AAAA,EACJ;AAEA,EAAA,OAAO,MAAA,CAAO,KAAK,EAAE,CAAA;AACzB;AC5GA,eAAsB,cAAA,CAClB,UACA,OAAA,EAEJ;AACI,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAG3B,EAAA,MAAM,OAAA,GAAU,gBAAgB,QAAQ,CAAA;AACxC,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAGzC,EAAA,MAAM,IAAA,GAAO,kBAAA,CAAmB,QAAA,EAAU,OAAA,EAAS,OAAO,CAAA;AAG1D,EAAA,MAAM,KAAA,CAAM,QAAQ,OAAA,CAAQ,UAAU,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAG5D,EAAA,MAAM,SAAA,CAAU,OAAA,CAAQ,UAAA,EAAY,IAAA,EAAM,OAAO,CAAA;AAGjD,EAAA,OAAO;AAAA,IACH,eAAe,QAAA,CAAS,MAAA;AAAA,IACxB,gBAAgB,QAAA,CAAS,MAAA;AAAA,IACzB,aAAA,EAAe,yBAAyB,QAAQ,CAAA;AAAA,IAChD,oBAAoB,aAAA,CAAc,MAAA;AAAA,IAClC,kBAAkB,QAAA,CAAS,MAAA;AAAA,IAC3B,QAAA,EAAU,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,GAC3B;AACJ;AAKA,SAAS,kBAAA,CACL,QAAA,EACA,OAAA,EACA,OAAA,EAEJ;AACI,EAAA,IAAI,IAAA,GAAO,EAAA;AAGX,EAAA,IAAA,IAAQ,cAAA,EAAe;AAGvB,EAAA,IAAA,IAAQ,eAAA,CAAgB,UAAU,OAAO,CAAA;AAGzC,EAAA,IAAA,IAAQ,iBAAA,CAAkB,SAAS,OAAO,CAAA;AAG1C,EAAA,IAAA,IAAQ,cAAA,EAAe;AAEvB,EAAA,OAAO,IAAA;AACX;AAKA,SAAS,cAAA,GACT;AACI,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAAA,iBAMK,IAAI,IAAA,EAAK,EAAE,WAAA,EAAa;AAAA;;AAAA,CAAA;AAIxC;AAKA,SAAS,eAAA,CAAgB,UAAkC,OAAA,EAC3D;AACI,EAAA,IAAI,IAAA,GAAO,EAAA;AAEX,EAAA,IAAA,IAAQ,CAAA;AAAA,CAAA;AAER,EAAA,IAAI,OAAA,CAAQ,iBAAiB,KAAA,EAC7B;AACI,IAAA,IAAA,IAAQ,CAAA;AAAA,CAAA;AAAA,EACZ;AAEA,EAAA,IAAA,IAAQ;AAAA,CAAA;AAGR,EAAA,MAAM,YAAA,GAAe,2BAA2B,QAAQ,CAAA;AACxD,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA;AAE5C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,WAAA,CAAY,QAAQ,CAAA,EAAA,EACxC;AACI,IAAA,MAAM,UAAA,GAAa,YAAY,CAAC,CAAA;AAChC,IAAA,MAAM,SAAA,GAAY,aAAa,UAAU,CAAA;AAEzC,IAAA,IAAA,IAAQ,YAAY,SAAA,CAAU,IAAA,CAAK,IAAI,CAAC,YAAY,UAAU,CAAA;AAAA,CAAA;AAAA,EAClE;AAEA,EAAA,IAAA,IAAQ;AAAA,CAAA;AAER,EAAA,OAAO,IAAA;AACX;AAKA,SAAS,2BAA2B,QAAA,EACpC;AACI,EAAA,MAAM,SAAsC,EAAC;AAE7C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EACrC;AACI,IAAA,MAAM,OAAA,GAAU,SAAS,CAAC,CAAA;AAC1B,IAAA,MAAM,OAAO,OAAA,CAAQ,kBAAA;AAErB,IAAA,IAAI,CAAC,MAAA,CAAO,IAAI,CAAA,EAChB;AACI,MAAA,MAAA,CAAO,IAAI,CAAA,mBAAI,IAAI,GAAA,EAAI;AAAA,IAC3B;AAEA,IAAA,MAAA,CAAO,IAAI,CAAA,CAAE,GAAA,CAAI,OAAA,CAAQ,YAAY,CAAA;AAAA,EACzC;AAGA,EAAA,MAAM,SAAmC,EAAC;AAC1C,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AAE/B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EACjC;AACI,IAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACxC;AAEA,EAAA,OAAO,MAAA;AACX;AAKA,SAAS,iBAAA,CACL,SACA,OAAA,EAEJ;AACI,EAAA,IAAI,IAAA,GAAO,EAAA;AAEX,EAAA,IAAA,IAAQ,CAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAKR,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAEzC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,aAAA,CAAc,QAAQ,CAAA,EAAA,EAC1C;AACI,IAAA,MAAM,YAAA,GAAe,cAAc,CAAC,CAAA;AACpC,IAAA,MAAM,MAAA,GAAS,QAAQ,YAAY,CAAA;AAEnC,IAAA,IAAA,IAAQ,OAAO,YAAY,CAAA;AAAA,CAAA;AAE3B,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EACnC;AACI,MAAA,MAAM,KAAA,GAAQ,OAAO,CAAC,CAAA;AACtB,MAAA,IAAA,IAAQ,kBAAA,CAAmB,OAAO,OAAO,CAAA;AAAA,IAC7C;AAEA,IAAA,IAAA,IAAQ,CAAA,KAAA,CAAA;AAER,IAAA,IAAI,CAAA,GAAI,aAAA,CAAc,MAAA,GAAS,CAAA,EAC/B;AACI,MAAA,IAAA,IAAQ,CAAA,CAAA,CAAA;AAAA,IACZ;AAEA,IAAA,IAAA,IAAQ;AAAA,CAAA;AAAA,EACZ;AAEA,EAAA,IAAA,IAAQ,CAAA;;AAAA,CAAA;AAER,EAAA,OAAO,IAAA;AACX;AAKA,SAAS,kBAAA,CAAmB,SAA+B,OAAA,EAC3D;AACI,EAAA,MAAM,UAAA,GAAa,mBAAmB,OAAO,CAAA;AAC7C,EAAA,MAAM,YAAA,GAAe,CAAA,OAAA,EAAU,OAAA,CAAQ,YAAY,CAAA,CAAA;AACnD,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA;AAE3C,EAAA,MAAM,OAAA,GAAU,CAAC,MAAA,EAAQ,KAAA,EAAO,OAAO,CAAA,CAAE,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA,KAAM,EAAA;AAErE,EAAA,IAAI,IAAA,GAAO,EAAA;AAGX,EAAA,IAAI,OAAA,CAAQ,iBAAiB,KAAA,EAC7B;AACI,IAAA,IAAA,IAAQ,CAAA;AAAA,CAAA;AACR,IAAA,IAAA,IAAQ,CAAA,WAAA,EAAc,OAAA,CAAQ,MAAM,CAAA,CAAA,EAAI,QAAQ,IAAI;AAAA,CAAA;AACpD,IAAA,IAAA,IAAQ,CAAA;AAAA,CAAA;AAAA,EACZ;AAGA,EAAA,IAAA,IAAQ,WAAW,UAAU,CAAA,GAAA,CAAA;AAG7B,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,IAAI,SAAA,EACJ;AACI,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,sBAAA,EAAyB,YAAY,CAAA,WAAA,CAAa,CAAA;AAAA,EAClE;AAOA,EAAA,IAAI,OAAA,EACJ;AACI,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,oBAAA,EAAuB,YAAY,CAAA,SAAA,CAAW,CAAA;AAAA,EAC9D;AAEA,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EACpB;AACI,IAAA,IAAA,IAAQ,CAAA,WAAA,EAAc,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,CAAA;AAAA,EAC3C;AAEA,EAAA,IAAA,IAAQ,CAAA,KAAA,CAAA;AAGR,EAAA,IAAA,IAAQ,CAAA,aAAA,EAAgB,OAAA,CAAQ,IAAI,CAAA,GAAA,EAAM,QAAQ,YAAY,CAAA,CAAA;AAE9D,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EACpB;AACI,IAAA,IAAA,IAAQ,CAAA,SAAA,CAAA;AAAA,EACZ;AAEA,EAAA,IAAA,IAAQ,CAAA;AAAA,CAAA;AAER,EAAA,OAAO,IAAA;AACX;AAKA,SAAS,mBAAmB,OAAA,EAC5B;AACI,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,WAAA,EAAY;AAG1C,EAAA,IAAI,QAAQ,IAAA,KAAS,GAAA,IAAO,QAAQ,IAAA,CAAK,KAAA,CAAM,YAAY,CAAA,EAC3D;AAEI,IAAA,IAAI,WAAW,KAAA,EACf;AACI,MAAA,OAAO,MAAA;AAAA,IACX;AACA,IAAA,IAAI,WAAW,MAAA,EACf;AACI,MAAA,OAAO,QAAA;AAAA,IACX;AAAA,EACJ;AAGA,EAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAC7B;AACI,IAAA,IAAI,WAAW,KAAA,EACf;AACI,MAAA,OAAO,SAAA;AAAA,IACX;AACA,IAAA,IAAI,MAAA,KAAW,KAAA,IAAS,MAAA,KAAW,OAAA,EACnC;AACI,MAAA,OAAO,QAAA;AAAA,IACX;AACA,IAAA,IAAI,WAAW,QAAA,EACf;AACI,MAAA,OAAO,QAAA;AAAA,IACX;AAAA,EACJ;AAGA,EAAA,OAAO,MAAA;AACX;AAKA,SAAS,cAAA,GACT;AACI,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAmBX;AAKA,SAAS,yBAAyB,QAAA,EAClC;AACI,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAE9B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EACrC;AACI,IAAA,IAAI,QAAA,CAAS,CAAC,CAAA,CAAE,YAAA,EAChB;AACI,MAAA,KAAA,CAAM,GAAA,CAAI,QAAA,CAAS,CAAC,CAAA,CAAE,YAAsB,CAAA;AAAA,IAChD;AAAA,EACJ;AAEA,EAAA,OAAO,KAAA,CAAM,IAAA;AACjB;AC7UO,IAAM,WAAA,GAAN,MAAM,YAAA,CACb;AAAA,EACY,MAAA;AAAA,EAER,YAAY,MAAA,EACZ;AAMI,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK;AAAA,MACf,OAAO,MAAA,CAAO,KAAA;AAAA;AAAA,MAGd,MAAM,MAAA,CAAO,MAAA,GAAS,EAAE,MAAA,EAAQ,MAAA,CAAO,QAAO,GAAI;AAAA,KACrD,CAAA;AAAA,EACL;AAAA,EAEA,MAAM,MAAA,EACN;AACI,IAAA,MAAM,WAAA,GAAc,IAAI,YAAA,CAAY,EAAE,OAAO,IAAA,CAAK,MAAA,CAAO,KAAA,EAAmB,MAAA,EAAQ,CAAA;AACpF,IAAA,WAAA,CAAY,SAAS,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,EAAE,QAAQ,CAAA;AACjD,IAAA,OAAO,WAAA;AAAA,EACX;AAAA,EAEA,KAAA,CAAM,SAAiB,OAAA,EACvB;AACI,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,IAAW,IAAI,OAAO,CAAA;AAAA,EAC5C;AAAA,EAEA,IAAA,CAAK,SAAiB,OAAA,EACtB;AACI,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA,IAAW,IAAI,OAAO,CAAA;AAAA,EAC3C;AAAA,EAEA,IAAA,CAAK,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACxE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,EAAE,GAAA,EAAK,gBAAgB,GAAG,OAAA,IAAW,OAAO,CAAA;AAAA,IACjE,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,cAAA,IAAkB,IAAI,OAAO,CAAA;AAAA,IAClD;AAAA,EACJ;AAAA,EAEA,KAAA,CAAM,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACzE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,EAAE,GAAA,EAAK,gBAAgB,GAAG,OAAA,IAAW,OAAO,CAAA;AAAA,IAClE,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,cAAA,IAAkB,IAAI,OAAO,CAAA;AAAA,IACnD;AAAA,EACJ;AAAA,EAEA,KAAA,CAAM,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACzE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,EAAE,GAAA,EAAK,gBAAgB,GAAG,OAAA,IAAW,OAAO,CAAA;AAAA,IAClE,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,cAAA,IAAkB,IAAI,OAAO,CAAA;AAAA,IACnD;AAAA,EACJ;AAAA,EAEA,MAAM,KAAA,GACN;AAAA,EAGA;AACJ,CAAA;;;AC/DO,IAAM,kBAAA,GAA+C;AAAA,EACxD,KAAA,EAAO,CAAA;AAAA,EACP,IAAA,EAAM,CAAA;AAAA,EACN,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO,CAAA;AAAA,EACP,KAAA,EAAO;AACX,CAAA;;;ACpBA,IAAM,cAAA,GAAiB;AAAA,EACnB,UAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,eAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA;AACJ,CAAA;AAKA,IAAM,YAAA,GAAe,cAAA;AAKrB,SAAS,eAAe,GAAA,EACxB;AACI,EAAA,MAAM,QAAA,GAAW,IAAI,WAAA,EAAY;AACjC,EAAA,OAAO,eAAe,IAAA,CAAK,CAAA,SAAA,KAAa,QAAA,CAAS,QAAA,CAAS,SAAS,CAAC,CAAA;AACxE;AASO,SAAS,kBAAkB,IAAA,EAClC;AAEI,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,IAAA,KAAS,MAAA,EAC9B;AACI,IAAA,OAAO,IAAA;AAAA,EACX;AAGA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EACtB;AACI,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,IAAA,KAAQ,iBAAA,CAAkB,IAAI,CAAC,CAAA;AAAA,EACnD;AAGA,EAAA,IAAI,OAAO,SAAS,QAAA,EACpB;AACI,IAAA,MAAM,SAAkC,EAAC;AAEzC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAC9C;AACI,MAAA,IAAI,cAAA,CAAe,GAAG,CAAA,EACtB;AAEI,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,YAAA;AAAA,MAClB,CAAA,MAAA,IACS,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,IAAA,EAChD;AAEI,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,iBAAA,CAAkB,KAAK,CAAA;AAAA,MACzC,CAAA,MAEA;AAEI,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,MAClB;AAAA,IACJ;AAEA,IAAA,OAAO,MAAA;AAAA,EACX;AAGA,EAAA,OAAO,IAAA;AACX;AAKA,IAAM,MAAA,GAAS;AAAA,EACX,KAAA,EAAO,SAAA;AAAA,EACP,MAAA,EAAQ,SAAA;AAAA,EACR,GAAA,EAAK,SAAA;AAAA;AAAA,EAGL,KAAA,EAAO,UAAA;AAAA;AAAA,EACP,IAAA,EAAM,UAAA;AAAA;AAAA,EACN,IAAA,EAAM,UAAA;AAAA;AAAA,EACN,KAAA,EAAO,UAAA;AAAA;AAAA,EACP,KAAA,EAAO,UAAA;AAAA;AAAA;AAAA,EAGP,IAAA,EAAM;AACV,CAAA;AAeO,SAAS,gBAAgB,IAAA,EAChC;AACI,EAAA,OAAO,KAAK,WAAA,EAAY;AAC5B;AAKO,SAAS,qBAAqB,IAAA,EACrC;AACI,EAAA,MAAM,IAAA,GAAO,KAAK,WAAA,EAAY;AAC9B,EAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,CAAK,QAAA,KAAa,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AACzD,EAAA,MAAM,GAAA,GAAM,OAAO,IAAA,CAAK,OAAA,EAAS,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAClD,EAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,CAAK,QAAA,EAAU,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AACrD,EAAA,MAAM,OAAA,GAAU,OAAO,IAAA,CAAK,UAAA,EAAY,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AACzD,EAAA,MAAM,OAAA,GAAU,OAAO,IAAA,CAAK,UAAA,EAAY,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AACzD,EAAA,MAAM,EAAA,GAAK,OAAO,IAAA,CAAK,eAAA,EAAiB,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAEzD,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,EAAI,OAAO,IAAI,EAAE,CAAA,CAAA;AACvE;AAKO,SAAS,YAAY,KAAA,EAC5B;AACI,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,KAAK,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,EAAA,EAAK,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAE5C,EAAA,IAAI,MAAM,KAAA,EACV;AACI,IAAA,MAAM,aAAa,KAAA,CAAM,KAAA,CAAM,MAAM,IAAI,CAAA,CAAE,MAAM,CAAC,CAAA;AAClD,IAAA,KAAA,CAAM,IAAA,CAAK,GAAG,UAAU,CAAA;AAAA,EAC5B;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAC1B;AAoBO,SAAS,aAAA,CAAc,QAAA,EAAuB,QAAA,GAAW,IAAA,EAChE;AACI,EAAA,MAAM,QAAkB,EAAC;AAGzB,EAAA,MAAM,SAAA,GAAY,oBAAA,CAAqB,QAAA,CAAS,SAAS,CAAA;AACzD,EAAA,IAAI,QAAA,EACJ;AACI,IAAA,KAAA,CAAM,IAAA,CAAK,GAAG,MAAA,CAAO,IAAI,IAAI,SAAS,CAAA,CAAA,EAAI,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAAA,EAC5D,CAAA,MAEA;AACI,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,EAC/B;AAGA,EAAA,IAAI,SAAS,MAAA,EACb;AACI,IAAA,IAAI,QAAA,EACJ;AACI,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,MAAA,CAAO,GAAG,CAAA,QAAA,EAAW,SAAS,MAAM,CAAA,CAAA,EAAI,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAAA,IACxE,CAAA,MAEA;AACI,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,QAAA,EAAW,QAAA,CAAS,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,IAC5C;AAAA,EACJ;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,MAAA,CAAO,IAAA,CAAK,SAAS,OAAO,CAAA,CAAE,SAAS,CAAA,EAC/D;AACI,IAAA,MAAA,CAAO,OAAA,CAAQ,SAAS,OAAO,CAAA,CAAE,QAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KACrD;AACI,MAAA,MAAM,WAAW,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,OAAO,KAAK,CAAA;AACjE,MAAA,IAAI,QAAA,EACJ;AACI,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,MAAA,CAAO,GAAG,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAAA,MACjE,CAAA,MAEA;AACI,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,MACrC;AAAA,IACJ,CAAC,CAAA;AAAA,EACL;AAGA,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,WAAA,EAAY;AAC5C,EAAA,IAAI,QAAA,EACJ;AACI,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA;AACnC,IAAA,KAAA,CAAM,IAAA,CAAK,GAAG,KAAK,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,EACtD,CAAA,MAEA;AACI,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,EAAI,QAAQ,CAAA,EAAA,CAAI,CAAA;AAAA,EAC/B;AAGA,EAAA,IAAI,QAAA,EACJ;AACI,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,EAAG,SAAS,OAAO,CAAA,EAAG,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAAA,EACnE,CAAA,MAEA;AACI,IAAA,KAAA,CAAM,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B;AAEA,EAAA,IAAI,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA;AAG3B,EAAA,IAAI,SAAS,KAAA,EACb;AACI,IAAA,MAAA,IAAU,IAAA,GAAO,WAAA,CAAY,QAAA,CAAS,KAAK,CAAA;AAAA,EAC/C;AAEA,EAAA,OAAO,MAAA;AACX;AAKO,SAAS,WAAW,QAAA,EAC3B;AACI,EAAA,MAAM,GAAA,GAA+B;AAAA,IACjC,SAAA,EAAW,eAAA,CAAgB,QAAA,CAAS,SAAS,CAAA;AAAA,IAC7C,OAAO,QAAA,CAAS,KAAA;AAAA,IAChB,SAAS,QAAA,CAAS;AAAA,GACtB;AAEA,EAAA,IAAI,SAAS,MAAA,EACb;AACI,IAAA,GAAA,CAAI,SAAS,QAAA,CAAS,MAAA;AAAA,EAC1B;AAEA,EAAA,IAAI,SAAS,OAAA,EACb;AACI,IAAA,GAAA,CAAI,UAAU,QAAA,CAAS,OAAA;AAAA,EAC3B;AAEA,EAAA,IAAI,SAAS,KAAA,EACb;AACI,IAAA,GAAA,CAAI,KAAA,GAAQ;AAAA,MACR,IAAA,EAAM,SAAS,KAAA,CAAM,IAAA;AAAA,MACrB,OAAA,EAAS,SAAS,KAAA,CAAM,OAAA;AAAA,MACxB,KAAA,EAAO,SAAS,KAAA,CAAM;AAAA,KAC1B;AAAA,EACJ;AAEA,EAAA,OAAO,IAAA,CAAK,UAAU,GAAG,CAAA;AAC7B;;;ACpSO,IAAM,MAAA,GAAN,MAAM,OAAA,CACb;AAAA,EACqB,MAAA;AAAA,EACA,MAAA;AAAA,EAEjB,YAAY,MAAA,EACZ;AACI,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAA,GACJ;AACI,IAAA,OAAO,KAAK,MAAA,CAAO,KAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,EACN;AACI,IAAA,OAAO,IAAI,OAAA,CAAO;AAAA,MACd,GAAG,IAAA,CAAK,MAAA;AAAA,MACR;AAAA,KACH,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,CAAM,SAAiB,OAAA,EACvB;AACI,IAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,MAAA,EAAW,OAAO,CAAA;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,CAAK,SAAiB,OAAA,EACtB;AACI,IAAA,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,OAAA,EAAS,MAAA,EAAW,OAAO,CAAA;AAAA,EAChD;AAAA,EAOA,IAAA,CAAK,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACxE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,OAAA,EAAS,cAAA,EAAgB,OAAO,CAAA;AAAA,IACrD,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,OAAA,EAAS,MAAA,EAAW,cAAc,CAAA;AAAA,IACvD;AAAA,EACJ;AAAA,EAOA,KAAA,CAAM,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACzE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,cAAA,EAAgB,OAAO,CAAA;AAAA,IACtD,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,MAAA,EAAW,cAAc,CAAA;AAAA,IACxD;AAAA,EACJ;AAAA,EAOA,KAAA,CAAM,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACzE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,cAAA,EAAgB,OAAO,CAAA;AAAA,IACtD,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,MAAA,EAAW,cAAc,CAAA;AAAA,IACxD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKQ,GAAA,CAAI,KAAA,EAAiB,OAAA,EAAiB,KAAA,EAAe,OAAA,EAC7D;AAGI,IAAA,IAAI,mBAAmB,KAAK,CAAA,GAAI,mBAAmB,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EACpE;AACI,MAAA;AAAA,IACJ;AAEA,IAAA,MAAM,QAAA,GAAwB;AAAA,MAC1B,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,KAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,KAAA;AAAA;AAAA,MAEA,OAAA,EAAS,OAAA,GAAU,iBAAA,CAAkB,OAAO,CAAA,GAA+B;AAAA,KAC/E;AAGA,IAAA,IAAA,CAAK,kBAAkB,QAAQ,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,QAAA,EAC1B;AACI,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,UAAA,CACxB,OAAO,CAAA,SAAA,KAAa,SAAA,CAAU,OAAO,CAAA,CACrC,IAAI,CAAA,SAAA,KAAa,IAAA,CAAK,gBAAA,CAAiB,SAAA,EAAW,QAAQ,CAAC,CAAA;AAGhE,IAAA,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA,CAAE,KAAA,CAAM,CAAA,KAAA,KAC5B;AAEI,MAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,0BAAA,EAA6B,YAAY;AAAA,CAAI,CAAA;AAAA,IACtE,CAAC,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAA,CAAiB,SAAA,EAAsB,QAAA,EACrD;AACI,IAAA,IACA;AACI,MAAA,MAAM,SAAA,CAAU,IAAI,QAAQ,CAAA;AAAA,IAChC,SACO,KAAA,EACP;AAEI,MAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,MAAA,OAAA,CAAQ,OAAO,KAAA,CAAM,CAAA,oBAAA,EAAuB,SAAA,CAAU,IAAI,aAAa,YAAY;AAAA,CAAI,CAAA;AAAA,IAC3F;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,GACN;AACI,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,UAAA,CAC7B,MAAA,CAAO,CAAA,SAAA,KAAa,SAAA,CAAU,KAAK,CAAA,CACnC,GAAA,CAAI,CAAA,SAAA,KAAa,SAAA,CAAU,OAAQ,CAAA;AAExC,IAAA,MAAM,OAAA,CAAQ,IAAI,aAAa,CAAA;AAAA,EACnC;AACJ,CAAA;;;AC/JO,IAAM,mBAAN,MACP;AAAA,EACoB,IAAA,GAAO,SAAA;AAAA,EACP,KAAA;AAAA,EACA,OAAA;AAAA,EAER,QAAA;AAAA,EAER,YAAY,MAAA,EACZ;AACI,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AACpB,IAAA,IAAA,CAAK,UAAU,MAAA,CAAO,OAAA;AACtB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAO,QAAA,IAAY,IAAA;AAAA,EACvC;AAAA,EAEA,MAAM,IAAI,QAAA,EACV;AAEI,IAAA,IAAI,CAAC,KAAK,OAAA,EACV;AACI,MAAA;AAAA,IACJ;AAGA,IAAA,IAAI,mBAAmB,QAAA,CAAS,KAAK,IAAI,kBAAA,CAAmB,IAAA,CAAK,KAAK,CAAA,EACtE;AACI,MAAA;AAAA,IACJ;AAGA,IAAA,MAAM,OAAA,GAAU,aAAA,CAAc,QAAA,EAAU,IAAA,CAAK,QAAQ,CAAA;AAGrD,IAAA,IAAI,QAAA,CAAS,UAAU,MAAA,IAAU,QAAA,CAAS,UAAU,OAAA,IAAW,QAAA,CAAS,UAAU,OAAA,EAClF;AACI,MAAA,OAAA,CAAQ,MAAM,OAAO,CAAA;AAAA,IACzB,CAAA,MAEA;AACI,MAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,IACvB;AAAA,EACJ;AACJ,CAAA;ACjDO,IAAM,gBAAN,MACP;AAAA,EACoB,IAAA,GAAO,MAAA;AAAA,EACP,KAAA;AAAA,EACA,OAAA;AAAA,EAEC,MAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACT,aAAA,GAAoC,IAAA;AAAA,EACpC,eAAA,GAAiC,IAAA;AAAA,EAEzC,YAAY,MAAA,EACZ;AACI,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AACpB,IAAA,IAAA,CAAK,UAAU,MAAA,CAAO,OAAA;AACtB,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,WAAA,GAAc,MAAA,CAAO,WAAA,IAAe,EAAA,GAAK,IAAA,GAAO,IAAA;AACrD,IAAA,IAAA,CAAK,QAAA,GAAW,OAAO,QAAA,IAAY,EAAA;AAGnC,IAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,MAAM,CAAA,EAC3B;AACI,MAAA,SAAA,CAAU,IAAA,CAAK,MAAA,EAAQ,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,IAC9C;AAAA,EACJ;AAAA,EAEA,MAAM,IAAI,QAAA,EACV;AAEI,IAAA,IAAI,CAAC,KAAK,OAAA,EACV;AACI,MAAA;AAAA,IACJ;AAGA,IAAA,IAAI,mBAAmB,QAAA,CAAS,KAAK,IAAI,kBAAA,CAAmB,IAAA,CAAK,KAAK,CAAA,EACtE;AACI,MAAA;AAAA,IACJ;AAGA,IAAA,MAAM,OAAA,GAAU,WAAW,QAAQ,CAAA;AAGnC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,cAAA,CAAe,QAAA,CAAS,SAAS,CAAA;AAGvD,IAAA,IAAI,IAAA,CAAK,oBAAoB,QAAA,EAC7B;AACI,MAAA,MAAM,IAAA,CAAK,aAAa,QAAQ,CAAA;AAChC,MAAA,MAAM,KAAK,aAAA,EAAc;AAAA,IAC7B,CAAA,MAAA,IAES,KAAK,eAAA,EACd;AACI,MAAA,MAAM,KAAK,oBAAA,EAAqB;AAAA,IACpC;AAGA,IAAA,IAAI,KAAK,aAAA,EACT;AACI,MAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAC7B;AACI,QAAA,IAAA,CAAK,cAAe,KAAA,CAAM,OAAA,GAAU,IAAA,EAAM,OAAA,EAAS,CAAC,KAAA,KACpD;AACI,UAAA,IAAI,KAAA,EACJ;AAEI,YAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,qCAAA,EAAwC,KAAA,CAAM,OAAO;AAAA,CAAI,CAAA;AAC9E,YAAA,MAAA,CAAO,KAAK,CAAA;AAAA,UAChB,CAAA,MAEA;AACI,YAAA,OAAA,EAAQ;AAAA,UACZ;AAAA,QACJ,CAAC,CAAA;AAAA,MACL,CAAC,CAAA;AAAA,IACL;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aAAa,QAAA,EAC3B;AAEI,IAAA,IAAI,KAAK,aAAA,EACT;AACI,MAAA,MAAM,KAAK,WAAA,EAAY;AAAA,IAC3B;AAGA,IAAA,MAAM,QAAA,GAAWA,IAAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,QAAQ,CAAA;AAE3C,IAAA,IAAA,CAAK,aAAA,GAAgB,kBAAkB,QAAA,EAAU;AAAA,MAC7C,KAAA,EAAO,GAAA;AAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACb,CAAA;AAED,IAAA,IAAA,CAAK,eAAA,GAAkB,QAAA;AAGvB,IAAA,IAAA,CAAK,aAAA,CAAc,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAChC;AACI,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,8BAAA,EAAiC,KAAA,CAAM,OAAO;AAAA,CAAI,CAAA;AAEvE,MAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,IAC3B,CAAC,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,WAAA,GACd;AACI,IAAA,IAAI,CAAC,KAAK,aAAA,EACV;AACI,MAAA;AAAA,IACJ;AAEA,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAC7B;AACI,MAAA,IAAA,CAAK,aAAA,CAAe,GAAA,CAAI,CAAC,KAAA,KACzB;AACI,QAAA,IAAI,KAAA,EACJ;AACI,UAAA,MAAA,CAAO,KAAK,CAAA;AAAA,QAChB,CAAA,MAEA;AACI,UAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,UAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AACvB,UAAA,OAAA,EAAQ;AAAA,QACZ;AAAA,MACJ,CAAC,CAAA;AAAA,IACL,CAAC,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAA,GACd;AACI,IAAA,IAAI,CAAC,KAAK,eAAA,EACV;AACI,MAAA;AAAA,IACJ;AAEA,IAAA,MAAM,QAAA,GAAWA,IAAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,KAAK,eAAe,CAAA;AAGvD,IAAA,IAAI,CAAC,UAAA,CAAW,QAAQ,CAAA,EACxB;AACI,MAAA;AAAA,IACJ;AAEA,IAAA,IACA;AACI,MAAA,MAAM,KAAA,GAAQ,SAAS,QAAQ,CAAA;AAG/B,MAAA,IAAI,KAAA,CAAM,IAAA,IAAQ,IAAA,CAAK,WAAA,EACvB;AACI,QAAA,MAAM,KAAK,YAAA,EAAa;AAAA,MAC5B;AAAA,IACJ,SACO,KAAA,EACP;AAEI,MAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,2CAAA,EAA8C,YAAY;AAAA,CAAI,CAAA;AAAA,IACvF;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YAAA,GACd;AACI,IAAA,IAAI,CAAC,KAAK,eAAA,EACV;AACI,MAAA;AAAA,IACJ;AAGA,IAAA,MAAM,KAAK,WAAA,EAAY;AAEvB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,eAAA,CAAgB,OAAA,CAAQ,UAAU,EAAE,CAAA;AAC1D,IAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA;AAGrC,IAAA,MAAM,YAAA,GAAe,KAAA,CAChB,MAAA,CAAO,CAAA,IAAA,KAAQ,KAAK,UAAA,CAAW,QAAQ,CAAA,IAAK,IAAA,CAAK,SAAS,MAAM,CAAC,CAAA,CACjE,IAAA,GACA,OAAA,EAAQ;AAGb,IAAA,KAAA,MAAW,QAAQ,YAAA,EACnB;AACI,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,eAAe,CAAA;AACxC,MAAA,IAAI,KAAA,EACJ;AACI,QAAA,MAAM,MAAA,GAAS,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACpC,QAAA,MAAM,SAAS,MAAA,GAAS,CAAA;AACxB,QAAA,MAAM,OAAA,GAAUA,IAAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,IAAI,CAAA;AACtC,QAAA,MAAMC,QAAAA,GAAUD,KAAK,IAAA,CAAK,MAAA,EAAQ,GAAG,QAAQ,CAAA,CAAA,EAAI,MAAM,CAAA,IAAA,CAAM,CAAA;AAE7D,QAAA,IACA;AACI,UAAA,UAAA,CAAW,SAASC,QAAO,CAAA;AAAA,QAC/B,SACO,KAAA,EACP;AACI,UAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,UAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,uCAAA,EAA0C,YAAY;AAAA,CAAI,CAAA;AAAA,QACnF;AAAA,MACJ;AAAA,IACJ;AAGA,IAAA,MAAM,WAAA,GAAcD,IAAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,KAAK,eAAe,CAAA;AAC1D,IAAA,MAAM,UAAUA,IAAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,QAAQ,CAAA,MAAA,CAAQ,CAAA;AAErD,IAAA,IACA;AACI,MAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAC1B;AACI,QAAA,UAAA,CAAW,aAAa,OAAO,CAAA;AAAA,MACnC;AAAA,IACJ,SACO,KAAA,EACP;AACI,MAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,+CAAA,EAAkD,YAAY;AAAA,CAAI,CAAA;AAAA,IAC3F;AAGA,IAAA,MAAM,IAAA,CAAK,YAAA,CAAa,IAAA,CAAK,eAAe,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,aAAA,GACd;AACI,IAAA,IACA;AAEI,MAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,MAAM,CAAA,EAC3B;AACI,QAAA;AAAA,MACJ;AAEA,MAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA;AAGrC,MAAA,MAAM,QAAA,GAAW,KAAA,CACZ,MAAA,CAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,SAAS,MAAM,CAAC,CAAA,CACpC,GAAA,CAAI,CAAA,IAAA,KACL;AACI,QAAA,MAAM,QAAA,GAAWA,IAAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,IAAI,CAAA;AACvC,QAAA,MAAM,KAAA,GAAQ,SAAS,QAAQ,CAAA;AAC/B,QAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,CAAM,KAAA,EAAM;AAAA,MACtC,CAAC,CAAA,CACA,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,KAAA,CAAM,OAAA,EAAQ,GAAI,CAAA,CAAE,KAAA,CAAM,SAAS,CAAA;AAGzD,MAAA,IAAI,QAAA,CAAS,MAAA,GAAS,IAAA,CAAK,QAAA,EAC3B;AACI,QAAA,MAAM,aAAA,GAAgB,QAAA,CAAS,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA;AAElD,QAAA,KAAA,MAAW,EAAE,IAAA,EAAK,IAAK,aAAA,EACvB;AACI,UAAA,MAAM,QAAA,GAAWA,IAAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,IAAI,CAAA;AACvC,UAAA,IACA;AACI,YAAA,UAAA,CAAW,QAAQ,CAAA;AAAA,UACvB,SACO,KAAA,EACP;AACI,YAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,YAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,2CAAA,EAA8C,IAAI,MAAM,YAAY;AAAA,CAAI,CAAA;AAAA,UACjG;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ,SACO,KAAA,EACP;AACI,MAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,2CAAA,EAA8C,YAAY;AAAA,CAAI,CAAA;AAAA,IACvF;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,IAAA,EACvB;AACI,IAAA,MAAM,IAAA,GAAO,KAAK,WAAA,EAAY;AAC9B,IAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,CAAK,QAAA,KAAa,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AACzD,IAAA,MAAM,GAAA,GAAM,OAAO,IAAA,CAAK,OAAA,EAAS,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAElD,IAAA,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,IAAI,GAAG,CAAA,IAAA,CAAA;AAAA,EAClC;AAAA,EAEA,MAAM,KAAA,GACN;AAEI,IAAA,MAAM,KAAK,WAAA,EAAY;AAAA,EAC3B;AACJ,CAAA;ACvTO,SAAS,oBAAA,GAChB;AACI,EAAA,OAAO,OAAA,CAAQ,IAAI,mBAAA,KAAwB,MAAA;AAC/C;AAKO,SAAS,kBAAA,GAChB;AACI,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,YAAA;AAC9C,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA;AAE/C,EAAA,IAAI,aAAA,EACJ;AACI,IAAA,OAAO,OAAA;AAAA,EACX;AAEA,EAAA,IAAI,YAAA,EACJ;AACI,IAAA,OAAO,MAAA;AAAA,EACX;AAGA,EAAA,OAAO,MAAA;AACX;AAKO,SAAS,gBAAA,GAChB;AACI,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,YAAA;AAE9C,EAAA,OAAO;AAAA,IACH,KAAA,EAAO,OAAA;AAAA,IACP,OAAA,EAAS,IAAA;AAAA,IACT,UAAU,CAAC;AAAA;AAAA,GACf;AACJ;AAKO,SAAS,aAAA,GAChB;AACI,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,YAAA;AAE9C,EAAA,OAAO;AAAA,IACH,KAAA,EAAO,MAAA;AAAA,IACP,OAAA,EAAS,YAAA;AAAA;AAAA,IACT,MAAA,EAAQ,OAAA,CAAQ,GAAA,CAAI,OAAA,IAAW,QAAA;AAAA,IAC/B,WAAA,EAAa,KAAK,IAAA,GAAO,IAAA;AAAA;AAAA,IACzB,QAAA,EAAU;AAAA,GACd;AACJ;AA0DA,SAAS,0BAA0B,OAAA,EACnC;AAEI,EAAA,IAAI,CAACE,UAAAA,CAAW,OAAO,CAAA,EACvB;AAEI,IAAA,IACA;AACI,MAAAC,SAAAA,CAAU,OAAA,EAAS,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,IAC1C,SACO,KAAA,EACP;AACI,MAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,OAAO,CAAA,GAAA,EAAM,YAAY,CAAA,CAAE,CAAA;AAAA,IAClF;AAAA,EACJ;AAGA,EAAA,IACA;AACI,IAAA,UAAA,CAAW,OAAA,EAAS,UAAU,IAAI,CAAA;AAAA,EACtC,CAAA,CAAA,MAEA;AACI,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,eAAA,EAAkB,OAAO,CAAA,4CAAA,CAA8C,CAAA;AAAA,EAC3F;AAGA,EAAA,MAAM,QAAA,GAAWH,IAAAA,CAAK,OAAA,EAAS,oBAAoB,CAAA;AACnD,EAAA,IACA;AACI,IAAA,aAAA,CAAc,QAAA,EAAU,QAAQ,OAAO,CAAA;AACvC,IAAAI,WAAW,QAAQ,CAAA;AAAA,EACvB,SACO,KAAA,EACP;AACI,IAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,OAAO,CAAA,GAAA,EAAM,YAAY,CAAA,CAAE,CAAA;AAAA,EACjF;AACJ;AAKA,SAAS,kBAAA,GACT;AACI,EAAA,IAAI,CAAC,sBAAqB,EAC1B;AACI,IAAA;AAAA,EACJ;AAEA,EAAA,MAAM,MAAA,GAAS,QAAQ,GAAA,CAAI,OAAA;AAG3B,EAAA,IAAI,CAAC,MAAA,EACL;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN;AAAA,KAEJ;AAAA,EACJ;AAGA,EAAA,yBAAA,CAA0B,MAAM,CAAA;AACpC;AAKA,SAAS,mBAAA,GACT;AACI,EAAA,MAAM,UAAA,GAAa,QAAQ,GAAA,CAAI,iBAAA;AAE/B,EAAA,IAAI,CAAC,UAAA,EACL;AACI,IAAA;AAAA,EACJ;AAGA,EAAA,IAAI,CAAC,UAAA,CAAW,UAAA,CAAW,0BAA0B,CAAA,EACrD;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,+BAA+B,UAAU,CAAA,gEAAA;AAAA,KAE7C;AAAA,EACJ;AACJ;AAKA,SAAS,mBAAA,GACT;AACI,EAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,CAAI,SAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,CAAI,SAAA;AAC7B,EAAA,MAAM,SAAA,GAAY,QAAQ,GAAA,CAAI,UAAA;AAC9B,EAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,CAAI,QAAA;AAG5B,EAAA,MAAM,iBAAA,GAAoB,QAAA,IAAY,QAAA,IAAY,SAAA,IAAa,OAAA;AAC/D,EAAA,IAAI,CAAC,iBAAA,EACL;AACI,IAAA;AAAA,EACJ;AAGA,EAAA,MAAM,gBAA0B,EAAC;AACjC,EAAA,IAAI,CAAC,QAAA,EAAU,aAAA,CAAc,IAAA,CAAK,WAAW,CAAA;AAC7C,EAAA,IAAI,CAAC,QAAA,EAAU,aAAA,CAAc,IAAA,CAAK,WAAW,CAAA;AAC7C,EAAA,IAAI,CAAC,SAAA,EAAW,aAAA,CAAc,IAAA,CAAK,YAAY,CAAA;AAC/C,EAAA,IAAI,CAAC,OAAA,EAAS,aAAA,CAAc,IAAA,CAAK,UAAU,CAAA;AAE3C,EAAA,IAAI,aAAA,CAAc,SAAS,CAAA,EAC3B;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,mDAAA,EAAsD,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA,mEAAA;AAAA,KAElF;AAAA,EACJ;AAGA,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,QAAA,EAAW,EAAE,CAAA;AACnC,EAAA,IAAI,MAAM,IAAI,CAAA,IAAK,IAAA,GAAO,CAAA,IAAK,OAAO,KAAA,EACtC;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,uBAAuB,QAAQ,CAAA,wCAAA;AAAA,KACnC;AAAA,EACJ;AAGA,EAAA,MAAM,UAAA,GAAa,4BAAA;AACnB,EAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,SAAU,CAAA,EAC/B;AACI,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,4BAAA,EAA+B,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,EAC/D;AAGA,EAAA,MAAM,UAAA,GAAa,QAAS,KAAA,CAAM,GAAG,EAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,EAAM,CAAA;AACxD,EAAA,KAAA,MAAW,SAAS,UAAA,EACpB;AACI,IAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,KAAK,CAAA,EAC1B;AACI,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,IACnE;AAAA,EACJ;AACJ;AAKA,SAAS,mBAAA,GACT;AACI,EAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,CAAI,QAAA;AAE5B,EAAA,IAAI,CAAC,OAAA,EACL;AACI,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,MACX;AAAA,KACJ;AAAA,EACJ;AAGJ;AAMO,SAAS,cAAA,GAChB;AACI,EAAA,IACA;AACI,IAAA,mBAAA,EAAoB;AACpB,IAAA,kBAAA,EAAmB;AACnB,IAAA,mBAAA,EAAoB;AACpB,IAAA,mBAAA,EAAoB;AAAA,EACxB,SACO,KAAA,EACP;AACI,IAAA,IAAI,iBAAiB,KAAA,EACrB;AACI,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0CAAA,EAA6C,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,IAChF;AACA,IAAA,MAAM,KAAA;AAAA,EACV;AACJ;;;AC9RA,SAAS,oBAAA,GACT;AACI,EAAA,MAAM,aAA0B,EAAC;AAGjC,EAAA,MAAM,gBAAgB,gBAAA,EAAiB;AACvC,EAAA,UAAA,CAAW,IAAA,CAAK,IAAI,gBAAA,CAAiB,aAAa,CAAC,CAAA;AAGnD,EAAA,MAAM,aAAa,aAAA,EAAc;AACjC,EAAA,IAAI,WAAW,OAAA,EACf;AACI,IAAA,UAAA,CAAW,IAAA,CAAK,IAAI,aAAA,CAAc,UAAU,CAAC,CAAA;AAAA,EACjD;AAEA,EAAA,OAAO,UAAA;AACX;AAKO,IAAM,aAAA,GAAN,MAAM,cAAA,CACb;AAAA,EACY,MAAA;AAAA,EAER,YAAY,MAAA,EACZ;AACI,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,MAAA,CAAO;AAAA,MACrB,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,YAAY,oBAAA;AAAqB,KACpC,CAAA;AAAA,EACL;AAAA,EAEA,MAAM,MAAA,EACN;AACI,IAAA,MAAM,OAAA,GAAU,IAAI,cAAA,CAAc,EAAE,OAAO,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,CAAA;AACtE,IAAA,OAAA,CAAQ,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA;AACzC,IAAA,OAAO,OAAA;AAAA,EACX;AAAA,EAEA,KAAA,CAAM,SAAiB,OAAA,EACvB;AACI,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,OAAO,CAAA;AAAA,EACtC;AAAA,EAEA,IAAA,CAAK,SAAiB,OAAA,EACtB;AACI,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,OAAO,CAAA;AAAA,EACrC;AAAA,EAEA,IAAA,CAAK,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACxE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,cAAA,EAAgB,OAAO,CAAA;AAAA,IACrD,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,cAAc,CAAA;AAAA,IAC5C;AAAA,EACJ;AAAA,EAEA,KAAA,CAAM,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACzE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,cAAA,EAAgB,OAAO,CAAA;AAAA,IACtD,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,cAAc,CAAA;AAAA,IAC7C;AAAA,EACJ;AAAA,EAEA,KAAA,CAAM,OAAA,EAAiB,cAAA,EAAkD,OAAA,EACzE;AACI,IAAA,IAAI,0BAA0B,KAAA,EAC9B;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,cAAA,EAAgB,OAAO,CAAA;AAAA,IACtD,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,cAAc,CAAA;AAAA,IAC7C;AAAA,EACJ;AAAA,EAEA,MAAM,KAAA,GACN;AACI,IAAA,MAAM,IAAA,CAAK,OAAO,KAAA,EAAM;AAAA,EAC5B;AACJ,CAAA;;;ACvGA,SAAS,cAAc,IAAA,EACvB;AACI,EAAA,MAAM,QAAQ,kBAAA,EAAmB;AAEjC,EAAA,QAAQ,IAAA;AACR,IACI,KAAK,MAAA;AACD,MAAA,OAAO,IAAI,WAAA,CAAY,EAAE,KAAA,EAAO,CAAA;AAAA,IAEpC,KAAK,QAAA;AACD,MAAA,OAAO,IAAI,aAAA,CAAc,EAAE,KAAA,EAAO,CAAA;AAAA,IAEtC;AACI,MAAA,OAAO,IAAI,WAAA,CAAY,EAAE,KAAA,EAAO,CAAA;AAAA;AAE5C;AAKA,SAAS,cAAA,GACT;AACI,EAAA,MAAM,UAAA,GAAa,QAAQ,GAAA,CAAI,cAAA;AAE/B,EAAA,IAAI,UAAA,KAAe,QAAA,IAAY,UAAA,KAAe,MAAA,EAC9C;AACI,IAAA,OAAO,UAAA;AAAA,EACX;AAGA,EAAA,OAAO,MAAA;AACX;AAKA,SAAS,gBAAA,GACT;AAEI,EAAA,cAAA,EAAe;AAGf,EAAA,OAAO,aAAA,CAAc,gBAAgB,CAAA;AACzC;AAKO,IAAM,SAAwB,gBAAA,EAAiB;;;ACtDtD,IAAM,aAAA,GAAgB,MAAA,CAAO,KAAA,CAAM,SAAS,CAAA;AAsB5C,eAAe,aAAa,OAAA,EAAgE;AACxF,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,EAAI;AACxB,EAAA,MAAM,YAAY,OAAA,CAAQ,SAAA,IAAaJ,KAAK,GAAA,EAAK,KAAA,EAAO,UAAU,QAAQ,CAAA;AAC1E,EAAA,MAAM,aAAa,OAAA,CAAQ,UAAA,IAAcA,KAAK,GAAA,EAAK,KAAA,EAAO,OAAO,QAAQ,CAAA;AAEzE,EAAA,IAAI;AAEA,IAAA,MAAM,SAAA,GAAY,MAAM,aAAA,CAAc,SAAS,CAAA;AAE/C,IAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EACzB;AACI,MAAA,IAAI,QAAQ,KAAA,EACZ;AACI,QAAA,aAAA,CAAc,KAAK,oBAAoB,CAAA;AAAA,MAC3C;AACA,MAAA,OAAO,IAAA;AAAA,IACX;AAGA,IAAA,MAAM,KAAA,GAAyB,MAAM,cAAA,CAAe,SAAA,EAAW;AAAA,MAE3D,UAAA;AAAA,MAEA,YAAA,EAAc,IAAA;AAAA,MACd,YAAA,EAAc;AAAA,KACjB,CAAA;AAGD,IAAA,IAAI,QAAQ,KAAA,EACZ;AACI,MAAA,aAAA,CAAc,KAAK,kBAAA,EAAoB;AAAA,QACnC,WAAW,KAAA,CAAM,gBAAA;AAAA,QACjB,WAAW,KAAA,CAAM,kBAAA;AAAA,QACjB,UAAU,KAAA,CAAM;AAAA,OACnB,CAAA;AAAA,IACL;AAEA,IAAA,OAAO,KAAA;AAAA,EACX,SACO,KAAA,EACP;AACI,IAAA,aAAA,CAAc,KAAA;AAAA,MACV,mBAAA;AAAA,MACA,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC;AAAA,KAC5D;AACA,IAAA,OAAO,IAAA;AAAA,EACX;AACJ;AAKA,eAAsB,gBAAA,CAAiB,OAAA,GAAgC,EAAC,EAAkB;AACtF,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,EAAI;AACxB,EAAA,MAAM,YAAY,OAAA,CAAQ,SAAA,IAAaA,KAAK,GAAA,EAAK,KAAA,EAAO,UAAU,QAAQ,CAAA;AAC1E,EAAA,MAAM,aAAa,OAAA,CAAQ,UAAA,IAAcA,KAAK,GAAA,EAAK,KAAA,EAAO,OAAO,QAAQ,CAAA;AACzE,EAAA,MAAM,SAAA,GAAY,QAAQ,KAAA,KAAU,KAAA;AAEpC,EAAA,IAAI,QAAQ,KAAA,EACZ;AACI,IAAA,aAAA,CAAc,KAAK,0BAAA,EAA4B,EAAE,WAAW,UAAA,EAAY,KAAA,EAAO,WAAW,CAAA;AAAA,EAC9F;AAGA,EAAA,MAAM,aAAa,OAAO,CAAA;AAG1B,EAAA,IAAI,SAAA,EAAW;AACX,IAAA,IAAI,YAAA,GAAe,KAAA;AACnB,IAAA,IAAI,mBAAA,GAAsB,KAAA;AAE1B,IAAA,MAAM,OAAA,GAAUK,MAAc,SAAA,EAAW;AAAA,MACrC,OAAA,EAAS,eAAA;AAAA;AAAA,MACT,UAAA,EAAY,IAAA;AAAA,MACZ,aAAA,EAAe,IAAA;AAAA,MACf,gBAAA,EAAkB;AAAA,QACd,kBAAA,EAAoB,GAAA;AAAA,QACpB,YAAA,EAAc;AAAA;AAClB,KACH,CAAA;AAED,IAAA,MAAM,aAAa,YAAY;AAC3B,MAAA,IAAI,YAAA,EAAc;AACd,QAAA,mBAAA,GAAsB,IAAA;AACtB,QAAA;AAAA,MACJ;AAEA,MAAA,YAAA,GAAe,IAAA;AACf,MAAA,mBAAA,GAAsB,KAAA;AAEtB,MAAA,IAAI,QAAQ,KAAA,EAAO;AACf,QAAA,aAAA,CAAc,KAAK,oCAAoC,CAAA;AAAA,MAC3D;AAEA,MAAA,MAAM,aAAa,OAAO,CAAA;AAE1B,MAAA,YAAA,GAAe,KAAA;AAEf,MAAA,IAAI,mBAAA,EAAqB;AACrB,QAAA,MAAM,UAAA,EAAW;AAAA,MACrB;AAAA,IACJ,CAAA;AAEA,IAAA,OAAA,CACK,EAAA,CAAG,KAAA,EAAO,UAAU,CAAA,CACpB,EAAA,CAAG,UAAU,UAAU,CAAA,CACvB,EAAA,CAAG,QAAA,EAAU,UAAU,CAAA;AAG5B,IAAA,OAAA,CAAQ,EAAA,CAAG,UAAU,MAAM;AACvB,MAAA,OAAA,CAAQ,KAAA,EAAM;AACd,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAClB,CAAC,CAAA;AAGD,IAAA,MAAM,IAAI,QAAQ,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EAC9B;AACJ;AAGA,IAAI,YAAY,GAAA,KAAQ,CAAA,OAAA,EAAU,QAAQ,IAAA,CAAK,CAAC,CAAC,CAAA,CAAA,EAAI;AACjD,EAAA,gBAAA,CAAiB,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA;AACpC;ACjJA,IAAM,kBAAA,GAAqB,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA;AAc/C,IAAM,sBAAN,MACP;AAAA,EACqB,UAAA;AAAA,EACA,GAAA;AAAA,EACA,KAAA;AAAA,EACT,YAAA,GAAe,KAAA;AAAA,EACf,oBAAA,uBAA2B,GAAA,EAAY;AAAA,EAE/C,YAAY,OAAA,EACZ;AACI,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,UAAA;AAC1B,IAAA,IAAA,CAAK,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AACtC,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,IAAS,KAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAA,GACN;AACI,IAAA,IAAI,KAAK,KAAA,EACT;AACI,MAAA,kBAAA,CAAmB,KAAK,wBAAA,EAA0B;AAAA,QAC9C,KAAA,EAAO,KAAK,UAAA,CAAW,MAAA;AAAA,QACvB,OAAO,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,IAAI;AAAA,OACzC,CAAA;AAAA,IACL;AAEA,IAAA,KAAA,MAAW,SAAA,IAAa,KAAK,UAAA,EAC7B;AACI,MAAA,IACA;AACI,QAAA,MAAM,UAAA,GAA+B;AAAA,UACjC,KAAK,IAAA,CAAK,GAAA;AAAA,UACV,OAAO,IAAA,CAAK;AAAA,SAChB;AAEA,QAAA,MAAM,SAAA,CAAU,SAAS,UAAU,CAAA;AAEnC,QAAA,IAAI,KAAK,KAAA,EACT;AACI,UAAA,kBAAA,CAAmB,IAAA,CAAK,CAAA,CAAA,EAAI,SAAA,CAAU,IAAI,CAAA,wBAAA,CAA0B,CAAA;AAAA,QACxE;AAAA,MACJ,SACO,KAAA,EACP;AACI,QAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACpE,QAAA,kBAAA,CAAmB,KAAA,CAAM,CAAA,CAAA,EAAI,SAAA,CAAU,IAAI,uBAAuB,GAAG,CAAA;AAAA,MACzE;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,GACN;AAEI,IAAA,MAAM,KAAK,WAAA,EAAY;AAGvB,IAAA,MAAM,cAAc,IAAA,CAAK,UAAA,CAAW,OAAA,CAAQ,CAAA,CAAA,KAAK,EAAE,aAAa,CAAA;AAEhE,IAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAC3B;AACI,MAAA,kBAAA,CAAmB,KAAK,+CAA+C,CAAA;AACvE,MAAA;AAAA,IACJ;AAIA,IAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AACpC,IAAA,KAAA,MAAW,WAAW,WAAA,EACtB;AAEI,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA,CAAE,CAAC,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,IAAK,GAAA;AAC7D,MAAA,WAAA,CAAY,GAAA,CAAIL,IAAAA,CAAK,IAAA,CAAK,GAAA,EAAK,OAAO,CAAC,CAAA;AAAA,IAC3C;AAEA,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AAExC,IAAA,IAAI,KAAK,KAAA,EACT;AACI,MAAA,kBAAA,CAAmB,KAAK,qBAAA,EAAuB;AAAA,QAC3C,QAAA,EAAU,WAAA;AAAA,QACV,SAAA;AAAA,QACA,KAAK,IAAA,CAAK;AAAA,OACb,CAAA;AAAA,IACL;AAEA,IAAA,MAAM,OAAA,GAAUK,MAAc,SAAA,EAAW;AAAA,MACrC,OAAA,EAAS,eAAA;AAAA;AAAA,MACT,UAAA,EAAY,IAAA;AAAA,MACZ,aAAA,EAAe,IAAA;AAAA,MACf,gBAAA,EAAkB;AAAA,QACd,kBAAA,EAAoB,GAAA;AAAA,QACpB,YAAA,EAAc;AAAA;AAClB,KACH,CAAA;AAED,IAAA,MAAM,YAAA,GAAe,OAAO,YAAA,EAAsB,KAAA,KAClD;AAEI,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,IAAA,CAAK,GAAA,EAAK,YAAY,CAAA;AAEhD,MAAA,IAAI,KAAK,YAAA,EACT;AACI,QAAA,IAAA,CAAK,oBAAA,CAAqB,IAAI,YAAY,CAAA;AAC1C,QAAA;AAAA,MACJ;AAEA,MAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AACpB,MAAA,IAAA,CAAK,qBAAqB,KAAA,EAAM;AAEhC,MAAA,IAAI,KAAK,KAAA,EACT;AACI,QAAA,kBAAA,CAAmB,KAAK,CAAA,KAAA,EAAQ,KAAK,IAAI,EAAE,IAAA,EAAM,UAAU,CAAA;AAAA,MAC/D;AAGA,MAAA,KAAA,MAAW,SAAA,IAAa,KAAK,UAAA,EAC7B;AACI,QAAA,MAAM,OAAA,GAAU,UAAU,aAAA,CAAc,IAAA;AAAA,UAAK,CAAA,OAAA,KACzC,EAAA,CAAG,OAAA,CAAQ,QAAA,EAAU,OAAO;AAAA,SAChC;AAEA,QAAA,IAAI,OAAA,EACJ;AACI,UAAA,IACA;AACI,YAAA,IAAI,UAAU,YAAA,EACd;AAEI,cAAA,MAAM,SAAA,CAAU,YAAA,CAAa,QAAA,EAAU,KAAK,CAAA;AAAA,YAChD,CAAA,MAEA;AAEI,cAAA,MAAM,UAAA,GAA+B;AAAA,gBACjC,KAAK,IAAA,CAAK,GAAA;AAAA,gBACV,OAAO,IAAA,CAAK;AAAA,eAChB;AACA,cAAA,MAAM,SAAA,CAAU,SAAS,UAAU,CAAA;AAAA,YACvC;AAEA,YAAA,IAAI,KAAK,KAAA,EACT;AACI,cAAA,kBAAA,CAAmB,IAAA,CAAK,CAAA,CAAA,EAAI,SAAA,CAAU,IAAI,CAAA,aAAA,CAAe,CAAA;AAAA,YAC7D;AAAA,UACJ,SACO,KAAA,EACP;AACI,YAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACpE,YAAA,kBAAA,CAAmB,KAAA,CAAM,CAAA,CAAA,EAAI,SAAA,CAAU,IAAI,yBAAyB,GAAG,CAAA;AAAA,UAC3E;AAAA,QACJ;AAAA,MACJ;AAEA,MAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AAGpB,MAAA,IAAI,IAAA,CAAK,oBAAA,CAAqB,IAAA,GAAO,CAAA,EACrC;AACI,QAAA,MAAM,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,oBAAoB,EAAE,CAAC,CAAA;AACpD,QAAA,MAAM,YAAA,CAAa,MAAM,QAAQ,CAAA;AAAA,MACrC;AAAA,IACJ,CAAA;AAEA,IAAA,OAAA,CACK,EAAA,CAAG,KAAA,EAAO,CAAC,IAAA,KAAS,YAAA,CAAa,MAAM,KAAK,CAAC,CAAA,CAC7C,EAAA,CAAG,QAAA,EAAU,CAAC,SAAS,YAAA,CAAa,IAAA,EAAM,QAAQ,CAAC,CAAA,CACnD,EAAA,CAAG,QAAA,EAAU,CAAC,IAAA,KAAS,YAAA,CAAa,IAAA,EAAM,QAAQ,CAAC,CAAA;AAGxD,IAAA,OAAA,CAAQ,EAAA,CAAG,UAAU,MACrB;AACI,MAAA,IAAI,KAAK,KAAA,EACT;AACI,QAAA,kBAAA,CAAmB,KAAK,0BAA0B,CAAA;AAAA,MACtD;AACA,MAAA,OAAA,CAAQ,KAAA,EAAM;AACd,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAClB,CAAC,CAAA;AAGD,IAAA,MAAM,IAAI,QAAQ,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EAC9B;AACJ;ACzMA,IAAM,cAAA,GAAiB,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA;AAc3C,SAAS,uBAAA,CAAwB,MAAA,GAAkC,EAAC,EAC3E;AACI,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,UAAA;AAAA,IACN,aAAA,EAAe,CAAC,MAAA,CAAO,SAAA,IAAa,2BAA2B,CAAA;AAAA,IAE/D,MAAM,SAAS,OAAA,EACf;AACI,MAAA,MAAM,MAAM,OAAA,CAAQ,GAAA;AACpB,MAAA,MAAM,YAAY,MAAA,CAAO,SAAA,IAAaL,KAAK,GAAA,EAAK,KAAA,EAAO,UAAU,QAAQ,CAAA;AACzE,MAAA,MAAM,aAAa,MAAA,CAAO,UAAA,IAAcA,KAAK,GAAA,EAAK,KAAA,EAAO,OAAO,QAAQ,CAAA;AAExE,MAAA,IACA;AAEI,QAAA,MAAM,SAAA,GAAY,MAAM,aAAA,CAAc,SAAS,CAAA;AAE/C,QAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EACzB;AACI,UAAA,IAAI,QAAQ,KAAA,EACZ;AACI,YAAA,cAAA,CAAe,KAAK,oBAAoB,CAAA;AAAA,UAC5C;AACA,UAAA;AAAA,QACJ;AAGA,QAAA,MAAM,KAAA,GAAQ,MAAM,cAAA,CAAe,SAAA,EAAW;AAAA,UAE1C,UAAA;AAAA,UAEA,YAAA,EAAc,IAAA;AAAA,UACd,YAAA,EAAc;AAAA,SACjB,CAAA;AAED,QAAA,IAAI,QAAQ,KAAA,EACZ;AACI,UAAA,cAAA,CAAe,KAAK,kBAAA,EAAoB;AAAA,YACpC,WAAW,KAAA,CAAM,gBAAA;AAAA,YACjB,WAAW,KAAA,CAAM,kBAAA;AAAA,YACjB,UAAU,KAAA,CAAM;AAAA,WACnB,CAAA;AAAA,QACL;AAAA,MACJ,SACO,KAAA,EACP;AACI,QAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACpE,QAAA,cAAA,CAAe,KAAA,CAAM,qBAAqB,GAAG,CAAA;AAC7C,QAAA,MAAM,GAAA;AAAA,MACV;AAAA,IACJ;AAAA,GACJ;AACJ;ACjEA,IAAM,YAAA,GAAe,MAAA,CAAO,KAAA,CAAM,QAAQ,CAAA;AAanC,SAAS,kBAAkB,GAAA,EAClC;AAEI,EAAA,MAAM,MAAA,GAASA,IAAAA,CAAK,GAAA,EAAK,cAAc,CAAA;AACvC,EAAA,IAAIE,UAAAA,CAAW,MAAM,CAAA,EACrB;AACI,IAAA,IACA;AACI,MAAA,MAAM,OAAA,GAAUI,YAAAA,CAAa,MAAA,EAAQ,OAAO,CAAA;AAC5C,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAEjC,MAAA,IAAI,OAAO,OAAA,EACX;AACI,QAAA,YAAA,CAAa,KAAK,iCAAiC,CAAA;AACnD,QAAA,OAAO,MAAA,CAAO,OAAA;AAAA,MAClB;AAAA,IACJ,SACO,KAAA,EACP;AACI,MAAA,YAAA,CAAa,IAAA,CAAK,gCAAgC,KAAc,CAAA;AAAA,IACpE;AAAA,EACJ;AAGA,EAAA,MAAM,OAAA,GAAUN,IAAAA,CAAK,GAAA,EAAK,cAAc,CAAA;AACxC,EAAA,IAAIE,UAAAA,CAAW,OAAO,CAAA,EACtB;AACI,IAAA,IACA;AACI,MAAA,MAAM,OAAA,GAAUI,YAAAA,CAAa,OAAA,EAAS,OAAO,CAAA;AAC7C,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAE9B,MAAA,IAAI,GAAA,CAAI,MAAM,OAAA,EACd;AACI,QAAA,YAAA,CAAa,KAAK,iCAAiC,CAAA;AACnD,QAAA,OAAO,IAAI,IAAA,CAAK,OAAA;AAAA,MACpB;AAAA,IACJ,SACO,KAAA,EACP;AACI,MAAA,YAAA,CAAa,IAAA,CAAK,gCAAgC,KAAc,CAAA;AAAA,IACpE;AAAA,EACJ;AAGA,EAAA,YAAA,CAAa,KAAK,sBAAsB,CAAA;AACxC,EAAA,OAAO;AAAA,IACH,UAAA,EAAY;AAAA,MACR,EAAE,IAAA,EAAM,UAAA,EAAY,OAAA,EAAS,IAAA;AAAK;AACtC,GACJ;AACJ;AAKA,eAAsB,0BAAA,CAA2B,QAAuB,GAAA,EACxE;AACI,EAAA,MAAM,aAA0B,EAAC;AAEjC,EAAA,IAAI,CAAC,MAAA,CAAO,UAAA,IAAc,MAAA,CAAO,UAAA,CAAW,WAAW,CAAA,EACvD;AACI,IAAA,OAAO,UAAA;AAAA,EACX;AAEA,EAAA,KAAA,MAAW,eAAA,IAAmB,OAAO,UAAA,EACrC;AACI,IAAA,IACA;AAEI,MAAA,IAAI,UAAU,eAAA,EACd;AACI,QAAA,MAAM,aAAA,GAAgB,eAAA,CAAgB,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,GACnDN,IAAAA,CAAK,GAAA,EAAK,eAAA,CAAgB,IAAI,CAAA,GAC9B,eAAA,CAAgB,IAAA;AAEtB,QAAA,YAAA,CAAa,IAAA,CAAK,CAAA,0BAAA,EAA6B,aAAa,CAAA,CAAE,CAAA;AAE9D,QAAA,IAAI,MAAA;AAGJ,QAAA,IAAI,aAAA,CAAc,QAAA,CAAS,KAAK,CAAA,EAChC;AACI,UAAA,MAAM,IAAA,GAAO,WAAW,GAAA,EAAK;AAAA,YACzB,cAAA,EAAgB;AAAA,WACnB,CAAA;AACD,UAAA,MAAA,GAAS,KAAK,aAAa,CAAA;AAAA,QAC/B,CAAA,MAEA;AACI,UAAA,MAAA,GAAS,MAAM,OAAO,aAAA,CAAA;AAAA,QAC1B;AAEA,QAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,OAAA,IAAW,MAAA,CAAO,eAAA,IAAmB,MAAA;AAEpE,QAAA,IAAI,OAAO,oBAAoB,UAAA,EAC/B;AACI,UAAA,MAAM,YAAY,eAAA,EAAgB;AAClC,UAAA,UAAA,CAAW,KAAK,SAAS,CAAA;AACzB,UAAA,YAAA,CAAa,IAAA,CAAK,CAAA,yBAAA,EAA4B,SAAA,CAAU,IAAI,CAAA,CAAE,CAAA;AAAA,QAClE,CAAA,MAEA;AACI,UAAA,YAAA,CAAa,IAAA,CAAK,CAAA,qBAAA,EAAwB,aAAa,CAAA,mBAAA,CAAqB,CAAA;AAAA,QAChF;AAAA,MACJ,CAAA,MAAA,IAES,MAAA,IAAU,eAAA,IAAmB,eAAA,CAAgB,SAAS,UAAA,EAC/D;AACI,QAAA,IAAI,eAAA,CAAgB,YAAY,KAAA,EAChC;AACI,UAAA,MAAM,cAAA,GAA0C;AAAA,YAC5C,WAAW,eAAA,CAAgB,SAAA;AAAA,YAC3B,YAAY,eAAA,CAAgB,UAEhC,CAAA;AAEA,UAAA,UAAA,CAAW,IAAA,CAAK,uBAAA,CAAwB,cAAc,CAAC,CAAA;AACvD,UAAA,YAAA,CAAa,KAAK,4BAA4B,CAAA;AAAA,QAClD;AAAA,MACJ;AAAA,IACJ,SACO,KAAA,EACP;AACI,MAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACpE,MAAA,YAAA,CAAa,KAAA,CAAM,4BAA4B,GAAG,CAAA;AAAA,IACtD;AAAA,EACJ;AAEA,EAAA,OAAO,UAAA;AACX","file":"index.js","sourcesContent":["/**\n * Contract Scanner\n *\n * Scans server/contracts directory and extracts exported contracts\n */\n\nimport { readdir, stat } from 'fs/promises';\nimport { join } from 'path';\nimport * as ts from 'typescript';\nimport { readFileSync } from 'fs';\nimport type { RouteContractMapping, HttpMethod } from './types.js';\n\n/**\n * Scan routes directory for contract.ts files and extract contract exports\n *\n * @param routesDir - Path to server/routes directory\n * @returns Array of contract-to-route mappings\n */\nexport async function scanContracts(routesDir: string): Promise<RouteContractMapping[]>\n{\n const contractFiles = await scanContractFiles(routesDir);\n const mappings: RouteContractMapping[] = [];\n\n for (let i = 0; i < contractFiles.length; i++)\n {\n const filePath = contractFiles[i];\n const exports = extractContractExports(filePath);\n\n // Calculate base path from file location: routes/posts/contract.ts → /posts\n const basePath = getBasePathFromFile(filePath, routesDir);\n\n for (let j = 0; j < exports.length; j++)\n {\n const contractExport = exports[j];\n\n // Combine base path with contract path: /posts + / → /posts\n const fullPath = combinePaths(basePath, contractExport.path);\n\n mappings.push({\n method: contractExport.method,\n path: fullPath,\n contractName: contractExport.name,\n contractImportPath: getImportPathFromRoutes(filePath, routesDir),\n routeFile: '', // Not needed anymore\n contractFile: filePath\n });\n }\n }\n\n return mappings;\n}\n\n/**\n * Recursively scan for contract.ts files in routes directory\n */\nasync function scanContractFiles(dir: string, files: string[] = []): Promise<string[]>\n{\n try\n {\n const entries = await readdir(dir);\n\n for (let i = 0; i < entries.length; i++)\n {\n const entry = entries[i];\n const fullPath = join(dir, entry);\n const fileStat = await stat(fullPath);\n\n if (fileStat.isDirectory())\n {\n await scanContractFiles(fullPath, files);\n }\n else if (entry === 'contract.ts')\n {\n files.push(fullPath);\n }\n }\n }\n catch (error)\n {\n // Directory doesn't exist or not readable\n }\n\n return files;\n}\n\n/**\n * Contract export information\n */\ninterface ContractExport\n{\n name: string;\n method: HttpMethod;\n path: string;\n}\n\n/**\n * Extract contract exports from a TypeScript file\n *\n * Looks for exports with structure:\n * export const xxxContract = {\n * method: 'GET',\n * path: '/users',\n * ...\n * }\n */\nfunction extractContractExports(filePath: string): ContractExport[]\n{\n const sourceCode = readFileSync(filePath, 'utf-8');\n const sourceFile = ts.createSourceFile(\n filePath,\n sourceCode,\n ts.ScriptTarget.Latest,\n true\n );\n\n const exports: ContractExport[] = [];\n\n function visit(node: ts.Node): void\n {\n // Look for: export const xxxContract = { ... }\n if (ts.isVariableStatement(node))\n {\n // Check if it has export modifier\n const hasExport = node.modifiers?.some(\n m => m.kind === ts.SyntaxKind.ExportKeyword\n );\n\n if (hasExport && node.declarationList.declarations.length > 0)\n {\n const declaration = node.declarationList.declarations[0];\n\n if (\n ts.isVariableDeclaration(declaration) &&\n ts.isIdentifier(declaration.name) &&\n declaration.initializer &&\n ts.isObjectLiteralExpression(declaration.initializer)\n )\n {\n const name = declaration.name.text;\n\n // Check if name looks like a contract\n if (isContractName(name))\n {\n const contractData = extractContractData(declaration.initializer);\n\n if (contractData.method && contractData.path)\n {\n exports.push({\n name,\n method: contractData.method,\n path: contractData.path\n });\n }\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return exports;\n}\n\n/**\n * Extract method and path from contract object literal\n */\nfunction extractContractData(objectLiteral: ts.ObjectLiteralExpression): {\n method?: HttpMethod;\n path?: string;\n}\n{\n const result: { method?: HttpMethod; path?: string } = {};\n\n for (let i = 0; i < objectLiteral.properties.length; i++)\n {\n const prop = objectLiteral.properties[i];\n\n if (\n ts.isPropertyAssignment(prop) &&\n ts.isIdentifier(prop.name)\n )\n {\n const propName = prop.name.text;\n\n if (propName === 'method')\n {\n // Handle both 'GET' and 'GET' as const\n let value: string | undefined;\n if (ts.isStringLiteral(prop.initializer))\n {\n value = prop.initializer.text;\n }\n else if (ts.isAsExpression(prop.initializer) && ts.isStringLiteral(prop.initializer.expression))\n {\n value = prop.initializer.expression.text;\n }\n if (value) result.method = value as HttpMethod;\n }\n else if (propName === 'path')\n {\n // Handle both '/path' and '/path' as const\n let value: string | undefined;\n if (ts.isStringLiteral(prop.initializer))\n {\n value = prop.initializer.text;\n }\n else if (ts.isAsExpression(prop.initializer) && ts.isStringLiteral(prop.initializer.expression))\n {\n value = prop.initializer.expression.text;\n }\n if (value) result.path = value;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Check if a name looks like a contract\n */\nfunction isContractName(name: string): boolean\n{\n return (\n name.indexOf('Contract') !== -1 ||\n name.indexOf('contract') !== -1 ||\n name.endsWith('Schema') ||\n name.endsWith('schema')\n );\n}\n\n/**\n * Get base URL path from contract file location\n *\n * @example\n * routes/posts/contract.ts → /posts\n * routes/users/[id]/contract.ts → /users/:id\n * routes/index/contract.ts → /\n */\nfunction getBasePathFromFile(filePath: string, routesDir: string): string\n{\n // Get relative path from routes dir\n let relativePath = filePath.replace(routesDir, '');\n\n // Remove leading slash\n if (relativePath.startsWith('/'))\n {\n relativePath = relativePath.slice(1);\n }\n\n // Remove /contract.ts\n relativePath = relativePath.replace('/contract.ts', '');\n\n // Handle index → /\n if (relativePath === 'index' || relativePath === '')\n {\n return '/';\n }\n\n // Split into segments\n const segments = relativePath.split('/');\n const transformed: string[] = [];\n\n for (let i = 0; i < segments.length; i++)\n {\n const seg = segments[i];\n\n // Skip 'index' segments (routes/index/contract.ts → /, routes/posts/index/contract.ts → /posts)\n if (seg === 'index')\n {\n continue;\n }\n\n // Dynamic parameter: [id] → :id\n if (seg.startsWith('[') && seg.endsWith(']'))\n {\n transformed.push(':' + seg.slice(1, -1));\n }\n // Static segment\n else\n {\n transformed.push(seg);\n }\n }\n\n // If no segments remain, return root\n if (transformed.length === 0)\n {\n return '/';\n }\n\n return '/' + transformed.join('/');\n}\n\n/**\n * Combine base path with contract path\n *\n * @example\n * combinePaths('/posts', '/') → /posts\n * combinePaths('/posts', '/:id') → /posts/:id\n * combinePaths('/', '/health') → /health\n */\nfunction combinePaths(basePath: string, contractPath: string): string\n{\n // Normalize paths\n basePath = basePath || '/';\n contractPath = contractPath || '/';\n\n // Remove trailing slash from base\n if (basePath.endsWith('/') && basePath !== '/')\n {\n basePath = basePath.slice(0, -1);\n }\n\n // If contract path is absolute, use it as is\n if (contractPath.startsWith('/') && contractPath !== '/')\n {\n // If base is /, just use contract path\n if (basePath === '/')\n {\n return contractPath;\n }\n // Otherwise combine: /posts + /sub → /posts/sub\n return basePath + contractPath;\n }\n\n // Contract path is / or relative\n if (contractPath === '/')\n {\n return basePath;\n }\n\n // Combine: /posts + id → /posts/id\n return basePath + '/' + contractPath;\n}\n\n/**\n * Get import path for contract file\n *\n * @example\n * routes/posts/contract.ts → @/server/routes/posts/contract\n * routes/users/[id]/contract.ts → @/server/routes/users/[id]/contract\n */\nfunction getImportPathFromRoutes(filePath: string, routesDir: string): string\n{\n // Get relative path from routes dir\n let relativePath = filePath.replace(routesDir, '');\n\n // Remove leading slash\n if (relativePath.startsWith('/'))\n {\n relativePath = relativePath.slice(1);\n }\n\n // Remove .ts extension\n if (relativePath.endsWith('.ts'))\n {\n relativePath = relativePath.slice(0, -3);\n }\n\n // Return as module path\n return '@/server/routes/' + relativePath;\n}","/**\n * Route Scanner Utilities\n *\n * Helper functions for grouping and organizing route-contract mappings\n */\n\nimport type { RouteContractMapping } from './types.js';\n\n/**\n * Group mappings by resource\n */\nexport function groupByResource(mappings: RouteContractMapping[]): Record<string, RouteContractMapping[]>\n{\n const grouped: Record<string, RouteContractMapping[]> = {};\n\n for (let i = 0; i < mappings.length; i++)\n {\n const mapping = mappings[i];\n const resource = extractResourceName(mapping.path);\n\n if (!grouped[resource])\n {\n grouped[resource] = [];\n }\n\n grouped[resource].push(mapping);\n }\n\n return grouped;\n}\n\n/**\n * Extract resource name from path\n *\n * Examples:\n * - /users → users\n * - /users/:id → users\n * - /users/:id/posts → usersPosts\n * - /videos/upload-and-analyze → videosUploadAndAnalyze\n */\nfunction extractResourceName(path: string): string\n{\n // Remove leading slash\n const segments = path.slice(1).split('/').filter(s => s && s !== '*');\n\n // Remove dynamic segments\n const staticSegments: string[] = [];\n for (let i = 0; i < segments.length; i++)\n {\n const seg = segments[i];\n if (!seg.startsWith(':'))\n {\n staticSegments.push(seg);\n }\n }\n\n // Join with camelCase\n if (staticSegments.length === 0)\n {\n return 'root';\n }\n\n // Convert first segment (handle hyphens)\n const first = toCamelCase(staticSegments[0], false);\n\n if (staticSegments.length === 1)\n {\n return first;\n }\n\n // Convert to camelCase: users/posts → usersPosts, videos/upload-and-analyze → videosUploadAndAnalyze\n const result: string[] = [first];\n for (let i = 1; i < staticSegments.length; i++)\n {\n const seg = staticSegments[i];\n result.push(toCamelCase(seg, true));\n }\n\n return result.join('');\n}\n\n/**\n * Convert string to camelCase, handling hyphens\n *\n * @param str - Input string\n * @param capitalize - Capitalize first letter\n * @returns camelCase string\n *\n * Examples:\n * - toCamelCase('upload-and-analyze', true) → 'UploadAndAnalyze'\n * - toCamelCase('upload-and-analyze', false) → 'uploadAndAnalyze'\n * - toCamelCase('users', false) → 'users'\n */\nfunction toCamelCase(str: string, capitalize: boolean): string\n{\n // Split by hyphen or underscore\n const parts = str.split(/[-_]/);\n\n if (parts.length === 1)\n {\n // No hyphens/underscores\n return capitalize\n ? str.charAt(0).toUpperCase() + str.slice(1)\n : str;\n }\n\n // Convert to camelCase\n const result: string[] = [];\n for (let i = 0; i < parts.length; i++)\n {\n const part = parts[i];\n if (i === 0 && !capitalize)\n {\n result.push(part);\n }\n else\n {\n result.push(part.charAt(0).toUpperCase() + part.slice(1));\n }\n }\n\n return result.join('');\n}","/**\n * Client Code Generator\n *\n * Generates type-safe API client code from route-contract mappings\n */\n\nimport { mkdir, writeFile } from 'fs/promises';\nimport { dirname } from 'path';\nimport { groupByResource } from './route-scanner.js';\nimport type { ClientGenerationOptions, GenerationStats, RouteContractMapping } from './types.js';\n\n/**\n * Generate API client code\n */\nexport async function generateClient(\n mappings: RouteContractMapping[],\n options: ClientGenerationOptions\n): Promise<GenerationStats>\n{\n const startTime = Date.now();\n\n // Group by resource\n const grouped = groupByResource(mappings);\n const resourceNames = Object.keys(grouped);\n\n // Generate code\n const code = generateClientCode(mappings, grouped, options);\n\n // Ensure output directory exists\n await mkdir(dirname(options.outputPath), { recursive: true });\n\n // Write file\n await writeFile(options.outputPath, code, 'utf-8');\n\n // Calculate stats\n return {\n routesScanned: mappings.length,\n contractsFound: mappings.length,\n contractFiles: countUniqueContractFiles(mappings),\n resourcesGenerated: resourceNames.length,\n methodsGenerated: mappings.length,\n duration: Date.now() - startTime\n };\n}\n\n/**\n * Generate the actual client code\n */\nfunction generateClientCode(\n mappings: RouteContractMapping[],\n grouped: Record<string, RouteContractMapping[]>,\n options: ClientGenerationOptions\n): string\n{\n let code = '';\n\n // Header\n code += generateHeader();\n\n // Imports\n code += generateImports(mappings, options);\n\n // API object\n code += generateApiObject(grouped, options);\n\n // Footer\n code += generateFooter();\n\n return code;\n}\n\n/**\n * Generate file header\n */\nfunction generateHeader(): string\n{\n return `/**\n * Auto-generated API Client\n *\n * Generated by @spfn/core codegen\n * DO NOT EDIT MANUALLY\n *\n * @generated ${new Date().toISOString()}\n */\n\n`;\n}\n\n/**\n * Generate imports section\n */\nfunction generateImports(mappings: RouteContractMapping[], options: ClientGenerationOptions): string\n{\n let code = '';\n\n code += `import { client } from '@spfn/core/client';\\n`;\n\n if (options.includeTypes !== false)\n {\n code += `import type { InferContract } from '@spfn/core';\\n`;\n }\n\n code += `\\n`;\n\n // Contract imports (group by import path)\n const importGroups = groupContractsByImportPath(mappings);\n const importPaths = Object.keys(importGroups);\n\n for (let i = 0; i < importPaths.length; i++)\n {\n const importPath = importPaths[i];\n const contracts = importGroups[importPath];\n\n code += `import { ${contracts.join(', ')} } from '${importPath}';\\n`;\n }\n\n code += `\\n`;\n\n return code;\n}\n\n/**\n * Group contracts by their import path\n */\nfunction groupContractsByImportPath(mappings: RouteContractMapping[]): Record<string, string[]>\n{\n const groups: Record<string, Set<string>> = {};\n\n for (let i = 0; i < mappings.length; i++)\n {\n const mapping = mappings[i];\n const path = mapping.contractImportPath;\n\n if (!groups[path])\n {\n groups[path] = new Set();\n }\n\n groups[path].add(mapping.contractName);\n }\n\n // Convert Set to Array\n const result: Record<string, string[]> = {};\n const keys = Object.keys(groups);\n\n for (let i = 0; i < keys.length; i++)\n {\n const key = keys[i];\n result[key] = Array.from(groups[key]);\n }\n\n return result;\n}\n\n/**\n * Generate API object with all methods\n */\nfunction generateApiObject(\n grouped: Record<string, RouteContractMapping[]>,\n options: ClientGenerationOptions\n): string\n{\n let code = '';\n\n code += `/**\n * Type-safe API client\n */\nexport const api = {\\n`;\n\n const resourceNames = Object.keys(grouped);\n\n for (let i = 0; i < resourceNames.length; i++)\n {\n const resourceName = resourceNames[i];\n const routes = grouped[resourceName];\n\n code += ` ${resourceName}: {\\n`;\n\n for (let j = 0; j < routes.length; j++)\n {\n const route = routes[j];\n code += generateMethodCode(route, options);\n }\n\n code += ` }`;\n\n if (i < resourceNames.length - 1)\n {\n code += `,`;\n }\n\n code += `\\n`;\n }\n\n code += `} as const;\\n\\n`;\n\n return code;\n}\n\n/**\n * Generate a single method\n */\nfunction generateMethodCode(mapping: RouteContractMapping, options: ClientGenerationOptions): string\n{\n const methodName = generateMethodName(mapping);\n const contractType = `typeof ${mapping.contractName}`;\n const hasParams = mapping.path.includes(':');\n const hasQuery = false; // TODO: detect from contract\n const hasBody = ['POST', 'PUT', 'PATCH'].indexOf(mapping.method) !== -1;\n\n let code = '';\n\n // JSDoc\n if (options.includeJsDoc !== false)\n {\n code += ` /**\\n`;\n code += ` * ${mapping.method} ${mapping.path}\\n`;\n code += ` */\\n`;\n }\n\n // Method signature\n code += ` ${methodName}: (`;\n\n // Parameters\n const params: string[] = [];\n\n if (hasParams)\n {\n params.push(`params: InferContract<${contractType}>['params']`);\n }\n\n if (hasQuery)\n {\n params.push(`query?: InferContract<${contractType}>['query']`);\n }\n\n if (hasBody)\n {\n params.push(`body: InferContract<${contractType}>['body']`);\n }\n\n if (params.length > 0)\n {\n code += `options: { ${params.join(', ')} }`;\n }\n\n code += `) => `;\n\n // Return type - pass basePath as first parameter\n code += `client.call('${mapping.path}', ${mapping.contractName}`;\n\n if (params.length > 0)\n {\n code += `, options`;\n }\n\n code += `),\\n`;\n\n return code;\n}\n\n/**\n * Generate method name from route\n */\nfunction generateMethodName(mapping: RouteContractMapping): string\n{\n const method = mapping.method.toLowerCase();\n\n // For index routes\n if (mapping.path === '/' || mapping.path.match(/^\\/[\\w-]+$/))\n {\n // Simple path like /users -> get, create, update\n if (method === 'get')\n {\n return 'list';\n }\n if (method === 'post')\n {\n return 'create';\n }\n }\n\n // For dynamic routes like /users/:id\n if (mapping.path.includes(':'))\n {\n if (method === 'get')\n {\n return 'getById';\n }\n if (method === 'put' || method === 'patch')\n {\n return 'update';\n }\n if (method === 'delete')\n {\n return 'delete';\n }\n }\n\n // Default: method name\n return method;\n}\n\n/**\n * Generate footer\n */\nfunction generateFooter(): string\n{\n return `/**\n * Export client instance for advanced usage\n *\n * Use this to add interceptors or customize the client:\n *\n * @example\n * \\`\\`\\`ts\n * import { client } from './api';\n * import { createAuthInterceptor } from '@spfn/auth/nextjs';\n * import { NextJSCookieProvider } from '@spfn/auth/nextjs';\n *\n * client.use(createAuthInterceptor({\n * cookieProvider: new NextJSCookieProvider(),\n * encryptionKey: process.env.ENCRYPTION_KEY!\n * }));\n * \\`\\`\\`\n */\nexport { client };\n`;\n}\n\n/**\n * Count unique contract files\n */\nfunction countUniqueContractFiles(mappings: RouteContractMapping[]): number\n{\n const files = new Set<string>();\n\n for (let i = 0; i < mappings.length; i++)\n {\n if (mappings[i].contractFile)\n {\n files.add(mappings[i].contractFile as string);\n }\n }\n\n return files.size;\n}","/**\n * Pino Logger Adapter\n *\n * High-performance logger adapter using Pino with pretty-print for development and JSON for production.\n */\n\nimport pino from 'pino';\nimport type { LoggerAdapter, AdapterConfig, LogLevel } from './types';\n\n/**\n * Pino Logger Adapter\n */\nexport class PinoAdapter implements LoggerAdapter\n{\n private logger: pino.Logger;\n\n constructor(config: AdapterConfig)\n {\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n // Development: use simple console output without transport\n // Production: use JSON output\n this.logger = pino({\n level: config.level,\n\n // 기본 필드\n base: config.module ? { module: config.module } : undefined,\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const childLogger = new PinoAdapter({ level: this.logger.level as LogLevel, module });\n childLogger.logger = this.logger.child({ module });\n return childLogger;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(context || {}, message);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(context || {}, message);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.warn(errorOrContext || {}, message);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.error(errorOrContext || {}, message);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal({ err: errorOrContext, ...context }, message);\n }\n else\n {\n this.logger.fatal(errorOrContext || {}, message);\n }\n }\n\n async close(): Promise<void>\n {\n // Pino는 자동으로 flush됨\n // 필요시 pino.final() 사용 가능\n }\n}","/**\n * Logger Type Definitions\n *\n * 로깅 시스템 타입 정의\n *\n * ✅ 구현 완료:\n * - LogLevel 타입 정의\n * - LogMetadata 인터페이스\n * - Transport 인터페이스\n * - 환경별 설정 타입\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현체)\n * - src/logger/config.ts (설정)\n */\n\n/**\n * 로그 레벨\n * debug < info < warn < error < fatal\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * 로그 레벨 우선순위\n */\nexport const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n fatal: 4,\n};\n\n/**\n * 로그 메타데이터\n */\nexport interface LogMetadata\n{\n timestamp: Date;\n level: LogLevel;\n message: string;\n module?: string;\n error?: Error;\n context?: Record<string, unknown>;\n}\n\n/**\n * Transport 인터페이스\n * 모든 Transport는 이 인터페이스를 구현해야 함\n */\nexport interface Transport\n{\n /**\n * Transport 이름\n */\n name: string;\n\n /**\n * 최소 로그 레벨 (이 레벨 이상만 처리)\n */\n level: LogLevel;\n\n /**\n * 활성화 여부\n */\n enabled: boolean;\n\n /**\n * 로그 처리 함수\n */\n log(metadata: LogMetadata): Promise<void>;\n\n /**\n * Transport 종료 (리소스 정리)\n */\n close?(): Promise<void>;\n}\n\n/**\n * Logger 설정\n */\nexport interface LoggerConfig\n{\n /**\n * 기본 로그 레벨\n */\n level: LogLevel;\n\n /**\n * 모듈명 (context)\n */\n module?: string;\n\n /**\n * Transport 리스트\n */\n transports: Transport[];\n}\n\n/**\n * Transport 설정 (공통)\n */\nexport interface TransportConfig\n{\n level: LogLevel;\n enabled: boolean;\n}\n\n/**\n * Console Transport 설정\n */\nexport interface ConsoleTransportConfig extends TransportConfig\n{\n colorize?: boolean;\n}\n\n/**\n * File Transport 설정\n */\nexport interface FileTransportConfig extends TransportConfig\n{\n logDir: string;\n maxFileSize?: number; // bytes\n maxFiles?: number; // 최대 로그 파일 개수\n}\n\n/**\n * Slack Transport 설정\n */\nexport interface SlackTransportConfig extends TransportConfig\n{\n webhookUrl: string;\n channel?: string;\n username?: string;\n}\n\n/**\n * Email Transport 설정\n */\nexport interface EmailTransportConfig extends TransportConfig\n{\n from: string;\n to: string[];\n smtpHost: string;\n smtpPort: number;\n smtpUser?: string;\n smtpPassword?: string;\n}","/**\n * Logger Formatters\n *\n * Log formatting utilities for console, JSON, Slack, and Email outputs with sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata } from './types';\n\n/**\n * 민감 정보로 간주되는 키 목록\n * 이 키들을 포함하는 필드는 자동으로 마스킹됨\n */\nconst SENSITIVE_KEYS = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'accesstoken',\n 'access_token',\n 'refreshtoken',\n 'refresh_token',\n 'authorization',\n 'auth',\n 'cookie',\n 'session',\n 'sessionid',\n 'session_id',\n 'privatekey',\n 'private_key',\n 'creditcard',\n 'credit_card',\n 'cardnumber',\n 'card_number',\n 'cvv',\n 'ssn',\n 'pin',\n];\n\n/**\n * 마스킹된 값\n */\nconst MASKED_VALUE = '***MASKED***';\n\n/**\n * 키가 민감 정보를 포함하는지 확인\n */\nfunction isSensitiveKey(key: string): boolean\n{\n const lowerKey = key.toLowerCase();\n return SENSITIVE_KEYS.some(sensitive => lowerKey.includes(sensitive));\n}\n\n/**\n * 민감 정보 마스킹\n * Context 객체에서 민감한 정보(비밀번호, 토큰 등)를 마스킹\n *\n * @param data - 원본 데이터\n * @returns 마스킹된 데이터\n */\nexport function maskSensitiveData(data: unknown): unknown\n{\n // null, undefined 처리\n if (data === null || data === undefined)\n {\n return data;\n }\n\n // 배열 처리\n if (Array.isArray(data))\n {\n return data.map(item => maskSensitiveData(item));\n }\n\n // 객체 처리\n if (typeof data === 'object')\n {\n const masked: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data))\n {\n if (isSensitiveKey(key))\n {\n // 민감 정보 키는 마스킹\n masked[key] = MASKED_VALUE;\n }\n else if (typeof value === 'object' && value !== null)\n {\n // 중첩된 객체는 재귀 처리\n masked[key] = maskSensitiveData(value);\n }\n else\n {\n // 일반 값은 그대로 유지\n masked[key] = value;\n }\n }\n\n return masked;\n }\n\n // 기본 타입은 그대로 반환\n return data;\n}\n\n/**\n * ANSI 컬러 코드\n */\nconst COLORS = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n\n // 로그 레벨 컬러\n debug: '\\x1b[36m', // cyan\n info: '\\x1b[32m', // green\n warn: '\\x1b[33m', // yellow\n error: '\\x1b[31m', // red\n fatal: '\\x1b[35m', // magenta\n\n // 추가 컬러\n gray: '\\x1b[90m',\n};\n\n/**\n * 로그 레벨을 컬러 문자열로 변환\n */\nexport function colorizeLevel(level: LogLevel): string\n{\n const color = COLORS[level];\n const levelStr = level.toUpperCase().padEnd(5);\n return `${color}${levelStr}${COLORS.reset}`;\n}\n\n/**\n * 타임스탬프 포맷 (ISO 8601)\n */\nexport function formatTimestamp(date: Date): string\n{\n return date.toISOString();\n}\n\n/**\n * 타임스탬프 포맷 (사람이 읽기 쉬운 형식)\n */\nexport function formatTimestampHuman(date: Date): string\n{\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n const seconds = String(date.getSeconds()).padStart(2, '0');\n const ms = String(date.getMilliseconds()).padStart(3, '0');\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`;\n}\n\n/**\n * 에러 객체를 문자열로 변환 (스택 트레이스 포함)\n */\nexport function formatError(error: Error): string\n{\n const lines: string[] = [];\n\n lines.push(`${error.name}: ${error.message}`);\n\n if (error.stack)\n {\n const stackLines = error.stack.split('\\n').slice(1);\n lines.push(...stackLines);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Context 객체를 문자열로 변환\n */\nexport function formatContext(context: Record<string, unknown>): string\n{\n try\n {\n return JSON.stringify(context, null, 2);\n }\n catch (error)\n {\n return '[Context serialization failed]';\n }\n}\n\n/**\n * 콘솔용 컬러 포맷\n */\nexport function formatConsole(metadata: LogMetadata, colorize = true): string\n{\n const parts: string[] = [];\n\n // [타임스탬프]\n const timestamp = formatTimestampHuman(metadata.timestamp);\n if (colorize)\n {\n parts.push(`${COLORS.gray}[${timestamp}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${timestamp}]`);\n }\n\n // [module=value]\n if (metadata.module)\n {\n if (colorize)\n {\n parts.push(`${COLORS.dim}[module=${metadata.module}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[module=${metadata.module}]`);\n }\n }\n\n // Context를 각각 [key=value] 형태로 추가\n if (metadata.context && Object.keys(metadata.context).length > 0)\n {\n Object.entries(metadata.context).forEach(([key, value]) =>\n {\n const valueStr = typeof value === 'string' ? value : String(value);\n if (colorize)\n {\n parts.push(`${COLORS.dim}[${key}=${valueStr}]${COLORS.reset}`);\n }\n else\n {\n parts.push(`[${key}=${valueStr}]`);\n }\n });\n }\n\n // (LEVEL):\n const levelStr = metadata.level.toUpperCase();\n if (colorize)\n {\n const color = COLORS[metadata.level];\n parts.push(`${color}(${levelStr})${COLORS.reset}:`);\n }\n else\n {\n parts.push(`(${levelStr}):`);\n }\n\n // 메시지\n if (colorize)\n {\n parts.push(`${COLORS.bright}${metadata.message}${COLORS.reset}`);\n }\n else\n {\n parts.push(metadata.message);\n }\n\n let output = parts.join(' ');\n\n // 에러는 별도 줄로 추가\n if (metadata.error)\n {\n output += '\\n' + formatError(metadata.error);\n }\n\n return output;\n}\n\n/**\n * JSON 포맷 (파일 저장 및 전송용)\n */\nexport function formatJSON(metadata: LogMetadata): string\n{\n const obj: Record<string, unknown> = {\n timestamp: formatTimestamp(metadata.timestamp),\n level: metadata.level,\n message: metadata.message,\n };\n\n if (metadata.module)\n {\n obj.module = metadata.module;\n }\n\n if (metadata.context)\n {\n obj.context = metadata.context;\n }\n\n if (metadata.error)\n {\n obj.error = {\n name: metadata.error.name,\n message: metadata.error.message,\n stack: metadata.error.stack,\n };\n }\n\n return JSON.stringify(obj);\n}\n\n/**\n * Slack 메시지 포맷\n */\nexport function formatSlack(metadata: LogMetadata): string\n{\n const emoji = {\n debug: ':bug:',\n info: ':information_source:',\n warn: ':warning:',\n error: ':x:',\n fatal: ':fire:',\n };\n\n const parts: string[] = [];\n\n parts.push(`${emoji[metadata.level]} *${metadata.level.toUpperCase()}*`);\n\n if (metadata.module)\n {\n parts.push(`\\`[${metadata.module}]\\``);\n }\n\n parts.push(metadata.message);\n\n let message = parts.join(' ');\n\n if (metadata.context)\n {\n message += '\\n```\\n' + JSON.stringify(metadata.context, null, 2) + '\\n```';\n }\n\n if (metadata.error)\n {\n message += '\\n```\\n' + formatError(metadata.error) + '\\n```';\n }\n\n return message;\n}\n\n/**\n * Email 제목 생성\n */\nexport function formatEmailSubject(metadata: LogMetadata): string\n{\n const prefix = `[${metadata.level.toUpperCase()}]`;\n const module = metadata.module ? `[${metadata.module}]` : '';\n\n return `${prefix}${module} ${metadata.message}`;\n}\n\n/**\n * Email 본문 생성 (HTML)\n */\nexport function formatEmailBody(metadata: LogMetadata): string\n{\n const parts: string[] = [];\n\n parts.push('<html>');\n parts.push('<body style=\"font-family: monospace; padding: 20px;\">');\n\n // 헤더\n parts.push(`<h2 style=\"color: ${getEmailColor(metadata.level)};\">`);\n parts.push(`${metadata.level.toUpperCase()}`);\n parts.push('</h2>');\n\n // 시간\n parts.push('<p>');\n parts.push(`<strong>Timestamp:</strong> ${formatTimestamp(metadata.timestamp)}`);\n parts.push('</p>');\n\n // 모듈\n if (metadata.module)\n {\n parts.push('<p>');\n parts.push(`<strong>Module:</strong> ${metadata.module}`);\n parts.push('</p>');\n }\n\n // 메시지\n parts.push('<p>');\n parts.push(`<strong>Message:</strong> ${metadata.message}`);\n parts.push('</p>');\n\n // Context\n if (metadata.context)\n {\n parts.push('<h3>Context</h3>');\n parts.push('<pre style=\"background: #f4f4f4; padding: 10px; border-radius: 4px;\">');\n parts.push(JSON.stringify(metadata.context, null, 2));\n parts.push('</pre>');\n }\n\n // 에러\n if (metadata.error)\n {\n parts.push('<h3>Error Stack Trace</h3>');\n parts.push('<pre style=\"background: #fff0f0; padding: 10px; border-radius: 4px;\">');\n parts.push(formatError(metadata.error));\n parts.push('</pre>');\n }\n\n parts.push('</body>');\n parts.push('</html>');\n\n return parts.join('\\n');\n}\n\n/**\n * Email 레벨별 컬러\n */\nfunction getEmailColor(level: LogLevel): string\n{\n const colors: Record<LogLevel, string> = {\n debug: '#00BCD4',\n info: '#4CAF50',\n warn: '#FF9800',\n error: '#F44336',\n fatal: '#9C27B0',\n };\n\n return colors[level];\n}","/**\n * Logger Class\n *\n * Central logging class with multiple transports, child loggers, and sensitive data masking.\n */\n\nimport type { LogLevel, LogMetadata, LoggerConfig, Transport } from './types';\nimport { LOG_LEVEL_PRIORITY } from './types';\nimport { maskSensitiveData } from './formatters';\n\n/**\n * Logger class\n */\nexport class Logger\n{\n private readonly config: LoggerConfig;\n private readonly module?: string;\n\n constructor(config: LoggerConfig)\n {\n this.config = config;\n this.module = config.module;\n }\n\n /**\n * Get current log level\n */\n get level(): LogLevel\n {\n return this.config.level;\n }\n\n /**\n * Create child logger (per module)\n */\n child(module: string): Logger\n {\n return new Logger({\n ...this.config,\n module,\n });\n }\n\n /**\n * Debug log\n */\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.log('debug', message, undefined, context);\n }\n\n /**\n * Info log\n */\n info(message: string, context?: Record<string, unknown>): void\n {\n this.log('info', message, undefined, context);\n }\n\n /**\n * Warn log\n */\n warn(message: string, context?: Record<string, unknown>): void;\n warn(message: string, error: Error, context?: Record<string, unknown>): void;\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('warn', message, errorOrContext, context);\n }\n else\n {\n this.log('warn', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Error log\n */\n error(message: string, context?: Record<string, unknown>): void;\n error(message: string, error: Error, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('error', message, errorOrContext, context);\n }\n else\n {\n this.log('error', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Fatal log\n */\n fatal(message: string, context?: Record<string, unknown>): void;\n fatal(message: string, error: Error, context?: Record<string, unknown>): void;\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.log('fatal', message, errorOrContext, context);\n }\n else\n {\n this.log('fatal', message, undefined, errorOrContext);\n }\n }\n\n /**\n * Log processing (internal)\n */\n private log(level: LogLevel, message: string, error?: Error, context?: Record<string, unknown>): void\n {\n // Early return if log level is below configured level\n // This prevents unnecessary metadata creation and processing\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.config.level])\n {\n return;\n }\n\n const metadata: LogMetadata = {\n timestamp: new Date(),\n level,\n message,\n module: this.module,\n error,\n // Mask sensitive information in context to prevent credential leaks\n context: context ? maskSensitiveData(context) as Record<string, unknown> : undefined,\n };\n\n // Pass to all enabled Transports\n this.processTransports(metadata);\n }\n\n /**\n * Process Transports\n */\n private processTransports(metadata: LogMetadata): void\n {\n const promises = this.config.transports\n .filter(transport => transport.enabled)\n .map(transport => this.safeTransportLog(transport, metadata));\n\n // Async processing to prevent Transport errors from blocking logs\n Promise.all(promises).catch(error =>\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport error: ${errorMessage}\\n`);\n });\n }\n\n /**\n * Transport log (error-safe)\n */\n private async safeTransportLog(transport: Transport, metadata: LogMetadata): Promise<void>\n {\n try\n {\n await transport.log(metadata);\n }\n catch (error)\n {\n // Use stderr directly to avoid circular logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[Logger] Transport \"${transport.name}\" failed: ${errorMessage}\\n`);\n }\n }\n\n /**\n * Close all Transports\n */\n async close(): Promise<void>\n {\n const closePromises = this.config.transports\n .filter(transport => transport.close)\n .map(transport => transport.close!());\n\n await Promise.all(closePromises);\n }\n}","/**\n * Console Transport\n *\n * 콘솔 출력 Transport\n *\n * ✅ 구현 완료:\n * - 콘솔 출력 (stdout/stderr)\n * - 컬러 출력 지원\n * - 로그 레벨별 스트림 분리 (warn/error/fatal → stderr)\n *\n * 🔗 관련 파일:\n * - src/logger/types.ts (Transport 인터페이스)\n * - src/logger/formatters.ts (포맷터)\n * - src/logger/config.ts (설정)\n */\n\nimport type { Transport, LogMetadata, LogLevel, ConsoleTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatConsole } from '../formatters';\n\n/**\n * Console Transport\n */\nexport class ConsoleTransport implements Transport\n{\n public readonly name = 'console';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private colorize: boolean;\n\n constructor(config: ConsoleTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.colorize = config.colorize ?? true;\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // 포맷팅\n const message = formatConsole(metadata, this.colorize);\n\n // warn/error/fatal은 stderr로, 나머지는 stdout으로\n if (metadata.level === 'warn' || metadata.level === 'error' || metadata.level === 'fatal')\n {\n console.error(message);\n }\n else\n {\n console.log(message);\n }\n }\n}","/**\n * File Transport\n *\n * File output transport with date and size-based rotation, automatic cleanup.\n */\n\nimport { createWriteStream, existsSync, mkdirSync, statSync, readdirSync, unlinkSync, renameSync } from 'fs';\nimport type { WriteStream } from 'fs';\nimport { join } from 'path';\nimport type { Transport, LogMetadata, LogLevel, FileTransportConfig } from '../types';\nimport { LOG_LEVEL_PRIORITY } from '../types';\nimport { formatJSON } from '../formatters';\n\n/**\n * File Transport\n */\nexport class FileTransport implements Transport\n{\n public readonly name = 'file';\n public readonly level: LogLevel;\n public readonly enabled: boolean;\n\n private readonly logDir: string;\n private readonly maxFileSize: number;\n private readonly maxFiles: number;\n private currentStream: WriteStream | null = null;\n private currentFilename: string | null = null;\n\n constructor(config: FileTransportConfig)\n {\n this.level = config.level;\n this.enabled = config.enabled;\n this.logDir = config.logDir;\n this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024; // 10MB\n this.maxFiles = config.maxFiles ?? 10;\n\n // 로그 디렉토리가 없으면 생성\n if (!existsSync(this.logDir))\n {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n async log(metadata: LogMetadata): Promise<void>\n {\n // Enabled 상태 체크\n if (!this.enabled)\n {\n return;\n }\n\n // 로그 레벨 체크\n if (LOG_LEVEL_PRIORITY[metadata.level] < LOG_LEVEL_PRIORITY[this.level])\n {\n return;\n }\n\n // JSON 포맷으로 변환\n const message = formatJSON(metadata);\n\n // 파일명: YYYY-MM-DD.log\n const filename = this.getLogFilename(metadata.timestamp);\n\n // 날짜가 변경되면 스트림 교체\n if (this.currentFilename !== filename)\n {\n await this.rotateStream(filename);\n await this.cleanOldFiles(); // 오래된 파일 정리\n }\n // 파일 크기 체크 및 로테이션\n else if (this.currentFilename)\n {\n await this.checkAndRotateBySize();\n }\n\n // 스트림에 쓰기\n if (this.currentStream)\n {\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.write(message + '\\n', 'utf-8', (error: Error | null | undefined) =>\n {\n if (error)\n {\n // 파일 쓰기 실패 시 stderr로 출력 (fallback)\n process.stderr.write(`[FileTransport] Failed to write log: ${error.message}\\n`);\n reject(error);\n }\n else\n {\n resolve();\n }\n });\n });\n }\n }\n\n /**\n * 스트림 교체 (날짜 변경 시)\n */\n private async rotateStream(filename: string): Promise<void>\n {\n // 기존 스트림 닫기\n if (this.currentStream)\n {\n await this.closeStream();\n }\n\n // 새 스트림 생성\n const filepath = join(this.logDir, filename);\n\n this.currentStream = createWriteStream(filepath, {\n flags: 'a', // append mode\n encoding: 'utf-8',\n });\n\n this.currentFilename = filename;\n\n // 스트림 에러 핸들링\n this.currentStream.on('error', (error) =>\n {\n process.stderr.write(`[FileTransport] Stream error: ${error.message}\\n`);\n // 에러 발생 시 스트림 초기화\n this.currentStream = null;\n this.currentFilename = null;\n });\n }\n\n /**\n * 현재 스트림 닫기\n */\n private async closeStream(): Promise<void>\n {\n if (!this.currentStream)\n {\n return;\n }\n\n return new Promise((resolve, reject) =>\n {\n this.currentStream!.end((error: Error | null | undefined) =>\n {\n if (error)\n {\n reject(error);\n }\n else\n {\n this.currentStream = null;\n this.currentFilename = null;\n resolve();\n }\n });\n });\n }\n\n /**\n * 파일 크기 체크 및 크기 기반 로테이션\n */\n private async checkAndRotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n const filepath = join(this.logDir, this.currentFilename);\n\n // 파일이 존재하지 않으면 스킵\n if (!existsSync(filepath))\n {\n return;\n }\n\n try\n {\n const stats = statSync(filepath);\n\n // 파일 크기가 maxFileSize를 초과하면 로테이션\n if (stats.size >= this.maxFileSize)\n {\n await this.rotateBySize();\n }\n }\n catch (error)\n {\n // 파일 stat 실패 시 무시\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to check file size: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 크기 기반 로테이션 수행\n * 예: 2025-01-01.log -> 2025-01-01.1.log, 2025-01-01.1.log -> 2025-01-01.2.log\n */\n private async rotateBySize(): Promise<void>\n {\n if (!this.currentFilename)\n {\n return;\n }\n\n // 기존 스트림 닫기\n await this.closeStream();\n\n const baseName = this.currentFilename.replace(/\\.log$/, '');\n const files = readdirSync(this.logDir);\n\n // 현재 날짜의 로그 파일들 찾기 (예: 2025-01-01.log, 2025-01-01.1.log, ...)\n const relatedFiles = files\n .filter(file => file.startsWith(baseName) && file.endsWith('.log'))\n .sort()\n .reverse(); // 역순 정렬로 높은 번호부터 처리\n\n // 기존 파일들을 번호 증가시켜 이동 (예: .1.log -> .2.log)\n for (const file of relatedFiles)\n {\n const match = file.match(/\\.(\\d+)\\.log$/);\n if (match)\n {\n const oldNum = parseInt(match[1], 10);\n const newNum = oldNum + 1;\n const oldPath = join(this.logDir, file);\n const newPath = join(this.logDir, `${baseName}.${newNum}.log`);\n\n try\n {\n renameSync(oldPath, newPath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate file: ${errorMessage}\\n`);\n }\n }\n }\n\n // 현재 파일을 .1.log로 이동\n const currentPath = join(this.logDir, this.currentFilename);\n const newPath = join(this.logDir, `${baseName}.1.log`);\n\n try\n {\n if (existsSync(currentPath))\n {\n renameSync(currentPath, newPath);\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to rotate current file: ${errorMessage}\\n`);\n }\n\n // 새 스트림 생성 (동일한 파일명으로)\n await this.rotateStream(this.currentFilename);\n }\n\n /**\n * 오래된 로그 파일 정리\n * maxFiles 개수를 초과하는 로그 파일 삭제\n */\n private async cleanOldFiles(): Promise<void>\n {\n try\n {\n // 디렉토리가 존재하지 않으면 스킵\n if (!existsSync(this.logDir))\n {\n return;\n }\n\n const files = readdirSync(this.logDir);\n\n // .log로 끝나는 파일만 필터링 후 수정 시간 기준 정렬\n const logFiles = files\n .filter(file => file.endsWith('.log'))\n .map(file =>\n {\n const filepath = join(this.logDir, file);\n const stats = statSync(filepath);\n return { file, mtime: stats.mtime };\n })\n .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()); // 최신 파일이 앞으로\n\n // maxFiles를 초과하는 오래된 파일들 삭제\n if (logFiles.length > this.maxFiles)\n {\n const filesToDelete = logFiles.slice(this.maxFiles);\n\n for (const { file } of filesToDelete)\n {\n const filepath = join(this.logDir, file);\n try\n {\n unlinkSync(filepath);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to delete old file \"${file}\": ${errorMessage}\\n`);\n }\n }\n }\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[FileTransport] Failed to clean old files: ${errorMessage}\\n`);\n }\n }\n\n /**\n * 날짜별 로그 파일명 생성\n */\n private getLogFilename(date: Date): string\n {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}.log`;\n }\n\n async close(): Promise<void>\n {\n // 스트림 정리\n await this.closeStream();\n }\n}","/**\n * Logger Configuration\n *\n * Environment-based logger configuration with validation for console, file, Slack, and Email transports.\n */\n\nimport { existsSync, accessSync, constants, mkdirSync, writeFileSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type {\n LogLevel,\n ConsoleTransportConfig,\n FileTransportConfig,\n SlackTransportConfig,\n EmailTransportConfig,\n} from './types';\n\n/**\n * Check if file logging is enabled (for self-hosted)\n */\nexport function isFileLoggingEnabled(): boolean\n{\n return process.env.LOGGER_FILE_ENABLED === 'true';\n}\n\n/**\n * Get default log level by environment\n */\nexport function getDefaultLogLevel(): LogLevel\n{\n const isProduction = process.env.NODE_ENV === 'production';\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment)\n {\n return 'debug';\n }\n\n if (isProduction)\n {\n return 'info';\n }\n\n // Test environment\n return 'warn';\n}\n\n/**\n * Console Transport configuration\n */\nexport function getConsoleConfig(): ConsoleTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'debug',\n enabled: true,\n colorize: !isProduction, // Dev: colored output, Production: plain text\n };\n}\n\n/**\n * File Transport configuration\n */\nexport function getFileConfig(): FileTransportConfig\n{\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'info',\n enabled: isProduction, // File logging in production only\n logDir: process.env.LOG_DIR || './logs',\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n };\n}\n\n/**\n * Slack Transport configuration\n */\nexport function getSlackConfig(): SlackTransportConfig | null\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return null; // Disabled if not configured\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'error', // Send error and above to Slack\n enabled: isProduction, // Enabled in production only\n webhookUrl,\n channel: process.env.SLACK_CHANNEL,\n username: process.env.SLACK_USERNAME || 'Logger Bot',\n };\n}\n\n/**\n * Email Transport configuration\n */\nexport function getEmailConfig(): EmailTransportConfig | null\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // Disabled if required settings are missing\n if (!smtpHost || !smtpPort || !emailFrom || !emailTo)\n {\n return null;\n }\n\n const isProduction = process.env.NODE_ENV === 'production';\n\n return {\n level: 'fatal', // Send fatal level only via email\n enabled: isProduction, // Enabled in production only\n from: emailFrom,\n to: emailTo.split(',').map(email => email.trim()),\n smtpHost,\n smtpPort: parseInt(smtpPort, 10),\n smtpUser: process.env.SMTP_USER,\n smtpPassword: process.env.SMTP_PASSWORD,\n };\n}\n\n/**\n * Validate directory path and write permissions\n */\nfunction validateDirectoryWritable(dirPath: string): void\n{\n // Check if directory exists\n if (!existsSync(dirPath))\n {\n // Try to create directory\n try\n {\n mkdirSync(dirPath, { recursive: true });\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to create log directory \"${dirPath}\": ${errorMessage}`);\n }\n }\n\n // Check write permission\n try\n {\n accessSync(dirPath, constants.W_OK);\n }\n catch\n {\n throw new Error(`Log directory \"${dirPath}\" is not writable. Please check permissions.`);\n }\n\n // Try to write a test file\n const testFile = join(dirPath, '.logger-write-test');\n try\n {\n writeFileSync(testFile, 'test', 'utf-8');\n unlinkSync(testFile);\n }\n catch (error)\n {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Cannot write to log directory \"${dirPath}\": ${errorMessage}`);\n }\n}\n\n/**\n * Validate file transport configuration\n */\nfunction validateFileConfig(): void\n{\n if (!isFileLoggingEnabled())\n {\n return; // File logging disabled, skip validation\n }\n\n const logDir = process.env.LOG_DIR;\n\n // Check if LOG_DIR is set\n if (!logDir)\n {\n throw new Error(\n 'LOG_DIR environment variable is required when LOGGER_FILE_ENABLED=true. ' +\n 'Example: LOG_DIR=/var/log/myapp'\n );\n }\n\n // Validate directory\n validateDirectoryWritable(logDir);\n}\n\n/**\n * Validate Slack transport configuration\n */\nfunction validateSlackConfig(): void\n{\n const webhookUrl = process.env.SLACK_WEBHOOK_URL;\n\n if (!webhookUrl)\n {\n return; // Slack disabled, skip validation\n }\n\n // Validate webhook URL format\n if (!webhookUrl.startsWith('https://hooks.slack.com/'))\n {\n throw new Error(\n `Invalid SLACK_WEBHOOK_URL: \"${webhookUrl}\". ` +\n 'Slack webhook URLs must start with \"https://hooks.slack.com/\"'\n );\n }\n}\n\n/**\n * Validate Email transport configuration\n */\nfunction validateEmailConfig(): void\n{\n const smtpHost = process.env.SMTP_HOST;\n const smtpPort = process.env.SMTP_PORT;\n const emailFrom = process.env.EMAIL_FROM;\n const emailTo = process.env.EMAIL_TO;\n\n // If any email config is set, all required fields must be present\n const hasAnyEmailConfig = smtpHost || smtpPort || emailFrom || emailTo;\n if (!hasAnyEmailConfig)\n {\n return; // Email disabled, skip validation\n }\n\n // Validate all required fields\n const missingFields: string[] = [];\n if (!smtpHost) missingFields.push('SMTP_HOST');\n if (!smtpPort) missingFields.push('SMTP_PORT');\n if (!emailFrom) missingFields.push('EMAIL_FROM');\n if (!emailTo) missingFields.push('EMAIL_TO');\n\n if (missingFields.length > 0)\n {\n throw new Error(\n `Email transport configuration incomplete. Missing: ${missingFields.join(', ')}. ` +\n 'Either set all required fields or remove all email configuration.'\n );\n }\n\n // Validate SMTP port is a number\n const port = parseInt(smtpPort!, 10);\n if (isNaN(port) || port < 1 || port > 65535)\n {\n throw new Error(\n `Invalid SMTP_PORT: \"${smtpPort}\". Must be a number between 1 and 65535.`\n );\n }\n\n // Validate email format (basic check)\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(emailFrom!))\n {\n throw new Error(`Invalid EMAIL_FROM format: \"${emailFrom}\"`);\n }\n\n // Validate email recipients\n const recipients = emailTo!.split(',').map(e => e.trim());\n for (const email of recipients)\n {\n if (!emailRegex.test(email))\n {\n throw new Error(`Invalid email address in EMAIL_TO: \"${email}\"`);\n }\n }\n}\n\n/**\n * Validate environment variables\n */\nfunction validateEnvironment(): void\n{\n const nodeEnv = process.env.NODE_ENV;\n\n if (!nodeEnv)\n {\n process.stderr.write(\n '[Logger] Warning: NODE_ENV is not set. Defaulting to test environment.\\n'\n );\n }\n // Allow any NODE_ENV value (development, production, test, staging, local, etc.)\n // No validation needed - users can use custom environments\n}\n\n/**\n * Validate all logger configuration\n * Throws an error if configuration is invalid\n */\nexport function validateConfig(): void\n{\n try\n {\n validateEnvironment();\n validateFileConfig();\n validateSlackConfig();\n validateEmailConfig();\n }\n catch (error)\n {\n if (error instanceof Error)\n {\n throw new Error(`[Logger] Configuration validation failed: ${error.message}`);\n }\n throw error;\n }\n}","/**\n * Custom Logger Adapter\n *\n * 자체 구현한 Logger를 사용하는 Adapter\n *\n * ✅ 구현 완료:\n * - 기존 Logger 클래스 래핑\n * - Transport 시스템 (Console, File)\n * - Child logger 지원\n *\n * 💡 용도:\n * - Pino 의존성 제거 필요시\n * - 커스텀 Transport 필요시\n * - 완전한 제어가 필요한 경우\n *\n * 🔗 관련 파일:\n * - src/logger/logger.ts (Logger 클래스)\n * - src/logger/transports/ (Transport 구현)\n * - src/logger/adapters/types.ts (인터페이스)\n */\n\nimport { Logger } from '../logger';\nimport { ConsoleTransport } from '../transports/console';\nimport { FileTransport } from '../transports/file';\nimport { getConsoleConfig, getFileConfig } from '../config';\nimport type { LoggerAdapter, AdapterConfig } from './types';\nimport type { Transport } from '../types';\n\n/**\n * Transport 초기화\n */\nfunction initializeTransports(): Transport[]\n{\n const transports: Transport[] = [];\n\n // Console Transport (항상 활성화)\n const consoleConfig = getConsoleConfig();\n transports.push(new ConsoleTransport(consoleConfig));\n\n // File Transport (프로덕션에서만 활성화)\n const fileConfig = getFileConfig();\n if (fileConfig.enabled)\n {\n transports.push(new FileTransport(fileConfig));\n }\n\n return transports;\n}\n\n/**\n * Custom Logger Adapter\n */\nexport class CustomAdapter implements LoggerAdapter\n{\n private logger: Logger;\n\n constructor(config: AdapterConfig)\n {\n this.logger = new Logger({\n level: config.level,\n module: config.module,\n transports: initializeTransports(),\n });\n }\n\n child(module: string): LoggerAdapter\n {\n const adapter = new CustomAdapter({ level: this.logger.level, module });\n adapter.logger = this.logger.child(module);\n return adapter;\n }\n\n debug(message: string, context?: Record<string, unknown>): void\n {\n this.logger.debug(message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void\n {\n this.logger.info(message, context);\n }\n\n warn(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.warn(message, errorOrContext, context);\n }\n else\n {\n this.logger.warn(message, errorOrContext);\n }\n }\n\n error(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.error(message, errorOrContext, context);\n }\n else\n {\n this.logger.error(message, errorOrContext);\n }\n }\n\n fatal(message: string, errorOrContext?: Error | Record<string, unknown>, context?: Record<string, unknown>): void\n {\n if (errorOrContext instanceof Error)\n {\n this.logger.fatal(message, errorOrContext, context);\n }\n else\n {\n this.logger.fatal(message, errorOrContext);\n }\n }\n\n async close(): Promise<void>\n {\n await this.logger.close();\n }\n}","/**\n * Logger Adapter Factory\n *\n * Adapter creation and initialization logic\n */\n\nimport { PinoAdapter } from './adapters/pino.js';\nimport { CustomAdapter } from './adapters/custom.js';\nimport { getDefaultLogLevel, validateConfig } from './config.js';\nimport type { LoggerAdapter } from './adapters/types.js';\n\n/**\n * Adapter type\n */\ntype AdapterType = 'pino' | 'custom';\n\n/**\n * Create adapter instance\n */\nfunction createAdapter(type: AdapterType): LoggerAdapter\n{\n const level = getDefaultLogLevel();\n\n switch (type)\n {\n case 'pino':\n return new PinoAdapter({ level });\n\n case 'custom':\n return new CustomAdapter({ level });\n\n default:\n return new PinoAdapter({ level });\n }\n}\n\n/**\n * Read adapter type from environment variable\n */\nfunction getAdapterType(): AdapterType\n{\n const adapterEnv = process.env.LOGGER_ADAPTER as AdapterType;\n\n if (adapterEnv === 'custom' || adapterEnv === 'pino')\n {\n return adapterEnv;\n }\n\n // Default: pino\n return 'pino';\n}\n\n/**\n * Initialize logger with configuration validation\n */\nfunction initializeLogger(): LoggerAdapter\n{\n // Validate configuration before creating logger\n validateConfig();\n\n // Create and return logger instance\n return createAdapter(getAdapterType());\n}\n\n/**\n * Singleton Logger instance\n */\nexport const logger: LoggerAdapter = initializeLogger();","/**\n * Contract Watcher & Client Generator\n *\n * Watches contract files and regenerates client code\n */\n\nimport { join } from 'path';\nimport { watch as chokidarWatch } from 'chokidar';\nimport { scanContracts } from './contract-scanner.js';\nimport { generateClient } from './client-generator.js';\nimport { logger } from '../logger';\nimport type { GenerationStats } from './types.js';\n\nconst codegenLogger = logger.child('codegen');\n\nexport interface WatchGenerateOptions {\n /** Routes directory (default: src/server/routes) */\n routesDir?: string;\n\n /** Output path for generated client (default: src/lib/api.ts) */\n outputPath?: string;\n\n /** Base URL for API client */\n baseUrl?: string;\n\n /** Enable debug logging */\n debug?: boolean;\n\n /** Watch mode (default: true) */\n watch?: boolean;\n}\n\n/**\n * Generate client once\n */\nasync function generateOnce(options: WatchGenerateOptions): Promise<GenerationStats | null> {\n const cwd = process.cwd();\n const routesDir = options.routesDir ?? join(cwd, 'src', 'server', 'routes');\n const outputPath = options.outputPath ?? join(cwd, 'src', 'lib', 'api.ts');\n\n try {\n // Scan contracts\n const contracts = await scanContracts(routesDir);\n\n if (contracts.length === 0)\n {\n if (options.debug)\n {\n codegenLogger.warn('No contracts found');\n }\n return null;\n }\n\n // Generate client\n const stats: GenerationStats = await generateClient(contracts, {\n routesDir,\n outputPath,\n baseUrl: options.baseUrl,\n includeTypes: true,\n includeJsDoc: true\n });\n\n // Log stats\n if (options.debug)\n {\n codegenLogger.info('Client generated', {\n endpoints: stats.methodsGenerated,\n resources: stats.resourcesGenerated,\n duration: stats.duration\n });\n }\n\n return stats;\n }\n catch (error)\n {\n codegenLogger.error(\n 'Generation failed',\n error instanceof Error ? error : new Error(String(error))\n );\n return null;\n }\n}\n\n/**\n * Watch contracts and generate client code\n */\nexport async function watchAndGenerate(options: WatchGenerateOptions = {}): Promise<void> {\n const cwd = process.cwd();\n const routesDir = options.routesDir ?? join(cwd, 'src', 'server', 'routes');\n const outputPath = options.outputPath ?? join(cwd, 'src', 'lib', 'api.ts');\n const watchMode = options.watch !== false;\n\n if (options.debug)\n {\n codegenLogger.info('Contract Watcher Started', { routesDir, outputPath, watch: watchMode });\n }\n\n // Initial generation\n await generateOnce(options);\n\n // Watch mode\n if (watchMode) {\n let isGenerating = false;\n let pendingRegeneration = false;\n\n const watcher = chokidarWatch(routesDir, {\n ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50\n }\n });\n\n const regenerate = async () => {\n if (isGenerating) {\n pendingRegeneration = true;\n return;\n }\n\n isGenerating = true;\n pendingRegeneration = false;\n\n if (options.debug) {\n codegenLogger.info('Contracts changed, regenerating...');\n }\n\n await generateOnce(options);\n\n isGenerating = false;\n\n if (pendingRegeneration) {\n await regenerate();\n }\n };\n\n watcher\n .on('add', regenerate)\n .on('change', regenerate)\n .on('unlink', regenerate);\n\n // Keep process alive\n process.on('SIGINT', () => {\n watcher.close();\n process.exit(0);\n });\n\n // Keep the process alive\n await new Promise(() => {});\n }\n}\n\n// Auto-run if executed directly\nif (import.meta.url === `file://${process.argv[1]}`) {\n watchAndGenerate({ debug: true });\n}","/**\n * Codegen Orchestrator\n *\n * Manages multiple code generators and coordinates their execution\n */\n\nimport { watch as chokidarWatch } from 'chokidar';\nimport { join, relative } from 'path';\nimport mm from 'micromatch';\nimport type { Generator, GeneratorOptions } from './generator.js';\nimport { logger } from '../logger';\n\nconst orchestratorLogger = logger.child('orchestrator');\n\nexport interface OrchestratorOptions\n{\n /** List of generators to orchestrate */\n generators: Generator[];\n\n /** Project root directory */\n cwd?: string;\n\n /** Enable debug logging */\n debug?: boolean;\n}\n\nexport class CodegenOrchestrator\n{\n private readonly generators: Generator[];\n private readonly cwd: string;\n private readonly debug: boolean;\n private isGenerating = false;\n private pendingRegenerations = new Set<string>();\n\n constructor(options: OrchestratorOptions)\n {\n this.generators = options.generators;\n this.cwd = options.cwd ?? process.cwd();\n this.debug = options.debug ?? false;\n }\n\n /**\n * Run all generators once\n */\n async generateAll(): Promise<void>\n {\n if (this.debug)\n {\n orchestratorLogger.info('Running all generators', {\n count: this.generators.length,\n names: this.generators.map(g => g.name)\n });\n }\n\n for (const generator of this.generators)\n {\n try\n {\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug\n };\n\n await generator.generate(genOptions);\n\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Generated successfully`);\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] Generation failed`, err);\n }\n }\n }\n\n /**\n * Start watch mode\n */\n async watch(): Promise<void>\n {\n // Initial generation\n await this.generateAll();\n\n // Collect all watch patterns from generators\n const allPatterns = this.generators.flatMap(g => g.watchPatterns);\n\n if (allPatterns.length === 0)\n {\n orchestratorLogger.warn('No watch patterns defined, exiting watch mode');\n return;\n }\n\n // Extract directories to watch from patterns\n // For pattern like \"watched/**/*.ts\", watch \"watched\" directory\n const dirsToWatch = new Set<string>();\n for (const pattern of allPatterns)\n {\n // Extract base directory from glob pattern (e.g., \"src/**/*.ts\" -> \"src\")\n const baseDir = pattern.split('**')[0].replace(/\\/$/, '') || '.';\n dirsToWatch.add(join(this.cwd, baseDir));\n }\n\n const watchDirs = Array.from(dirsToWatch);\n\n if (this.debug)\n {\n orchestratorLogger.info('Starting watch mode', {\n patterns: allPatterns,\n watchDirs,\n cwd: this.cwd\n });\n }\n\n const watcher = chokidarWatch(watchDirs, {\n ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50\n }\n });\n\n const handleChange = async (absolutePath: string, event: 'add' | 'change' | 'unlink') =>\n {\n // Convert absolute path to relative path for pattern matching\n const filePath = relative(this.cwd, absolutePath);\n\n if (this.isGenerating)\n {\n this.pendingRegenerations.add(absolutePath);\n return;\n }\n\n this.isGenerating = true;\n this.pendingRegenerations.clear();\n\n if (this.debug)\n {\n orchestratorLogger.info(`File ${event}`, { file: filePath });\n }\n\n // Find matching generators\n for (const generator of this.generators)\n {\n const matches = generator.watchPatterns.some(pattern =>\n mm.isMatch(filePath, pattern)\n );\n\n if (matches)\n {\n try\n {\n if (generator.onFileChange)\n {\n // Use custom handler\n await generator.onFileChange(filePath, event);\n }\n else\n {\n // Fallback to full regeneration\n const genOptions: GeneratorOptions = {\n cwd: this.cwd,\n debug: this.debug\n };\n await generator.generate(genOptions);\n }\n\n if (this.debug)\n {\n orchestratorLogger.info(`[${generator.name}] Regenerated`);\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n orchestratorLogger.error(`[${generator.name}] Regeneration failed`, err);\n }\n }\n }\n\n this.isGenerating = false;\n\n // Process pending regenerations\n if (this.pendingRegenerations.size > 0)\n {\n const next = Array.from(this.pendingRegenerations)[0];\n await handleChange(next, 'change');\n }\n };\n\n watcher\n .on('add', (path) => handleChange(path, 'add'))\n .on('change', (path) => handleChange(path, 'change'))\n .on('unlink', (path) => handleChange(path, 'unlink'));\n\n // Cleanup on exit\n process.on('SIGINT', () =>\n {\n if (this.debug)\n {\n orchestratorLogger.info('Shutting down watch mode');\n }\n watcher.close();\n process.exit(0);\n });\n\n // Keep process alive\n await new Promise(() => {});\n }\n}\n","/**\n * Contract Generator\n *\n * Generates type-safe API client from contract definitions\n */\n\nimport { join } from 'path';\nimport type { Generator, GeneratorOptions } from '../generator.js';\nimport { scanContracts } from '../contract-scanner.js';\nimport { generateClient } from '../client-generator.js';\nimport { logger } from '../../logger';\n\nconst contractLogger = logger.child('contract-gen');\n\nexport interface ContractGeneratorConfig\n{\n /** Routes directory (default: src/server/routes) */\n routesDir?: string;\n\n /** Output path (default: src/lib/api.ts) */\n outputPath?: string;\n\n /** Base URL for API client */\n baseUrl?: string;\n}\n\nexport function createContractGenerator(config: ContractGeneratorConfig = {}): Generator\n{\n return {\n name: 'contract',\n watchPatterns: [config.routesDir ?? 'src/server/routes/**/*.ts'],\n\n async generate(options: GeneratorOptions): Promise<void>\n {\n const cwd = options.cwd;\n const routesDir = config.routesDir ?? join(cwd, 'src', 'server', 'routes');\n const outputPath = config.outputPath ?? join(cwd, 'src', 'lib', 'api.ts');\n\n try\n {\n // Scan contracts\n const contracts = await scanContracts(routesDir);\n\n if (contracts.length === 0)\n {\n if (options.debug)\n {\n contractLogger.warn('No contracts found');\n }\n return;\n }\n\n // Generate client\n const stats = await generateClient(contracts, {\n routesDir,\n outputPath,\n baseUrl: config.baseUrl,\n includeTypes: true,\n includeJsDoc: true\n });\n\n if (options.debug)\n {\n contractLogger.info('Client generated', {\n endpoints: stats.methodsGenerated,\n resources: stats.resourcesGenerated,\n duration: stats.duration\n });\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n contractLogger.error('Generation failed', err);\n throw err;\n }\n }\n };\n}","/**\n * Codegen Configuration Loader\n *\n * Loads codegen configuration from .spfnrc.json or package.json\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { createJiti } from 'jiti';\nimport type { Generator } from './generator.js';\nimport { createContractGenerator, type ContractGeneratorConfig } from './generators/contract-generator.js';\nimport { logger } from '../logger';\n\nconst configLogger = logger.child('config');\n\nexport interface CodegenConfig\n{\n generators?: Array<\n | { path: string } // Custom generator via file path\n | ({ name: 'contract' } & ContractGeneratorConfig & { enabled?: boolean }) // Built-in contract generator\n >;\n}\n\n/**\n * Load codegen configuration from .spfnrc.json or package.json\n */\nexport function loadCodegenConfig(cwd: string): CodegenConfig\n{\n // 1. Check .spfnrc.json\n const rcPath = join(cwd, '.spfnrc.json');\n if (existsSync(rcPath))\n {\n try\n {\n const content = readFileSync(rcPath, 'utf-8');\n const config = JSON.parse(content);\n\n if (config.codegen)\n {\n configLogger.info('Loaded config from .spfnrc.json');\n return config.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse .spfnrc.json', error as Error);\n }\n }\n\n // 2. Check package.json\n const pkgPath = join(cwd, 'package.json');\n if (existsSync(pkgPath))\n {\n try\n {\n const content = readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n\n if (pkg.spfn?.codegen)\n {\n configLogger.info('Loaded config from package.json');\n return pkg.spfn.codegen as CodegenConfig;\n }\n }\n catch (error)\n {\n configLogger.warn('Failed to parse package.json', error as Error);\n }\n }\n\n // 3. Default configuration\n configLogger.info('Using default config');\n return {\n generators: [\n { name: 'contract', enabled: true }\n ]\n };\n}\n\n/**\n * Create generator instances from configuration\n */\nexport async function createGeneratorsFromConfig(config: CodegenConfig, cwd: string): Promise<Generator[]>\n{\n const generators: Generator[] = [];\n\n if (!config.generators || config.generators.length === 0)\n {\n return generators;\n }\n\n for (const generatorConfig of config.generators)\n {\n try\n {\n // Custom generator (via file path)\n if ('path' in generatorConfig)\n {\n const generatorPath = generatorConfig.path.startsWith('.')\n ? join(cwd, generatorConfig.path)\n : generatorConfig.path;\n\n configLogger.info(`Loading custom generator: ${generatorPath}`);\n\n let module: any;\n\n // Use jiti for .ts files, regular import for .js\n if (generatorPath.endsWith('.ts'))\n {\n const jiti = createJiti(cwd, {\n interopDefault: true\n });\n module = jiti(generatorPath);\n }\n else\n {\n module = await import(generatorPath);\n }\n\n const createGenerator = module.default || module.createGenerator || module;\n\n if (typeof createGenerator === 'function')\n {\n const generator = createGenerator();\n generators.push(generator);\n configLogger.info(`Custom generator loaded: ${generator.name}`);\n }\n else\n {\n configLogger.warn(`Invalid generator at ${generatorPath}: expected function`);\n }\n }\n // Built-in contract generator\n else if ('name' in generatorConfig && generatorConfig.name === 'contract')\n {\n if (generatorConfig.enabled !== false)\n {\n const contractConfig: ContractGeneratorConfig = {\n routesDir: generatorConfig.routesDir,\n outputPath: generatorConfig.outputPath,\n baseUrl: generatorConfig.baseUrl\n };\n\n generators.push(createContractGenerator(contractConfig));\n configLogger.info('Contract generator enabled');\n }\n }\n }\n catch (error)\n {\n const err = error instanceof Error ? error : new Error(String(error));\n configLogger.error('Failed to load generator', err);\n }\n }\n\n return generators;\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spfn/core",
3
- "version": "0.1.0-alpha.41",
3
+ "version": "0.1.0-alpha.42",
4
4
  "description": "SPFN Framework Core - File-based routing, transactions, repository pattern",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",