asaihost-nodejs 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -25
- package/dist/InterventionLog-CRP6YJVM.cjs +30 -0
- package/dist/{InterventionLog-25EHE4QR.cjs.map → InterventionLog-CRP6YJVM.cjs.map} +1 -1
- package/dist/{InterventionLog-R6CCPU2B.es.js → InterventionLog-PZT2CCN3.es.js} +5 -5
- package/dist/LogStore-7MTUQA4G.cjs +54 -0
- package/dist/{LogStore-M2AUBNGO.cjs.map → LogStore-7MTUQA4G.cjs.map} +1 -1
- package/dist/{LogStore-ECXX34WC.es.js → LogStore-Q35YFNAY.es.js} +3 -3
- package/dist/asaihost-nodejs.cjs +1296 -1410
- package/dist/asaihost-nodejs.cjs.map +1 -1
- package/dist/asaihost-nodejs.d.cts +154 -17
- package/dist/asaihost-nodejs.d.ts +154 -17
- package/dist/asaihost-nodejs.es.js +911 -1025
- package/dist/asaihost-nodejs.es.js.map +1 -1
- package/dist/{chunk-HHPGUJ75.cjs → chunk-2BCIIKRG.cjs} +13 -6
- package/dist/chunk-2BCIIKRG.cjs.map +1 -0
- package/dist/{chunk-G4WVDUBH.cjs → chunk-4E7Z5K5U.cjs} +7 -7
- package/dist/{chunk-G4WVDUBH.cjs.map → chunk-4E7Z5K5U.cjs.map} +1 -1
- package/dist/{chunk-DROOHKB3.es.js → chunk-57UQJKSL.es.js} +2 -2
- package/dist/{chunk-EOGZPRML.es.js → chunk-A5CDJGJI.es.js} +224 -39
- package/dist/chunk-A5CDJGJI.es.js.map +1 -0
- package/dist/{chunk-E7V3EBDB.es.js → chunk-A6VJPLDD.es.js} +5 -3
- package/dist/chunk-A6VJPLDD.es.js.map +1 -0
- package/dist/{chunk-X7VHW2TD.cjs → chunk-H3K33HBA.cjs} +249 -64
- package/dist/chunk-H3K33HBA.cjs.map +1 -0
- package/dist/{chunk-KOFCBB3N.cjs → chunk-K2QPSQEV.cjs} +9 -9
- package/dist/{chunk-KOFCBB3N.cjs.map → chunk-K2QPSQEV.cjs.map} +1 -1
- package/dist/{chunk-LOMSUPPU.es.js → chunk-LTEP4XB2.es.js} +6 -6
- package/dist/{chunk-QWVR2HNT.cjs → chunk-LXJMGLKW.cjs} +21 -19
- package/dist/chunk-LXJMGLKW.cjs.map +1 -0
- package/dist/{chunk-4WJDC4M4.es.js → chunk-NLZNIGNF.es.js} +2 -2
- package/dist/chunk-NLZNIGNF.es.js.map +1 -0
- package/dist/{chunk-W7DVKGX5.cjs → chunk-OCEBEEP5.cjs} +2 -2
- package/dist/{chunk-W7DVKGX5.cjs.map → chunk-OCEBEEP5.cjs.map} +1 -1
- package/dist/{chunk-NLBFIRDB.cjs → chunk-RIRKIYET.cjs} +12 -12
- package/dist/{chunk-NLBFIRDB.cjs.map → chunk-RIRKIYET.cjs.map} +1 -1
- package/dist/{chunk-XBIN4C2V.es.js → chunk-SB23ESX2.es.js} +2 -2
- package/dist/{chunk-VLMM735Q.cjs → chunk-TKJAHTPO.cjs} +26 -26
- package/dist/{chunk-VLMM735Q.cjs.map → chunk-TKJAHTPO.cjs.map} +1 -1
- package/dist/{chunk-MCMADJQR.es.js → chunk-VUZO7DCA.es.js} +4 -4
- package/dist/chunk-VUZO7DCA.es.js.map +1 -0
- package/dist/{chunk-KUZQ36IJ.es.js → chunk-ZQBHJRAO.es.js} +10 -3
- package/dist/chunk-ZQBHJRAO.es.js.map +1 -0
- package/dist/intervention-hooks-KF3SNB5Q.cjs +21 -0
- package/dist/{intervention-hooks-LE6X4C6N.cjs.map → intervention-hooks-KF3SNB5Q.cjs.map} +1 -1
- package/dist/{intervention-hooks-FI4EHOL5.es.js → intervention-hooks-TCGIC4IV.es.js} +6 -6
- package/dist/log-formats-TUXGMCCU.cjs +31 -0
- package/dist/{log-formats-FKFMQKNO.cjs.map → log-formats-TUXGMCCU.cjs.map} +1 -1
- package/dist/{log-formats-I5E32H5F.es.js → log-formats-WW3TDUAK.es.js} +2 -2
- package/dist/{password-63OY27RX.es.js → password-4BABWAG4.es.js} +4 -4
- package/dist/password-PJHJRGPE.cjs +20 -0
- package/dist/{password-NZ5EGDWG.cjs.map → password-PJHJRGPE.cjs.map} +1 -1
- package/dist/user-store-6J2PSEIN.cjs +12 -0
- package/dist/{user-store-SX4N6PQ4.cjs.map → user-store-6J2PSEIN.cjs.map} +1 -1
- package/dist/user-store-UC5URX3C.es.js +12 -0
- package/package.json +2 -13
- package/dist/InterventionLog-25EHE4QR.cjs +0 -30
- package/dist/LogStore-M2AUBNGO.cjs +0 -54
- package/dist/chunk-4WJDC4M4.es.js.map +0 -1
- package/dist/chunk-E7V3EBDB.es.js.map +0 -1
- package/dist/chunk-EOGZPRML.es.js.map +0 -1
- package/dist/chunk-HHPGUJ75.cjs.map +0 -1
- package/dist/chunk-KUZQ36IJ.es.js.map +0 -1
- package/dist/chunk-MCMADJQR.es.js.map +0 -1
- package/dist/chunk-QWVR2HNT.cjs.map +0 -1
- package/dist/chunk-X7VHW2TD.cjs.map +0 -1
- package/dist/intervention-hooks-LE6X4C6N.cjs +0 -21
- package/dist/log-formats-FKFMQKNO.cjs +0 -31
- package/dist/password-NZ5EGDWG.cjs +0 -20
- package/dist/user-store-J7LWEXSW.es.js +0 -12
- package/dist/user-store-SX4N6PQ4.cjs +0 -12
- /package/dist/{InterventionLog-R6CCPU2B.es.js.map → InterventionLog-PZT2CCN3.es.js.map} +0 -0
- /package/dist/{LogStore-ECXX34WC.es.js.map → LogStore-Q35YFNAY.es.js.map} +0 -0
- /package/dist/{chunk-DROOHKB3.es.js.map → chunk-57UQJKSL.es.js.map} +0 -0
- /package/dist/{chunk-LOMSUPPU.es.js.map → chunk-LTEP4XB2.es.js.map} +0 -0
- /package/dist/{chunk-XBIN4C2V.es.js.map → chunk-SB23ESX2.es.js.map} +0 -0
- /package/dist/{intervention-hooks-FI4EHOL5.es.js.map → intervention-hooks-TCGIC4IV.es.js.map} +0 -0
- /package/dist/{log-formats-I5E32H5F.es.js.map → log-formats-WW3TDUAK.es.js.map} +0 -0
- /package/dist/{password-63OY27RX.es.js.map → password-4BABWAG4.es.js.map} +0 -0
- /package/dist/{user-store-J7LWEXSW.es.js.map → user-store-UC5URX3C.es.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/core/network.ts","../src/core/host-config.ts","../src/infra/process.ts","../src/infra/logger.ts","../src/ws/route-index.ts","../src/infra/registry.ts","../src/infra/security-audit.ts","../src/infra/crypto-compliance.ts","../src/infra/ntp-check.ts","../src/infra/config-integrity.ts","../src/core/init.ts","../src/http/server.ts","../src/ws/server.ts","../src/ws/auth.ts","../src/utils/userinfo.ts","../src/ws/message.ts","../src/infra/connection-quota.ts","../src/http/static-path-cache.ts","../src/http/security.ts","../src/http/log.ts","../src/http/static.ts","../src/infra/safe-path.ts","../src/http/server-paths.ts","../src/http/connection.ts","../src/infra/port-release.ts","../src/proxy/server.ts","../src/utils/index.ts","../src/utils/ws-mock.ts","../src/infra/user-auth.ts","../src/infra/access-control.ts","../src/infra/host-limits.ts","../src/common/server/Api.ts","../src/common/server/Ws.ts","../src/common/server/Sys.ts","../src/common/server/WsClient.ts","../src/common/Index.ts","../src/sysserver/ws/common/ping.ts","../src/sysserver/ws/chat/web.ts","../src/sysserver/ws/index.ts","../src/sysserver/api/common/logmanage.ts","../src/infra/siem-auth.ts","../src/sysserver/api/common/interventionlog.ts","../src/sysserver/api/common/unifiedlog.ts","../src/sysserver/lib/common/ErrorCode.ts","../src/sysserver/api/common/errorcodes.ts","../src/sysserver/api/common/sqlitemanage.ts","../src/sysserver/api/common/health.ts","../src/infra/input-sanitize.ts","../src/sysserver/api/login/service/session.ts","../src/sysserver/api/login/service/rbac.ts","../src/sysserver/api/login/index.ts","../src/sysserver/api/index.ts","../src/sysserver/lib/common/As.ts","../src/sysserver/lib/common/AsCode.ts","../src/sysserver/lib/common/AsAES.ts","../src/sysserver/lib/common/AsDb.ts","../src/sysserver/lib/common/reqWork.ts","../src/sysserver/lib/common/AsFs.ts","../src/sysserver/lib/common/AsPath.ts","../src/sysserver/lib/index.ts","../src/sysserver/db/src/common.ts","../src/sysserver/db/src/Sql.ts","../src/sysserver/db/src/mysql/Index.ts","../src/sysserver/db/src/sqlite/Index.ts","../src/sysserver/db/src/file/Index.ts","../src/sysserver/db/db.ts","../src/sysserver/index.ts","../src/config/validate.ts","../src/config/syscom.ts","../src/infra/transport-bridge.ts","../src/types.ts","../index.ts"],"sourcesContent":["/**\r\n * index.ts — AsaiHost 插件入口\r\n *\r\n * 启动流程:注册 sys/api/ws/jsonp 处理器 → 按 hosts 配置拉起 HTTP/WS → 按 proxyhosts 拉起反向代理。\r\n * workHandlers 使用模块级 Map,避免 global 污染且支持多实例。\r\n */\r\nimport * as ws from \"ws\";\r\nimport { initAsaiHost, validateHostdir } from \"./core\";\r\nimport { startHTTPServer } from \"./http/server\";\r\nimport { startProxyServer } from \"./proxy/server\";\r\nimport { releaseConfiguredPorts } from \"./infra/port-release\";\r\n\r\n/** 业务处理器注册表(sysWork / apiWork / wsWork / jsonpWork) */\r\nconst workHandlers = new Map<string, Function>();\r\nexport function getWorkHandler(name: string): Function | undefined {\r\n return workHandlers.get(name);\r\n}\r\n\r\nexport default function ($asai: any, opt: any) {\r\n // [优化] 将处理器存入模块级 Map,而非挂载到 global\r\n workHandlers.set(\"sysWork\", opt.sysWork);\r\n workHandlers.set(\"apiWork\", opt.apiWork);\r\n workHandlers.set(\"wsWork\", opt.wsWork);\r\n workHandlers.set(\"jsonpWork\", opt.jsonpWork);\r\n\r\n function StartAsaiHost(): void {\r\n initAsaiHost($asai, opt);\r\n\r\n console.log(`※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※`);\r\n\r\n releaseConfiguredPorts($asai);\r\n\r\n if ($asai.hostconfig?.hosts) {\r\n $asai.startHTTPServer = (hostdir: string) =>\r\n startHTTPServer($asai, hostdir);\r\n Object.keys($asai.hostconfig.hosts).forEach((el: string) => {\r\n if (validateHostdir(el)) {\r\n startHTTPServer($asai, el);\r\n }\r\n });\r\n // asai 被 validateHostdir 排除,需显式启动(9199 主站);default 仅作模板不单独监听\r\n if ($asai.hostconfig.hosts.asai) {\r\n startHTTPServer($asai, \"asai\");\r\n }\r\n }\r\n\r\n if ($asai.hostconfig?.proxyhosts) {\r\n Object.keys($asai.hostconfig.proxyhosts).forEach((el: string) => {\r\n if (validateHostdir(el)) {\r\n startProxyServer($asai, el);\r\n }\r\n });\r\n }\r\n }\r\n\r\n return { StartAsaiHost, asaiWs: ws };\r\n}\r\n","/** 网络工具 — 本机 IP 探测与绑定地址解析 */\r\nimport * as os from 'os';\r\n\r\nexport function getIp(): string {\r\n\ttry {\r\n\t\tconst interfaces = os.networkInterfaces();\r\n\t\tfor (const name of Object.keys(interfaces)) {\r\n\t\t\tconst iface = interfaces[name];\r\n\t\t\tif (!iface) continue;\r\n\t\t\tfor (const alias of iface) {\r\n\t\t\t\tif (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {\r\n\t\t\t\t\treturn alias.address;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} catch (err) {\r\n\t\tconsole.error('Get IP address error:', err);\r\n\t}\r\n\treturn '127.0.0.1';\r\n}\r\n\r\nexport function getHostIP(ip?: string | null, $asai?: any): string {\r\n\tif (ip && typeof ip === 'string') return ip;\r\n\tif ($asai?.hostconfig?.ip === 'asai') return 'localhost';\r\n\treturn $asai?.hostconfig?.ip || '127.0.0.1';\r\n}\r\n","/** 主机/代理配置合并与缓存 — 启动后配置不变,进程级缓存 */\r\nimport { getHostIP } from './network';\r\n\r\nconst hostCfgCache = new Map<string, any>();\r\nconst proxyHostCfgCache = new Map<string, any>();\r\n\r\nexport function validateHostdir(hostdir: string): boolean {\r\n\tif (typeof hostdir !== 'string' || hostdir.length === 0 || hostdir.length > 100 || hostdir === 'default' || hostdir === 'asai') {\r\n\t\treturn false;\r\n\t}\r\n\treturn /^[a-zA-Z0-9_-]+$/.test(hostdir);\r\n}\r\n\r\nfunction loadHostCFG(hostdir: string, $asai: any): any {\r\n\tlet base = hostCfgCache.get(hostdir);\r\n\tif (!base) {\r\n\t\tconst defaultCfg = $asai.hostconfig.hosts.default || {};\r\n\t\tconst hostCfg = $asai.hostconfig.hosts[hostdir] || {};\r\n\t\tbase = { ...defaultCfg, ...hostCfg };\r\n\t\thostCfgCache.set(hostdir, base);\r\n\t}\r\n\treturn base;\r\n}\r\n\r\n/** 返回浅拷贝,避免调用方修改污染缓存 */\r\nexport function getHostCFG(hostdir: string, $asai: any): any {\r\n\treturn { ...loadHostCFG(hostdir, $asai) };\r\n}\r\n\r\nfunction loadProxyHostCFG(proxyhostdir: string, $asai: any): any {\r\n\tlet base = proxyHostCfgCache.get(proxyhostdir);\r\n\tif (!base) {\r\n\t\tconst defaultCfg = $asai.hostconfig.proxyhosts?.default || {};\r\n\t\tconst proxyCfg = $asai.hostconfig.proxyhosts?.[proxyhostdir] || {};\r\n\t\tbase = { ...defaultCfg, ...proxyCfg };\r\n\t\tif (!base.url && base.port) {\r\n\t\t\tbase.url = (base.httptype || 'http://') + getHostIP(base.ip, $asai) + ':' + base.port;\r\n\t\t}\r\n\t\tproxyHostCfgCache.set(proxyhostdir, base);\r\n\t}\r\n\treturn base;\r\n}\r\n\r\nexport function getProxyHostCFG(proxyhostdir: string, $asai: any): any {\r\n\treturn { ...loadProxyHostCFG(proxyhostdir, $asai) };\r\n}\r\n","/**\r\n * process.ts — 进程级异常守护与优雅退出\r\n *\r\n * - uncaughtException:记录日志并按窗口限流,超限则 gracefulShutdown\r\n * - unhandledRejection:记录完整堆栈\r\n * - SIGTERM/SIGINT:关闭 HTTP/WS 后退出\r\n */\r\nexport function initProcess($asai: any, cb?: ((err: Error) => void) | null): void {\r\n const MAX_RESTARTS = $asai?.hostconfig?.tm?.maxtry || 10;\r\n const RESTART_WINDOW = $asai?.hostconfig?.tm?.restartwindow || 60000;\r\n const restartTimes: number[] = [];\r\n\r\n // uncaughtExceptionMonitor: 主 handler 崩溃时兜底记录,永不退出\r\n if (process.on && typeof process.on === 'function' && 'uncaughtExceptionMonitor' in process) {\r\n process.on('uncaughtExceptionMonitor', (err: Error) => {\r\n try {\r\n $asai.$log('FATAL', `Monitor caught: ${err?.message || err}`);\r\n } catch {\r\n /* ignore */\r\n }\r\n });\r\n }\r\n\r\n process.on('unhandledRejection', (reason: unknown, promise: Promise<unknown>) => {\r\n const stackTrace = new Error().stack;\r\n let promiseInfo = '';\r\n if (promise && typeof promise === 'object') {\r\n promiseInfo = promise.constructor?.name || 'Promise';\r\n const stackLines = stackTrace?.split('\\n') || [];\r\n const relevantStack = stackLines.slice(3, 6).join(' | ');\r\n promiseInfo += ` Created at: ${relevantStack}`;\r\n }\r\n\r\n let reasonInfo = '';\r\n if (reason instanceof Error) {\r\n reasonInfo = `\\n${reason.name}: ${reason.message}`;\r\n if (reason.stack) reasonInfo += `\\n【Stack】${reason.stack}`;\r\n } else if (typeof reason === 'object' && reason !== null) {\r\n try {\r\n reasonInfo = JSON.stringify(reason, null, 2).substring(0, 500);\r\n } catch {\r\n reasonInfo = String(reason);\r\n }\r\n } else {\r\n reasonInfo = String(reason);\r\n }\r\n\r\n const errorMsg = `Unhandled Promise Rejection:\\n【Reason】 ${reasonInfo}\\n【Promise】${promiseInfo}`;\r\n $asai.$log('UNHANDLED_REJECTION', errorMsg);\r\n });\r\n\r\n process.on('uncaughtException', (err: Error) => {\r\n const errorMsg = `Uncaught Exception: ${JSON.stringify(err)}`;\r\n try {\r\n $asai.$log('UNCAUGHT_EXCEPTIONS', errorMsg);\r\n } catch {\r\n /* $log itself threw */\r\n }\r\n\r\n const now = Date.now();\r\n restartTimes.push(now);\r\n while (restartTimes.length > 0 && restartTimes[0] < now - RESTART_WINDOW) {\r\n restartTimes.shift();\r\n }\r\n\r\n if (restartTimes.length > MAX_RESTARTS) {\r\n try {\r\n $asai.$log('NO_RESTART', 'Process crashed too frequently, gracefully shutdown and wait for daemon restart.');\r\n void import('../sysserver/lib/common/intervention-hooks').then(({ logProcessGuardEvent }) =>\r\n logProcessGuardEvent($asai, {\r\n action: 'crash_loop_shutdown',\r\n detail: `${restartTimes.length} crashes in ${RESTART_WINDOW}ms window`,\r\n outcome: 'Failure',\r\n severity: 10,\r\n }),\r\n ).catch(() => undefined);\r\n } catch {\r\n /* $log itself threw */\r\n }\r\n try {\r\n $asai.$log('SHUTDOWN', 'Error:', err?.message || err);\r\n } catch {\r\n /* $log itself threw */\r\n }\r\n gracefulShutdown($asai);\r\n return;\r\n }\r\n\r\n if (cb && typeof cb === 'function') {\r\n try {\r\n cb(err);\r\n } catch (callbackErr) {\r\n console.error('Error in process error callback:', callbackErr);\r\n }\r\n }\r\n });\r\n\r\n process.on('SIGTERM', () => {\r\n try {\r\n $asai.$log('SIGTERM', 'SIGTERM,CLOSING...');\r\n } catch {\r\n /* ignore */\r\n }\r\n gracefulShutdown($asai);\r\n });\r\n\r\n process.on('SIGINT', () => {\r\n try {\r\n $asai.$log('SIGINT', 'SIGINT,CLOSING...');\r\n } catch {\r\n /* ignore */\r\n }\r\n gracefulShutdown($asai);\r\n });\r\n}\r\n\r\nexport function gracefulShutdown($asai: any): void {\r\n void import('../sysserver/lib/common/intervention-hooks').then(({ logProcessGuardEvent }) =>\r\n logProcessGuardEvent($asai, {\r\n action: 'graceful_shutdown',\r\n detail: 'SIGTERM/SIGINT or crash guard triggered',\r\n outcome: 'Success',\r\n }),\r\n ).catch(() => undefined);\r\n\r\n const shutdownTimeout = 60000;\r\n let shutdownTimer: NodeJS.Timeout;\r\n\r\n const startTime = Date.now();\r\n shutdownTimer = setTimeout(() => {\r\n $asai.$log('SHUTDOWN', `Timeout! Exiting after ${Date.now() - startTime}ms`);\r\n process.exit(1);\r\n }, shutdownTimeout);\r\n\r\n try {\r\n Object.values($asai.servershttp || {}).forEach((server: any) => {\r\n if (server && typeof server.close === 'function') {\r\n server.close((err?: Error) => {\r\n if (err) $asai.$log('HTTP', 'HTTP server close error:', err);\r\n });\r\n }\r\n });\r\n\r\n Object.values($asai.serversws || {}).forEach((server: any) => {\r\n if (server && typeof server.close === 'function') {\r\n server.close((err?: Error) => {\r\n if (err) $asai.$log('WS', 'WS server close error:', err);\r\n });\r\n }\r\n });\r\n\r\n if ($asai.hostconfig.guardtm) {\r\n clearTimeout($asai.hostconfig.guardtm);\r\n $asai.hostconfig.guardtm = null;\r\n }\r\n\r\n Object.keys($asai.tasksws || {}).forEach((hostdir) => {\r\n if ($asai.tasksws[hostdir].httpMonitor) {\r\n clearInterval($asai.tasksws[hostdir].httpMonitor);\r\n delete $asai.tasksws[hostdir].httpMonitor;\r\n }\r\n });\r\n\r\n setTimeout(() => {\r\n clearTimeout(shutdownTimer);\r\n $asai.$log('SHUTDOWN', `Web Server Closed (${Date.now() - startTime}ms)`);\r\n process.exit(0);\r\n }, 3000);\r\n } catch (err) {\r\n $asai.$log('SHUTDOWN', 'Graceful shutdown error:', err);\r\n clearTimeout(shutdownTimer);\r\n process.exit(1);\r\n }\r\n}\r\n","/**\r\n * 日志系统 — 带缓冲区异步写入,支持按日轮转\r\n *\r\n * 功能:\r\n * 1. LogBuffer:缓冲区批量写入+定时刷新,避免频繁 I/O\r\n * 2. 按文件大小自动轮转(默认 1MB)\r\n * 3. 进程退出时自动刷新所有缓冲区,防止日志丢失\r\n * 4. 支持控制台显示(view)与文件记录(record)独立开关\r\n */\r\n\r\nimport fs from \"node:fs/promises\";\r\nimport { getNowTime } from \"../core/time\";\r\nimport { mirrorWebLog, mirrorAccessLog } from \"../sysserver/lib/common/LogStore\";\r\nimport {\r\n formatW3CHeader,\r\n formatW3CServerRecord,\r\n W3C_SERVER_FIELDS,\r\n W3C_ACCESS_FIELDS,\r\n parseCLF,\r\n} from \"../sysserver/lib/common/log-formats\";\r\n\r\n/** 全局日志缓冲区实例 Map(key = `${$asai.id}_${src}`) */\r\nconst logBuffers = new Map<string, LogBuffer>();\r\n\r\n/** 进程退出时刷新所有 LogBuffer 实例 */\r\nfunction flushAllLogBuffers(): void {\r\n logBuffers.forEach((buffer) => {\r\n buffer.forceFlush();\r\n });\r\n}\r\n\r\n/**\r\n * 异步日志缓冲区 — 攒批写入文件\r\n * - 满 maxBufferSize 条或超时 flushInterval 自动刷出\r\n * - 进程退出时通过 process.on('beforeExit') 统一刷出全部缓冲区\r\n */\r\nclass LogBuffer {\r\n private buffer: string[] = [];\r\n private timer: ReturnType<typeof setTimeout> | null = null;\r\n private readonly flushInterval = 100; // 攒批超时(ms)\r\n private readonly maxBufferSize = 100; // 单次攒批上限(条)\r\n\r\n /** 全局只注册一次 beforeExit,避免重复订阅 */\r\n private static globalFlushRegistered = false;\r\n\r\n constructor(\r\n private $asai: any,\r\n private filePath: string,\r\n ) {\r\n // 全局只注册一次 beforeExit:统一 flush 所有缓冲区\r\n if (!LogBuffer.globalFlushRegistered) {\r\n LogBuffer.globalFlushRegistered = true;\r\n process.once(\"beforeExit\", () => flushAllLogBuffers());\r\n }\r\n }\r\n\r\n /** 入队一条日志 */\r\n public add(logData: string): void {\r\n this.buffer.push(logData);\r\n\r\n if (this.buffer.length >= this.maxBufferSize) {\r\n this.flush(); // 攒满 → 立即刷出\r\n } else if (!this.timer) {\r\n this.timer = setTimeout(() => this.flush(), this.flushInterval);\r\n }\r\n }\r\n\r\n /** 强制刷出(供外部调用,如进程退出时) */\r\n public forceFlush(): void {\r\n this.flush();\r\n }\r\n\r\n /** 刷出缓冲区 → 异步写入文件(ensureFile 在 flush 时执行,避免每请求 stat) */\r\n private flush(): void {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n if (this.buffer.length === 0) return;\r\n\r\n const logContent = this.buffer.join(\"\");\r\n this.buffer = [];\r\n void this.writeBatch(logContent);\r\n }\r\n\r\n private async writeBatch(logContent: string): Promise<void> {\r\n try {\r\n const { ensureFile } = this.$asai.$lib.AsFs;\r\n await ensureFile(this.filePath);\r\n const stat = await fs.stat(this.filePath);\r\n const maxSize = this.$asai.hostconfig.logger?.path?.maxsize || 1_048_576;\r\n if (stat.size >= maxSize) {\r\n const lastIndex = this.filePath.lastIndexOf(\".\");\r\n const filename = this.filePath.substring(0, lastIndex);\r\n const fileext = this.filePath.substring(lastIndex);\r\n await fs.rename(\r\n this.filePath,\r\n `${filename}-${getNowTime(5)}${fileext}`,\r\n );\r\n }\r\n await fs.appendFile(this.filePath, logContent, \"utf8\");\r\n const src = this.filePath.includes(\"/client/\") || this.filePath.includes(\"\\\\client\\\\\") ? \"client\" : \"server\";\r\n const kind = logContent.includes(\"[SEC-AUDIT]\") ? \"sec\" : src;\r\n void mirrorWebLog(this.$asai, {\r\n source: kind === \"sec\" ? \"sec\" : src,\r\n rawLine: logContent,\r\n }).catch(() => undefined);\r\n } catch (err) {\r\n console.error(\"Log write error:\", err);\r\n }\r\n }\r\n\r\n /** 销毁:清定时器+刷出残余数据 */\r\n public destroy(): void {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n this.flush();\r\n }\r\n}\r\n\r\n/**\r\n * 写入一条日志(通过缓冲区异步写入文件)\r\n * saveLog → LogBuffer.add\r\n */\r\nfunction saveLog($asai: any, src: string, logstr: string): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const bufferKey = `${$asai.id || \"default\"}_${src}`;\r\n let logBuffer = logBuffers.get(bufferKey);\r\n if (!logBuffer) {\r\n logBuffer = new LogBuffer($asai, src);\r\n logBuffers.set(bufferKey, logBuffer);\r\n }\r\n logBuffer.add(logstr);\r\n resolve();\r\n } catch (err) {\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/* eslint-disable @typescript-eslint/no-unused-vars */\r\nfunction newLoggerFile($asai: any, _dateCur: any, logstr: string) {\r\n return formatW3CHeader({\r\n software: $asai.hostconfig.website?.title || \"AsaiHost\",\r\n version: $asai.hostconfig.website?.ver || \"1.0.0.0\",\r\n fields: [...W3C_SERVER_FIELDS],\r\n date: _dateCur,\r\n }) + logstr;\r\n}\r\n/* eslint-enable @typescript-eslint/no-unused-vars */\r\n\r\n/** 新 W3C 日志文件是否已写入头部(按路径缓存) */\r\nconst w3cHeaderWritten = new Set<string>();\r\n\r\nasync function ensureW3CHeader($asai: any, filePath: string, dateCur: Date): Promise<void> {\r\n if (w3cHeaderWritten.has(filePath)) return;\r\n try {\r\n const stat = await fs.stat(filePath);\r\n if (stat.size > 0) {\r\n w3cHeaderWritten.add(filePath);\r\n return;\r\n }\r\n } catch {\r\n /* 文件不存在,继续写头 */\r\n }\r\n const header = formatW3CHeader({\r\n software: $asai.hostconfig.website?.title || \"AsaiHost\",\r\n version: $asai.hostconfig.website?.ver || \"1.0.0.0\",\r\n fields: [...W3C_SERVER_FIELDS],\r\n date: dateCur,\r\n });\r\n await fs.appendFile(filePath, header, \"utf8\");\r\n w3cHeaderWritten.add(filePath);\r\n}\r\n\r\n/**\r\n * 每个日志文件的轮转元信息缓存。\r\n * 性能关键:避免每条日志都执行 ensureFile + stat(两次磁盘 I/O),\r\n * 改为按字节累加估算大小 + 周期性 stat 校准,I/O 从「每行 2 次」降到「每文件每隔数秒 1 次」。\r\n */\r\ninterface LogFileMeta {\r\n ensured: boolean; // 文件是否已确保存在\r\n size: number; // 当前大小(字节,写入时累加估算)\r\n lastStatMs: number; // 上次 stat 校准时间戳\r\n}\r\nconst logFileMeta = new Map<string, LogFileMeta>();\r\n/** stat 校准最小间隔(ms):两次校准之间用累加字节判断轮转 */\r\nconst STAT_REFRESH_INTERVAL = 5000;\r\n\r\n/**\r\n * 追加日志(外部接口)\r\n * - 自动确保文件存在\r\n * - 超 maxsize(默认 1MB)自动轮转 + 重命名\r\n * - 仅在文件未确保或超过校准间隔时才触碰磁盘元信息,其余时间走内存累加\r\n */\r\nexport async function setAppend(\r\n $asai: any,\r\n src: string,\r\n logstr: string,\r\n): Promise<void> {\r\n try {\r\n const maxSize = $asai.hostconfig.logger?.path?.maxsize || 1_048_576;\r\n let meta = logFileMeta.get(src);\r\n const now = Date.now();\r\n\r\n // 首次写入或到达校准窗口:确保文件存在并以真实大小校准缓存\r\n if (\r\n !meta ||\r\n !meta.ensured ||\r\n now - meta.lastStatMs >= STAT_REFRESH_INTERVAL\r\n ) {\r\n const { ensureFile } = $asai.$lib.AsFs;\r\n await ensureFile(src);\r\n const stat = await fs.stat(src);\r\n meta = { ensured: true, size: stat.size, lastStatMs: now };\r\n logFileMeta.set(src, meta);\r\n }\r\n\r\n // 大小达到阈值则轮转:重命名旧文件,重置缓存(下次写入会重新 ensureFile)\r\n if (meta.size >= maxSize) {\r\n const dateCur: any = new Date();\r\n const lastIndex = src.lastIndexOf(\".\");\r\n const filename = src.substring(0, lastIndex);\r\n const fileext = src.substring(lastIndex);\r\n await fs.rename(src, `${filename}-${getNowTime(5, dateCur)}${fileext}`);\r\n meta.ensured = false;\r\n meta.size = 0;\r\n }\r\n\r\n // 内存累加估算大小,避免下次写入再次 stat\r\n meta.size += Buffer.byteLength(logstr);\r\n await saveLog($asai, src, logstr);\r\n } catch (err) {\r\n console.error(err);\r\n // 出错时让该文件下次重新校准\r\n logFileMeta.delete(src);\r\n }\r\n}\r\n\r\n/** CLF + W3C Extended 访问日志双写(HTTP 响应完成时调用) */\r\nexport async function appendAccessLog($asai: any, clfLine: string, w3cLine: string): Promise<void> {\r\n const accessDir = $asai.hostconfig.logger?.path?.access;\r\n if (!accessDir) return;\r\n const dateCur = new Date();\r\n const dateStr = getNowTime(2, dateCur);\r\n const clfPath = `${accessDir}access-clf-${dateStr}.log`;\r\n const w3cPath = `${accessDir}access-w3c-${dateStr}.log`;\r\n\r\n try {\r\n const { ensureFile } = $asai.$lib.AsFs;\r\n await ensureFile(clfPath);\r\n await fs.appendFile(clfPath, clfLine, \"utf8\");\r\n await ensureW3CAccessHeader($asai, w3cPath, dateCur);\r\n await fs.appendFile(w3cPath, w3cLine, \"utf8\");\r\n const clfParsed = parseCLF(clfLine);\r\n void mirrorAccessLog($asai, {\r\n format: 'clf',\r\n rawLine: clfLine,\r\n host: clfParsed?.host as string,\r\n method: clfParsed?.method as string,\r\n url: clfParsed?.url as string,\r\n status: clfParsed?.status as number,\r\n }).catch(() => undefined);\r\n void mirrorAccessLog($asai, {\r\n format: 'w3c',\r\n rawLine: w3cLine,\r\n }).catch(() => undefined);\r\n } catch (err) {\r\n console.error(\"Access log write error:\", err);\r\n }\r\n}\r\n\r\nconst w3cAccessHeaderWritten = new Set<string>();\r\n\r\nasync function ensureW3CAccessHeader($asai: any, filePath: string, dateCur: Date): Promise<void> {\r\n if (w3cAccessHeaderWritten.has(filePath)) return;\r\n try {\r\n const stat = await fs.stat(filePath);\r\n if (stat.size > 0) {\r\n w3cAccessHeaderWritten.add(filePath);\r\n return;\r\n }\r\n } catch {\r\n /* 新文件 */\r\n }\r\n const header = formatW3CHeader({\r\n software: $asai.hostconfig.website?.title || \"AsaiHost\",\r\n version: $asai.hostconfig.website?.ver || \"1.0.0.0\",\r\n fields: [...W3C_ACCESS_FIELDS],\r\n date: dateCur,\r\n });\r\n await fs.appendFile(filePath, header, \"utf8\");\r\n w3cAccessHeaderWritten.add(filePath);\r\n}\r\n\r\n/** 同步风格日志写入(包装 setAppend) */\r\nexport function setLog($asai: any, src: string, logstr: string): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n setAppend($asai, src, logstr).then(resolve).catch(reject);\r\n } catch (err) {\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 初始化日志系统\r\n * - 挂载 $asai.$log 函数\r\n * - $asai.hostconfig.logger.lv.record ? llog(写文件) : xlog(仅控制台)\r\n * - 参数 0 / 不传:服务端日志(自动加时间戳);参数 1:客户端日志\r\n * - 参数 > 666:静默日志(仅记录,控制台不输出)\r\n */\r\nexport function initLog($asai: any): void {\r\n /** 控制台输出(受 lv.view 开关控制) */\r\n function clog(...args: any[]): void {\r\n if ($asai.hostconfig.logger?.lv?.view) {\r\n console.log(...args);\r\n }\r\n }\r\n\r\n function formatArg(item: any): string {\r\n if (item instanceof Error) return item.message || String(item);\r\n if (typeof item === \"object\") {\r\n try {\r\n return JSON.stringify(item);\r\n } catch {\r\n return String(item);\r\n }\r\n }\r\n return String(item);\r\n }\r\n\r\n /** 高频日志采样(logger.sample.REQ_OTHER = 0.05 表示约 5% 记录) */\r\n function shouldSample(args: any[]): boolean {\r\n const sample = $asai.hostconfig.logger?.sample;\r\n if (!sample || typeof sample !== \"object\") return true;\r\n const typeArg = args.find((a) => typeof a === \"string\");\r\n if (!typeArg || sample[typeArg] == null) return true;\r\n const rate = Number(sample[typeArg]);\r\n if (Number.isNaN(rate) || rate >= 1) return true;\r\n if (rate <= 0) return false;\r\n return Math.random() < rate;\r\n }\r\n\r\n function enqueueServerLog(logType: string, method: string | undefined, url: string | undefined, message: string, dateCur: Date): void {\r\n const filePath = `${$asai.hostconfig.logger.path.server}log-${getNowTime(2, dateCur)}.txt`;\r\n const logstr = formatW3CServerRecord({\r\n date: dateCur,\r\n logType,\r\n method,\r\n url,\r\n message,\r\n });\r\n void (async () => {\r\n try {\r\n await ensureW3CHeader($asai, filePath, dateCur);\r\n await saveLog($asai, filePath, logstr);\r\n } catch (err) {\r\n console.error(\"Log enqueue error:\", err);\r\n }\r\n })();\r\n }\r\n\r\n /** 仅控制台日志(record=false 走此分支) */\r\n function xlog(...args: any[]): void {\r\n clog(...args);\r\n }\r\n\r\n /** 完整日志:控制台 + 异步缓冲写文件(不 await,避免阻塞请求) */\r\n function llog(...args: any[]): void {\r\n if (!shouldSample(args)) return;\r\n\r\n const dateCur = new Date();\r\n const argType = args[0];\r\n\r\n if (argType === 1) {\r\n if ($asai.hostconfig.logger?.path?.client) {\r\n const logMsg = args.slice(1).map(formatArg).join(\"\\n\");\r\n const logstr = formatW3CServerRecord({\r\n date: dateCur,\r\n logType: \"CLIENT\",\r\n message: logMsg,\r\n });\r\n clog(`[${getNowTime(3, dateCur)}]\\n${logMsg}\\n`);\r\n const filePath = `${$asai.hostconfig.logger.path.client}log-${getNowTime(2, dateCur)}.txt`;\r\n void (async () => {\r\n try {\r\n await ensureW3CHeader($asai, filePath, dateCur);\r\n await saveLog($asai, filePath, logstr);\r\n } catch (err) {\r\n console.error(\"Log enqueue error:\", err);\r\n }\r\n })();\r\n }\r\n return;\r\n }\r\n\r\n const logType = typeof argType === \"string\" ? argType : \"LOG\";\r\n const restArgs = typeof argType === \"number\" && argType > 666 ? args.slice(1) : args.slice(1);\r\n const message = restArgs.map(formatArg).join(\"; \").replace(/[\\n\\r]/g, \" \");\r\n let method: string | undefined;\r\n let url: string | undefined;\r\n if (typeof restArgs[0] === \"string\" && typeof restArgs[1] === \"string\") {\r\n method = restArgs[0];\r\n url = restArgs[1];\r\n }\r\n\r\n if (typeof argType === \"number\" && argType > 666) {\r\n if ($asai.hostconfig.logger?.path?.server) {\r\n enqueueServerLog(logType, method, url, message, dateCur);\r\n }\r\n } else if ($asai.hostconfig.logger?.path?.server) {\r\n const consoleLine = `[${getNowTime(3, dateCur)}] ${message}\\n`;\r\n clog(consoleLine);\r\n enqueueServerLog(logType, method, url, message, dateCur);\r\n }\r\n }\r\n\r\n if (\r\n $asai &&\r\n typeof $asai === \"object\" &&\r\n $asai.hostconfig.logger?.lv?.record\r\n ) {\r\n $asai.$log = llog;\r\n } else {\r\n $asai.$log = xlog;\r\n }\r\n}\r\n","/**\r\n * WS 路由前缀索引 — 最长前缀匹配,替代 hostserverwss.find() 线性扫描\r\n */\r\nconst NON_ROUTE_KEYS = new Set(['wsWork', 'commandwork']);\r\n\r\nexport class WsRouteIndex {\r\n\tprivate routes: string[] = [];\r\n\r\n\trebuild(keys: string[]): void {\r\n\t\tthis.routes = keys.filter((k) => k && !NON_ROUTE_KEYS.has(k)).sort((a, b) => b.length - a.length);\r\n\t}\r\n\r\n\tmatchTy(ty: string | undefined): string | undefined {\r\n\t\tif (!ty || typeof ty !== 'string') return undefined;\r\n\t\tfor (const route of this.routes) {\r\n\t\t\tif (ty.startsWith(route)) return route;\r\n\t\t}\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tmatchString(msg: string): string | undefined {\r\n\t\tif (typeof msg !== 'string') return undefined;\r\n\t\tfor (const route of this.routes) {\r\n\t\t\tif (msg.startsWith(route)) return route;\r\n\t\t}\r\n\t\treturn undefined;\r\n\t}\r\n}\r\n\r\nexport function createWsRouteIndex(keys: string[] = []): WsRouteIndex {\r\n\tconst index = new WsRouteIndex();\r\n\tindex.rebuild(keys);\r\n\treturn index;\r\n}\r\n\r\nexport function isWsRouteKey(key: string): boolean {\r\n\treturn !!key && !NON_ROUTE_KEYS.has(key);\r\n}\r\n","/**\r\n * 统一 API / WS 路由注册 — 同步 $lib 与 hostserver*,避免双写遗漏\r\n */\r\nimport { WsRouteIndex, isWsRouteKey } from '../ws/route-index';\r\n\r\nexport type RouteFactory = ($asai: any) => Record<string, unknown>;\r\n\r\nexport function ensureWsRouteIndex($asai: any): WsRouteIndex {\r\n\tif (!$asai.wsRouteIndex) {\r\n\t\t$asai.wsRouteIndex = new WsRouteIndex();\r\n\t}\r\n\treturn $asai.wsRouteIndex as WsRouteIndex;\r\n}\r\n\r\nexport function syncApiRouteKeys($asai: any): void {\r\n\t$asai.hostserverapis = Object.keys($asai.hostserverapi || {});\r\n}\r\n\r\nexport function syncWsRouteKeys($asai: any): void {\r\n\tconst keys = Object.keys($asai.hostserverws || {}).filter(isWsRouteKey);\r\n\t$asai.hostserverwss = keys;\r\n\tensureWsRouteIndex($asai).rebuild(keys);\r\n}\r\n\r\n/** 注册 API:同时写入 $lib.api 与 hostserverapi(若已初始化) */\r\nexport function registerApi($asai: any, key: string, factory: RouteFactory): void {\r\n\tif (!$asai.$lib) $asai.$lib = {};\r\n\tif (!$asai.$lib.api) $asai.$lib.api = {};\r\n\t$asai.$lib.api[key] = factory;\r\n\tif ($asai.hostserverapi) {\r\n\t\t$asai.hostserverapi[key] = factory;\r\n\t\tsyncApiRouteKeys($asai);\r\n\t}\r\n}\r\n\r\n/** 注册 WS:同时写入 $lib.ws 与 hostserverws(若已初始化) */\r\nexport function registerWs($asai: any, key: string, factory: RouteFactory): void {\r\n\tif (!$asai.$lib) $asai.$lib = {};\r\n\tif (!$asai.$lib.ws) $asai.$lib.ws = {};\r\n\t$asai.$lib.ws[key] = factory;\r\n\tif ($asai.hostserverws) {\r\n\t\t$asai.hostserverws[key] = factory;\r\n\t\tsyncWsRouteKeys($asai);\r\n\t}\r\n}\r\n\r\n/** 初始化 hostserverapi(work 层启动时调用) */\r\nexport function initHostserverApi($asai: any, extra: Record<string, RouteFactory> = {}): void {\r\n\t$asai.hostserverapi = {\r\n\t\t...($asai.$lib?.api || {}),\r\n\t\t...extra,\r\n\t};\r\n\tsyncApiRouteKeys($asai);\r\n}\r\n\r\n/** 初始化 hostserverws(work 层启动时调用) */\r\nexport function initHostserverWs($asai: any, extra: Record<string, RouteFactory> = {}): any {\r\n\tconst commonModule = $asai.$lib?.ServerWs ? $asai.$lib.ServerWs($asai) : {};\r\n\t$asai.hostserverws = {\r\n\t\t...(commonModule || {}),\r\n\t\t...($asai.$lib?.ws || {}),\r\n\t\t...extra,\r\n\t};\r\n\tsyncWsRouteKeys($asai);\r\n\treturn commonModule;\r\n}\r\n\r\n/** 挂载 register* 到 $asai 运行时 */\r\nexport function attachRegistry($asai: any): void {\r\n\t$asai.registerApi = (key: string, factory: RouteFactory) => registerApi($asai, key, factory);\r\n\t$asai.registerWs = (key: string, factory: RouteFactory) => registerWs($asai, key, factory);\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 6.2 — 安全审计事件记录\r\n * 与 GDPR 行为日志分离,专用于鉴权失败、访问拒绝等安全事件。\r\n */\r\nexport type SecurityEventType =\r\n\t| 'AUTH_FAIL'\r\n\t| 'AUTH_MISSING'\r\n\t| 'ACCESS_DENIED'\r\n\t| 'INPUT_REJECTED'\r\n\t| 'RATE_LIMIT'\r\n\t| 'CONFIG_WARN';\r\n\r\nexport interface SecurityAuditEvent {\r\n\ttype: SecurityEventType;\r\n\tpath?: string;\r\n\tmethod?: string;\r\n\tuser?: string;\r\n\tlevel?: string | number;\r\n\tdetail?: string;\r\n\tip?: string;\r\n}\r\n\r\nfunction isAuditEnabled($asai: any): boolean {\r\n\tconst sec = $asai?.hostconfig?.security;\r\n\tif (sec && typeof sec.auditLog === 'number') return sec.auditLog !== 0;\r\n\treturn true;\r\n}\r\n\r\nexport function logSecurityEvent($asai: any, event: SecurityAuditEvent): void {\r\n\tif (!isAuditEnabled($asai)) return;\r\n\tconst ts = new Date().toISOString();\r\n\tconst parts = [\r\n\t\t'[SEC-AUDIT]',\r\n\t\tts,\r\n\t\tevent.type,\r\n\t\tevent.method || '-',\r\n\t\tevent.path || '-',\r\n\t\tevent.user ? `user=${event.user}` : '',\r\n\t\tevent.level != null ? `lv=${event.level}` : '',\r\n\t\tevent.detail || '',\r\n\t\tevent.ip ? `ip=${event.ip}` : '',\r\n\t].filter(Boolean);\r\n\tconst line = parts.join(' ');\r\n\t($asai?.$log || console.warn)('SEC', line);\r\n}\r\n\r\nexport function getClientIp(req: any): string {\r\n\tconst forwarded = req?.headers?.['x-forwarded-for'];\r\n\tif (typeof forwarded === 'string' && forwarded.length > 0) {\r\n\t\treturn forwarded.split(',')[0].trim();\r\n\t}\r\n\treturn req?.socket?.remoteAddress || '-';\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 4.3 — 标准加密算法合规自检\r\n */\r\nexport const APPROVED_ALGORITHMS = ['aes-256-gcm', 'scrypt', 'sha256', 'hmac-sha256'] as const;\r\n\r\nexport function verifyCryptoCompliance($asai: any): string[] {\r\n\tconst warnings: string[] = [];\r\n\tconst aes = $asai?.hostconfig?.aes;\r\n\tconst algo = String(aes?.algorithm || 'aes-256-gcm').toLowerCase();\r\n\tif (!APPROVED_ALGORITHMS.includes(algo as (typeof APPROVED_ALGORITHMS)[number])) {\r\n\t\twarnings.push(`非推荐加密算法: ${algo}(CR 4.3)`);\r\n\t}\r\n\tif (aes?.keylength && Number(aes.keylength) < 256) {\r\n\t\twarnings.push(`AES 密钥长度不足: ${aes.keylength}(建议 ≥256)`);\r\n\t}\r\n\treturn warnings;\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 2.11 RE(1) — NTP 时间偏移检测(启动自检,不阻断服务)\r\n */\r\nimport { execFile } from 'node:child_process';\r\nimport { promisify } from 'node:util';\r\n\r\nconst execFileAsync = promisify(execFile);\r\n\r\nexport async function checkNtpOffset(maxOffsetMs = 5000): Promise<{ ok: boolean; offsetMs?: number; detail: string }> {\r\n\tif (process.platform === 'win32') {\r\n\t\ttry {\r\n\t\t\tconst { stdout } = await execFileAsync('w32tm', ['/query', '/status'], { timeout: 5000 });\r\n\t\t\tif (/Leap Indicator:\\s*0/.test(stdout) || /Source:/.test(stdout)) {\r\n\t\t\t\treturn { ok: true, detail: 'Windows Time service active' };\r\n\t\t\t}\r\n\t\t\treturn { ok: false, detail: 'Windows Time service status unknown' };\r\n\t\t} catch {\r\n\t\t\treturn { ok: false, detail: 'w32tm unavailable' };\r\n\t\t}\r\n\t}\r\n\ttry {\r\n\t\tconst { stdout } = await execFileAsync('timedatectl', ['show', '-p', 'NTPSynchronized', '--value'], { timeout: 3000 });\r\n\t\tif (stdout.trim() === 'yes') return { ok: true, detail: 'NTP synchronized (timedatectl)' };\r\n\t} catch {\r\n\t\t/* fall through */\r\n\t}\r\n\ttry {\r\n\t\tconst { stdout } = await execFileAsync('ntpdate', ['-q', 'pool.ntp.org'], { timeout: 8000 });\r\n\t\tconst m = stdout.match(/offset\\s+([-0-9.]+)\\s+sec/i);\r\n\t\tif (m) {\r\n\t\t\tconst offsetMs = Math.abs(parseFloat(m[1]) * 1000);\r\n\t\t\treturn {\r\n\t\t\t\tok: offsetMs <= maxOffsetMs,\r\n\t\t\t\toffsetMs,\r\n\t\t\t\tdetail: `ntpdate offset ${offsetMs}ms`,\r\n\t\t\t};\r\n\t\t}\r\n\t} catch {\r\n\t\t/* optional tool */\r\n\t}\r\n\treturn { ok: false, detail: 'NTP check skipped (no timedatectl/ntpdate)' };\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 3.4 RE(1) — asaihost.json 完整性 manifest 校验\r\n */\r\nimport { createHash } from 'node:crypto';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\nexport function computeConfigHash(configPath: string): string | null {\r\n\ttry {\r\n\t\tconst raw = fs.readFileSync(configPath);\r\n\t\treturn createHash('sha256').update(raw).digest('hex');\r\n\t} catch {\r\n\t\treturn null;\r\n\t}\r\n}\r\n\r\nexport function verifyConfigManifest(serverRoot: string): { ok: boolean; detail: string } {\r\n\tconst configPath = path.join(serverRoot, 'websys/sys/asaihost.json');\r\n\tconst manifestPath = path.join(serverRoot, 'websys/sys/asaihost.manifest.json');\r\n\tif (!fs.existsSync(manifestPath)) {\r\n\t\treturn { ok: true, detail: 'no manifest (optional)' };\r\n\t}\r\n\ttry {\r\n\t\tconst manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\r\n\t\tconst expected = String(manifest.sha256 || '');\r\n\t\tconst actual = computeConfigHash(configPath);\r\n\t\tif (!actual) return { ok: false, detail: 'config file unreadable' };\r\n\t\tif (expected && expected !== actual) {\r\n\t\t\treturn { ok: false, detail: 'asaihost.json hash mismatch' };\r\n\t\t}\r\n\t\treturn { ok: true, detail: 'manifest verified' };\r\n\t} catch (e: any) {\r\n\t\treturn { ok: false, detail: e?.message || 'manifest parse error' };\r\n\t}\r\n}\r\n\r\nexport function writeConfigManifest(serverRoot: string): string | null {\r\n\tconst configPath = path.join(serverRoot, 'websys/sys/asaihost.json');\r\n\tconst hash = computeConfigHash(configPath);\r\n\tif (!hash) return null;\r\n\tconst manifestPath = path.join(serverRoot, 'websys/sys/asaihost.manifest.json');\r\n\tfs.writeFileSync(\r\n\t\tmanifestPath,\r\n\t\tJSON.stringify({ file: 'asaihost.json', sha256: hash, updatedAt: new Date().toISOString() }, null, 2),\r\n\t\t'utf8',\r\n\t);\r\n\treturn hash;\r\n}\r\n","/** 启动期初始化 — IP、日志、进程守护、AES 插件、路由注册表、IEC 62443 自检 */\r\nimport { getIp, getHostIP } from './network';\r\nimport { getHostCFG } from './host-config';\r\nimport { initProcess, gracefulShutdown } from '../infra/process';\r\nimport { initLog, setAppend, appendAccessLog } from '../infra/logger';\r\nimport { attachRegistry } from '../infra/registry';\r\nimport { isDevDefaultPassword } from '../config/secrets';\r\nimport { logSecurityEvent } from '../infra/security-audit';\r\nimport { verifyCryptoCompliance } from '../infra/crypto-compliance';\r\nimport { checkNtpOffset } from '../infra/ntp-check';\r\nimport { verifyConfigManifest } from '../infra/config-integrity';\r\n\r\nexport function initAsaiHost($asai: any, _opt: any): void {\r\n\tif (!$asai.hostconfig?.ip) {\r\n\t\t$asai.hostconfig.ip = getIp();\r\n\t}\r\n\t$asai.setAppend = (src: string, logstr: string) => setAppend($asai, src, logstr);\r\n\t$asai.appendAccessLog = (clfLine: string, w3cLine: string) => appendAccessLog($asai, clfLine, w3cLine);\r\n\t$asai.getHost = (hostdir: string) => getHostCFG(hostdir, $asai);\r\n\t$asai.getHostIP = (ip?: string | null) => getHostIP(ip, $asai);\r\n\t$asai.gracefulShutdown = () => gracefulShutdown($asai);\r\n\tattachRegistry($asai);\r\n\r\n\tinitProcess($asai);\r\n\tinitLog($asai);\r\n\r\n\t$asai.hostconfig.asaiport = [];\r\n\t$asai.hostconfig.guardtm = null;\r\n\r\n\tif ($asai.hostconfig?.aes?.lv && !$asai.$lib?.aesfns && typeof $asai.$lib?.AsAES === 'function') {\r\n\t\tconst { reqAES, resAES } = $asai.$lib.AsAES($asai);\r\n\t\t$asai.$lib.aesfns = {\r\n\t\t\tallaes: $asai.hostconfig.aes.lv > 1,\r\n\t\t\treqAES,\r\n\t\t\tresAES,\r\n\t\t};\r\n\t}\r\n\r\n\tif (isDevDefaultPassword($asai.hostconfig?.password || '')) {\r\n\t\tlogSecurityEvent($asai, {\r\n\t\t\ttype: 'CONFIG_WARN',\r\n\t\t\tdetail: 'Using dev-only password; set ASAI_HOST_PASSWORD for production (IEC 62443-4-2 CR 1.7)',\r\n\t\t});\r\n\t\tvoid import('../sysserver/lib/common/intervention-hooks').then(({ logSecurityConfigIntervention }) =>\r\n\t\t\tlogSecurityConfigIntervention($asai, {\r\n\t\t\t\tsection: 'password',\r\n\t\t\t\tdetail: 'dev-default-password detected at startup',\r\n\t\t\t}),\r\n\t\t).catch(() => undefined);\r\n\t}\r\n\r\n\tscheduleLogComplianceCheck($asai);\r\n\r\n\tfor (const w of verifyCryptoCompliance($asai)) {\r\n\t\tlogSecurityEvent($asai, { type: 'CONFIG_WARN', detail: w });\r\n\t}\r\n\tconst root = $asai.serverRoot || process.cwd();\r\n\tconst manifest = verifyConfigManifest(root);\r\n\tif (!manifest.ok) {\r\n\t\tlogSecurityEvent($asai, { type: 'CONFIG_WARN', detail: `Config integrity: ${manifest.detail}` });\r\n\t}\r\n\tvoid checkNtpOffset().then((ntp) => {\r\n\t\tif (!ntp.ok) logSecurityEvent($asai, { type: 'CONFIG_WARN', detail: `NTP: ${ntp.detail}` });\r\n\t});\r\n}\r\n\r\n/** 定时合规巡检(默认 6 小时,链异常/磁盘告警经 WS 广播) */\r\nfunction scheduleLogComplianceCheck($asai: any): void {\r\n\tconst hours = Number($asai?.hostconfig?.logger?.complianceIntervalHours) || 6;\r\n\tif (hours <= 0) return;\r\n\tconst ms = hours * 3600 * 1000;\r\n\tsetInterval(() => {\r\n\t\tvoid import('../sysserver/lib/common/LogStore').then(({ getComplianceReport }) =>\r\n\t\t\tgetComplianceReport($asai, 'prod'),\r\n\t\t).catch(() => undefined);\r\n\t}, ms);\r\n}\r\n","/**\n * http-server.ts — HTTP/HTTPS 静态资源与 API 路由服务\n *\n * 请求分发:/sys → sysWork,/api → apiWork,/jsonp → jsonpWork,其余走静态目录。\n * 性能要点:\n * - 处理器在 server 创建时缓存到闭包,避免每请求查 Map\n * - 静态文件查找合并 stat,减少重复磁盘 I/O\n * - Userinfo 直接读 req.headers(Node 已解析)\n */\nimport * as http from 'http';\nimport * as https from 'https';\nimport { getHostCFG, getHostIP, getNowTime } from '../core';\nimport { createWSHost } from '../ws/server';\nimport { getWorkHandler } from '../index';\nimport { StaticPathCache } from './static-path-cache';\nimport { applySecurityHeaders, checkHttpHeader } from './security';\nimport { formatHttpError, logHttp, createSkipChecker } from './log';\nimport { createStaticHandler } from './static';\nimport { setupHttpConnectionMonitor } from './connection';\nimport { releasePort } from '../infra/port-release';\n\nexport { getHttpUserinfo, checkHttpHeader } from './security';\n\nfunction scheduleHttpRetry($asai: any, hostdir: string): void {\n\tif ($asai.hostconfig.guardtm) {\n\t\tclearTimeout($asai.hostconfig.guardtm);\n\t\t$asai.hostconfig.guardtm = null;\n\t}\n\t$asai.hostconfig.guardtm = setTimeout(() => {\n\t\tstartHTTPServer($asai, hostdir);\n\t\tif ($asai.hostconfig.guardtm) {\n\t\t\tclearTimeout($asai.hostconfig.guardtm);\n\t\t\t$asai.hostconfig.guardtm = null;\n\t\t}\n\t}, $asai.hostconfig.tm?.d || 2000);\n}\n\nfunction clearFailedHttpHost($asai: any, hostdir: string, ws?: boolean): void {\n\tdelete $asai.servershttp[hostdir];\n\tif (ws) delete $asai.serversws[hostdir];\n}\n\nexport function getHTTPServer(httptype: string = '', cfg: any, $asai: any): any {\n\ttry {\n\t\tif (httptype.startsWith('https')) {\n\t\t\t// 返回包装对象,避免修改不可扩展的原生模块\n\t\t\treturn {\n\t\t\t\tAsCreateServer: (callback: any) => {\n\t\t\t\t\treturn https.createServer(cfg?.httpscert || $asai.hostconfig.httpscert, callback);\n\t\t\t\t},\n\t\t\t\tAgent: https.Agent,\n\t\t\t\trequest: https.request,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tAsCreateServer: http.createServer,\n\t\t\t\tAgent: http.Agent,\n\t\t\t\trequest: http.request,\n\t\t\t};\n\t\t}\n\t} catch (err) {\n\t\t$asai.$log('HTTP', 'Http server error:', err instanceof Error ? `${err.name}: ${err.message}\\n${err.stack}` : JSON.stringify(err));\n\t\treturn {\n\t\t\tAsCreateServer: http.createServer,\n\t\t\tAgent: http.Agent,\n\t\t\trequest: http.request,\n\t\t};\n\t}\n}\n\nexport function startHTTPServer($asai: any, hostdir: string): any {\n\tconst hostcfg = getHostCFG(hostdir, $asai);\n\tif (!hostcfg || hostcfg.close) return;\n\n\ttry {\n\t\tif (!$asai.servershttp[hostdir]) {\n\t\t\tif (hostcfg.mimetypes !== undefined) {\n\t\t\t\thostcfg.mimetypes = { ...($asai.hostconfig.mimetypes || {}), ...(hostcfg.mimetypes || {}) };\n\t\t\t} else {\n\t\t\t\thostcfg.mimetypes = { ...($asai.hostconfig.mimetypes || {}) };\n\t\t\t}\n\n\t\t\tconst httpLib = getHTTPServer(hostcfg.httptype, hostcfg, $asai);\n\t\t\tconst indexFile = $asai.hostconfig.index || 'index.html';\n\t\t\tconst staticPathCache = new StaticPathCache(2000, 30_000);\n\t\t\tconst skipChecker = createSkipChecker($asai);\n\t\t\tconst isHttps = (hostcfg.httptype || '').startsWith('https');\n\t\t\t// 处理器缓存在闭包内,热路径零查找\n\t\t\tconst apiWorkHost = getWorkHandler('apiWorkHost');\n\t\t\tconst sysWork = getWorkHandler('sysWork');\n\t\t\tconst apiWork = getWorkHandler('apiWork');\n\t\t\tconst jsonpWork = getWorkHandler('jsonpWork');\n\t\t\tconst handleStatic = createStaticHandler({ hostcfg, hostdir, indexFile, $asai, staticPathCache });\n\n\t\t\tconst server = (httpLib as any).AsCreateServer((req: any, res: any) => {\n\t\t\t\ttry {\n\t\t\t\t\tif (!checkHttpHeader(req, $asai)) {\n\t\t\t\t\t\tlogHttp($asai, 'HTTP', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\tres.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' });\n\t\t\t\t\t\tres.end('502');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tapplySecurityHeaders(res, isHttps, $asai.hostconfig);\n\n\t\t\t\t\tif (req.url?.startsWith('/sys') && sysWork) {\n\t\t\t\t\t\tlogHttp($asai, 'SYS', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\tsysWork(req, res, hostdir);\n\t\t\t\t\t} else if (req.url?.startsWith('/api') && apiWork) {\n\t\t\t\t\t\tlogHttp($asai, 'API', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\tapiWork(req, res, hostdir);\n\t\t\t\t\t} else if (req.url?.startsWith('/jsonp') && jsonpWork) {\n\t\t\t\t\t\tlogHttp($asai, 'JSONP', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\tjsonpWork(req, res, hostdir);\n\t\t\t\t\t} else if (handleStatic) {\n\t\t\t\t\t\tlogHttp($asai, 'REQ_OTHER', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\thandleStatic(req, res, req.url!);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$asai.$log('HTTP', req.method, req.url);\n\t\t\t\t\t\tres.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });\n\t\t\t\t\t\tres.end('404');\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\t$asai.$log('HTTP', 'HTTP request error:', formatHttpError(err));\n\t\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\n\t\t\t\t\t\tres.end('Internal server error');\n\t\t\t\t\t} else if (!res.writableEnded) {\n\t\t\t\t\t\tres.end();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t$asai.servershttp[hostdir] = server;\n\n\t\t\tif (hostcfg.ws) {\n\t\t\t\tcreateWSHost($asai, hostdir);\n\t\t\t}\n\n\t\t\tserver.on('error', (err: any) => {\n\t\t\t\tif (err.code === 'EADDRINUSE') {\n\t\t\t\t\t$asai.hostconfig.asaiport.push(hostcfg.port);\n\t\t\t\t\t$asai.$log('HTTP', `\\x1B[41mPort ${hostcfg.port} is already start!\\x1B[0m`);\n\t\t\t\t\tclearFailedHttpHost($asai, hostdir, hostcfg.ws);\n\t\t\t\t\tasaiGuard($asai, hostdir);\n\t\t\t\t} else {\n\t\t\t\t\t$asai.$log('HTTP', 'Server error:', err instanceof Error ? `${err.name}: ${err.message}\\n${err.stack}` : err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treleasePort(hostcfg.port, { excludePid: process.pid, label: hostdir });\n\n\t\t\tif ($asai.hostconfig.ip === 'asai' || (!hostcfg.ip && !$asai.hostconfig.ip)) {\n\t\t\t\tserver.listen(hostcfg.port, () => {\n\t\t\t\t\tconsole.log(`[${hostdir}] Start At ${getNowTime()}.`);\n\t\t\t\t\tif (hostcfg.ws) {\n\t\t\t\t\t\tconsole.log(`\\x1B[41;28mWS Server ${hostcfg.wstype || 'ws://'}localhost:${hostcfg.port}\\x1B[0m`);\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log(`\\x1B[42;28mHTTP Server ${hostcfg.httptype}localhost:${hostcfg.port}\\x1B[0m`);\n\t\t\t\t\tconsole.log(`================================================`);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst ipcur: string = getHostIP(hostcfg.ip, $asai);\n\t\t\t\tserver.listen(hostcfg.port, ipcur, () => {\n\t\t\t\t\tconsole.log(`[${hostdir}] Start At ${getNowTime()}.`);\n\t\t\t\t\tif (hostcfg.ws) {\n\t\t\t\t\t\tconsole.log(`\\x1B[41;28mWS Server ${hostcfg.wstype || 'ws://'}${ipcur}:${hostcfg.port}\\x1B[0m`);\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log(`\\x1B[44;28mHTTP Server ${hostcfg.httptype}${ipcur}:${hostcfg.port}\\x1B[0m`);\n\t\t\t\t\tconsole.log(`================================================`);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (hostcfg.ckhttp) {\n\t\t\t\tsetupHttpConnectionMonitor($asai, hostdir, server, hostcfg);\n\t\t\t}\n\t\t}\n\t} catch (err) {\n\t\t$asai.$log('HTTP', 'Http server error:', err instanceof Error ? `${err.name}: ${err.message}\\n${err.stack}` : JSON.stringify(err));\n\t}\n\n\treturn $asai.servershttp[hostdir];\n}\n\nfunction findSameProcessPortOwner($asai: any, port: number, excludeHostdir: string): string | null {\n\tfor (const hostdir of Object.keys($asai.servershttp || {})) {\n\t\tif (hostdir === excludeHostdir) continue;\n\t\tconst cfg = getHostCFG(hostdir, $asai);\n\t\tif (cfg?.port === port) return hostdir;\n\t}\n\treturn null;\n}\n\nexport function asaiGuard($asai: any, failedHostdir: string = 'asai'): void {\n\tconst conflictPorts: number[] = $asai.hostconfig.asaiport || [];\n\tconst hostcfg = getHostCFG(failedHostdir, $asai);\n\tconst port = hostcfg?.port;\n\tif (!port || !conflictPorts.includes(port)) {\n\t\tscheduleHttpRetry($asai, failedHostdir);\n\t\treturn;\n\t}\n\n\tconst sameProcessOwner = findSameProcessPortOwner($asai, port, failedHostdir);\n\tif (sameProcessOwner) {\n\t\tconsole.error(\n\t\t\t`[AsaiHost] 端口 ${port} 已被同进程站点 [${sameProcessOwner}] 占用,[${failedHostdir}] 停止重试(请检查 asaihost.json 是否重复配置 port)`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst released = releasePort(port, { excludePid: process.pid, label: failedHostdir });\n\t$asai.hostconfig.asaiport = conflictPorts.filter((p: number) => p !== port);\n\tif (released) {\n\t\tconsole.warn(`[AsaiHost] 端口 ${port} 已释放,正在重新启动 [${failedHostdir}]`);\n\t\tscheduleHttpRetry($asai, failedHostdir);\n\t\treturn;\n\t}\n\n\tconsole.error(`[AsaiHost] 端口 ${port} 无法释放,启动失败(netstat -ano | findstr :${port})`);\n\tprocess.exit(1);\n}\n","/** WebSocket 服务 — 挂载在 HTTP server 上,鉴权 + 消息转发 */\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { getHostCFG } from '../core';\nimport { getWorkHandler } from '../index';\nimport { getWsUserinfo, isOkWs, loginWs } from './auth';\nimport { attachWssHelpers, clearWsServerTasks } from './message';\nimport { acquireWsSlot, countActiveWsConnections, getMaxWebConnections, releaseWsSlot } from '../infra/connection-quota';\nimport { getClientIp, logSecurityEvent } from '../infra/security-audit';\n\nexport { clearWsServerTasks } from './message';\nexport { getWsUserinfo } from './auth';\n\nexport function createWSHost($asai: any, hostdir: string): void {\n\tconst hostcfg = getHostCFG(hostdir, $asai);\n\tconst wsWorkHandler = getWorkHandler('wsWork');\n\tconst logWsMessage = !!$asai.hostconfig.logger?.lv?.view;\n\n\ttry {\n\t\tif ($asai.serversws[hostdir]) return;\n\n\t\tif (hostcfg.ckws && !$asai.connectionsws[hostdir]) {\n\t\t\t$asai.connectionsws[hostdir] = {};\n\t\t}\n\t\tif (!$asai.tasksws[hostdir]) $asai.tasksws[hostdir] = {};\n\n\t\tconst wss = new WebSocketServer({ server: $asai.servershttp[hostdir], perMessageDeflate: false });\n\t\tattachWssHelpers(wss, $asai);\n\n\t\twss.on('error', (err: Error) => {\n\t\t\tclearWsServerTasks($asai, hostdir);\n\t\t\t$asai.$log('WS', 'WS Server error!', err);\n\t\t\twss.close?.(() => {\n\t\t\t\t$asai.$log('WS', 'WS Server closed');\n\t\t\t\tdelete $asai.serversws[hostdir];\n\t\t\t});\n\t\t});\n\n\t\twss.on('close', (code: number, reason: Buffer) => {\n\t\t\ttry {\n\t\t\t\t$asai.$log('WS', `WebSocket closed, server ${hostdir}, code: ${code}, reason: ${reason?.toString()}`);\n\t\t\t\tclearWsServerTasks($asai, hostdir);\n\t\t\t} catch (err) {\n\t\t\t\t$asai.$log('WS', 'WS close handler error:', err);\n\t\t\t}\n\t\t});\n\n\t\twss.on('connection', (ws: any, req: any) => {\n\t\t\tconst clientIp = getClientIp(req);\n\t\t\tif (!acquireWsSlot($asai, hostdir, clientIp)) {\n\t\t\t\tconst wsmsg = JSON.stringify({\n\t\t\t\t\tty: 'publish/web',\n\t\t\t\t\tdb: { exit: 1, type: 'err', lang: 'maxws', langpm: 'ip', con: 'WS IP quota exceeded' },\n\t\t\t\t});\n\t\t\t\tws.send(wsmsg, () => ws.close(1013, 'Server busy'));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tws.once('close', () => releaseWsSlot(hostdir, clientIp));\n\n\t\t\treq.Userinfo = getWsUserinfo(req, $asai) || [];\n\t\t\tws.Userinfo = req.Userinfo;\n\n\t\t\tconst maxWs = getMaxWebConnections($asai, hostcfg);\n\t\t\tconst currentWsConnections = countActiveWsConnections(wss, ws, $asai, hostdir, hostcfg, req.Userinfo);\n\n\t\t\tif (currentWsConnections >= maxWs) {\n\t\t\t\t$asai.$log('WS', `WS Connection MAX rejected (${currentWsConnections}/${maxWs})`);\n\t\t\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/ws', detail: 'maxWebConnections', ip: clientIp });\n\t\t\t\tconst wsmsg = JSON.stringify({\n\t\t\t\t\tty: 'publish/web',\n\t\t\t\t\tdb: { exit: 1, type: 'err', lang: 'maxws', langpm: `${maxWs}`, con: `connection limit ${maxWs} exceeded` },\n\t\t\t\t});\n\t\t\t\tws.send(wsmsg, () => ws.close(1013, 'Server busy'));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst isOpen = !hostcfg.ckws || isOkWs($asai, hostdir, ws, req, hostcfg);\n\t\t\tif (isOpen) {\n\t\t\t\tloginWs($asai, hostdir, ws, req, hostcfg, wsWorkHandler, logWsMessage);\n\t\t\t} else {\n\t\t\t\tws.close();\n\t\t\t}\n\t\t});\n\n\t\t$asai.serversws[hostdir] = wss;\n\t} catch (err) {\n\t\t$asai.$log('WS', 'ws server:', JSON.stringify(err));\n\t}\n}\n","/** WebSocket 连接鉴权、登录态管理与消息回调 */\nimport { WebSocket } from 'ws';\nimport { deUserInfoWithAsai } from '../utils/userinfo';\n\nexport function getWsUserinfo(req: any, $asai: any): any {\n\ttry {\n\t\tconst raw = req.headers?.['sec-websocket-protocol'];\n\t\tif (!raw) return null;\n\t\treturn deUserInfoWithAsai(raw.split('##'), $asai);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** 用户是否已在 WS 在线表(ckws 单点登录判定) */\nexport function isUserOnlineOnWs($asai: any, us: string, hostdir?: string): boolean {\n\tif (!us || us === 'asai') return false;\n\tconst map = $asai.connectionsws || {};\n\tconst dirs = hostdir ? [hostdir] : Object.keys(map);\n\tfor (const dir of dirs) {\n\t\tif (map[dir]?.[us]) return true;\n\t}\n\treturn false;\n}\n\n/** 连接仍有效(非刷新替换场景) */\nfunction isWsStillActive(ws: any): boolean {\n\tif (!ws) return false;\n\tconst state = ws.readyState;\n\treturn state === WebSocket.CONNECTING || state === WebSocket.OPEN;\n}\n\n/** 仅拒绝后来连接,不打扰已在线用户 */\nfunction rejectIncomingWs(ws: any, db: Record<string, unknown>): void {\n\tconst payload = JSON.stringify({ ty: 'publish/web', db: { exit: 1, type: 'err', ...db } });\n\ttry {\n\t\tws.send(payload, () => {\n\t\t\ttry {\n\t\t\t\tws.close();\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t});\n\t} catch {\n\t\ttry {\n\t\t\tws.close();\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t}\n}\n\nexport function isOkWs($asai: any, hostdir: string, ws: any, _req: any, hostcfg: any): boolean {\n\tconst [us, , tk] = ws.Userinfo || [];\n\n\tif (!us) {\n\t\tws.close();\n\t\treturn false;\n\t}\n\n\tif (us !== 'asai' && $asai.connectionsws[hostdir]?.[us]) {\n\t\tconst existingWs = $asai.connectionsws[hostdir][us];\n\t\tif (existingWs?.Userinfo?.[2] === tk) {\n\t\t\t// 同账号同 token:已有页面在运行则拒绝后来连接;旧连接已关闭/关闭中(刷新)才允许接管\n\t\t\tif (isWsStillActive(existingWs)) {\n\t\t\t\trejectIncomingWs(ws, {\n\t\t\t\t\tlang: 'pageworking',\n\t\t\t\t\tlangpm: `${us}`,\n\t\t\t\t\tcon: `${us} page already running`,\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\texistingWs.close();\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t\tdelete $asai.connectionsws[hostdir][us];\n\t\t\treturn true;\n\t\t}\n\t\t// 不同 token 的同账号:先登录者占据在线位,仅拒绝新连接\n\t\trejectIncomingWs(ws, {\n\t\t\tlang: 'logged',\n\t\t\tlangpm: `${us}`,\n\t\t\tcon: `${us} logged in!`,\n\t\t});\n\t\treturn false;\n\t}\n\n\tif (us !== 'asai') {\n\t\tconst connections = $asai.connectionsws[hostdir] || {};\n\t\t// 相同 token 已被其他账号占用:先占用者优先,仅拒绝新连接\n\t\tconst sameTkWs: any = Object.values(connections).find(\n\t\t\t(item: any) => item.Userinfo?.[2] === tk && item.Userinfo?.[0] !== us,\n\t\t);\n\t\tconst maxOnline = hostcfg.maxonline || 100;\n\n\t\tif (sameTkWs) {\n\t\t\trejectIncomingWs(ws, {\n\t\t\t\tlang: 'loggedsametk',\n\t\t\t\tlangpm: `${us}(${sameTkWs.Userinfo[0]})`,\n\t\t\t\tcon: `${us}(${sameTkWs.Userinfo[0]}) logged in!`,\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t\tif (Object.keys(connections).length >= maxOnline) {\n\t\t\trejectIncomingWs(ws, {\n\t\t\t\tlang: 'maxlogged',\n\t\t\t\tlangpm: `${maxOnline}`,\n\t\t\t\tcon: `max ${maxOnline} users online!`,\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport function loginWs(\n\t$asai: any, hostdir: string, ws: any, req: any, hostcfg: any,\n\twsWorkHandler: Function | undefined, logWsMessage: boolean,\n): void {\n\tconst [us] = ws.Userinfo || [];\n\tif (hostcfg.ckws && us) {\n\t\tif (!ws.tasksws) ws.tasksws = {};\n\t\t$asai.connectionsws[hostdir][us] = ws;\n\t}\n\n\tws.on('message', (msg: Buffer) => {\n\t\tif (logWsMessage) $asai.$log('WS', 'message', msg.toString());\n\t\twsWorkHandler?.(msg, ws, hostdir, req);\n\t});\n\n\tws.on('close', () => {\n\t\tif (hostcfg.ckws) {\n\t\t\tif (ws.tasksws) {\n\t\t\t\tObject.values(ws.tasksws).forEach((el: any) => el && clearInterval(el));\n\t\t\t\tws.tasksws = undefined;\n\t\t\t}\n\t\t\t// 仅当在线表里存的仍是「自己」时才删除;快速刷新时旧连接的 close 晚于新连接登记,\n\t\t\t// 若无条件删除会把刚登记的新连接误删,导致账号校验判定为未登录而触发退出\n\t\t\tif (us && $asai.connectionsws[hostdir]?.[us] === ws) delete $asai.connectionsws[hostdir][us];\n\t\t}\n\t\tif (ws.readyState !== WebSocket.CLOSED && ws.readyState !== WebSocket.CLOSING) ws.close();\n\t});\n}\n","/** HTTP/WS Userinfo 解密(us##lv##tk,依赖 AsCode + asaisn) */\r\nexport function deUserInfoWithAsai(userinfo: string[] | null | undefined, $asai: any): string[] | null {\r\n\tif (!Array.isArray(userinfo) || userinfo.length < 3) {\r\n\t\treturn userinfo as any;\r\n\t}\r\n\tif (userinfo[2]) {\r\n\t\tconst sn = $asai?.hostconfig?.asaisn;\r\n\t\tif (!sn) {\r\n\t\t\t$asai.$log('USER', 'User info decode error: ASAI_ASAISN not configured');\r\n\t\t\treturn userinfo;\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tuserinfo[2] = $asai.$lib.AsCode.asdecode(userinfo[2], sn);\r\n\t\t\tuserinfo[0] = $asai.$lib.AsCode.asdecode(userinfo[0], userinfo[2]);\r\n\t\t\tuserinfo[1] = $asai.$lib.AsCode.asdecode(userinfo[1], userinfo[2]);\r\n\t\t} catch (err) {\r\n\t\t\t$asai.$log('USER', 'User info decode error:', err);\r\n\t\t}\r\n\t}\r\n\treturn userinfo;\r\n}\r\n","/** WS 出站消息序列化与定时任务清理 */\r\nimport { WebSocket } from 'ws';\r\n\r\nexport function clearWsServerTasks($asai: any, hostdir: string): void {\r\n\tconst tasks = $asai.tasksws[hostdir];\r\n\tif (tasks && typeof tasks === 'object') {\r\n\t\tObject.values(tasks).forEach((el: any) => {\r\n\t\t\tif (el) clearInterval(el as NodeJS.Timeout);\r\n\t\t});\r\n\t\t$asai.tasksws[hostdir] = {};\r\n\t}\r\n}\r\n\r\n/** ping/pong 原样返回,对象走 JSON,可选 AES 加密 db 字段 */\r\nexport function resWsMsg(msg: any, $asai: any): any {\r\n\tif (msg === 'ping' || msg === 'pong') return msg;\r\n\tif (typeof msg !== 'object' || msg === null) return msg;\r\n\tif ((msg?.aes || $asai.$lib.aesfns?.allaes) && msg?.db && $asai.$lib?.aesfns?.resAES) {\r\n\t\tmsg.db = $asai.$lib.aesfns.resAES(msg.db);\r\n\t}\r\n\treturn JSON.stringify(msg);\r\n}\r\n\r\nexport function attachWssHelpers(wss: any, $asai: any): void {\r\n\twss.sendws = (msg: any, type: number, curws: any) => {\r\n\t\tconst data = resWsMsg(msg, $asai);\r\n\t\tif (type) {\r\n\t\t\twss.clients.forEach((client: any) => {\r\n\t\t\t\tif ((type === 2 || client !== curws) && client.readyState === WebSocket.OPEN) {\r\n\t\t\t\t\tclient.send(data);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t} else {\r\n\t\t\tcurws.send(data);\r\n\t\t}\r\n\t};\r\n\twss.broadws = (msg: any) => {\r\n\t\tconst data = resWsMsg(msg, $asai);\r\n\t\twss.clients.forEach((client: any) => {\r\n\t\t\tif (client?.readyState === WebSocket.OPEN) client.send(data);\r\n\t\t});\r\n\t};\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 7 — API/WS/登录配额统一服务\r\n */\r\nimport type { WebSocket, WebSocketServer } from 'ws';\r\nimport { WebSocket as WsConst } from 'ws';\r\nimport { logSecurityEvent } from './security-audit';\r\n\r\ntype SlotMap = Map<string, number>;\r\ntype RateMap = Map<string, { count: number; resetAt: number }>;\r\n\r\nconst apiGlobal = new Map<string, number>();\r\nconst apiPerIp = new Map<string, SlotMap>();\r\nconst apiRatePerIp = new Map<string, RateMap>();\r\nconst wsPerIp = new Map<string, SlotMap>();\r\n\r\nfunction getQuota($asai: any) {\r\n\treturn $asai?.hostconfig?.security?.quota || {};\r\n}\r\n\r\nfunction isEnabled($asai: any): boolean {\r\n\tconst q = getQuota($asai);\r\n\treturn q.enabled === 1 || q.enabled === true;\r\n}\r\n\r\nfunction hostKey(hostdir: string): string {\r\n\treturn hostdir || 'default';\r\n}\r\n\r\nexport function acquireApiSlot($asai: any, hostdir: string, ip: string): { ok: boolean; code?: number; message?: string } {\r\n\tif (!isEnabled($asai)) return { ok: true };\r\n\tconst q = getQuota($asai);\r\n\tconst hk = hostKey(hostdir);\r\n\r\n\tconst maxGlobal = q.maxApiConcurrent ?? 500;\r\n\tconst curGlobal = apiGlobal.get(hk) || 0;\r\n\tif (curGlobal >= maxGlobal) {\r\n\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/api', detail: 'maxApiConcurrent', ip });\r\n\t\treturn { ok: false, code: 503, message: 'API quota exceeded' };\r\n\t}\r\n\r\n\tconst maxPerIp = q.maxApiPerIp ?? 30;\r\n\tconst ipMap = apiPerIp.get(hk) || new Map();\r\n\tconst curIp = ipMap.get(ip) || 0;\r\n\tif (curIp >= maxPerIp) {\r\n\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/api', detail: 'maxApiPerIp', ip });\r\n\t\treturn { ok: false, code: 429, message: 'Too many requests' };\r\n\t}\r\n\r\n\tconst maxPerMin = q.maxApiPerIpPerMin ?? 120;\r\n\tconst now = Date.now();\r\n\tlet rateHost = apiRatePerIp.get(hk);\r\n\tif (!rateHost) {\r\n\t\trateHost = new Map();\r\n\t\tapiRatePerIp.set(hk, rateHost);\r\n\t}\r\n\tlet bucket = rateHost.get(ip);\r\n\tif (!bucket || bucket.resetAt < now) {\r\n\t\tbucket = { count: 0, resetAt: now + 60000 };\r\n\t\trateHost.set(ip, bucket);\r\n\t}\r\n\tbucket.count += 1;\r\n\tif (bucket.count > maxPerMin) {\r\n\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/api', detail: 'maxApiPerIpPerMin', ip });\r\n\t\treturn { ok: false, code: 429, message: 'Rate limit exceeded' };\r\n\t}\r\n\r\n\tapiGlobal.set(hk, curGlobal + 1);\r\n\tipMap.set(ip, curIp + 1);\r\n\tapiPerIp.set(hk, ipMap);\r\n\treturn { ok: true };\r\n}\r\n\r\nexport function releaseApiSlot(hostdir: string, ip: string): void {\r\n\tconst hk = hostKey(hostdir);\r\n\tconst g = apiGlobal.get(hk) || 0;\r\n\tif (g > 0) apiGlobal.set(hk, g - 1);\r\n\tconst ipMap = apiPerIp.get(hk);\r\n\tif (ipMap) {\r\n\t\tconst c = ipMap.get(ip) || 0;\r\n\t\tif (c > 0) ipMap.set(ip, c - 1);\r\n\t}\r\n}\r\n\r\nexport function acquireWsSlot($asai: any, hostdir: string, ip: string): boolean {\r\n\tif (!isEnabled($asai)) return true;\r\n\tconst maxPerIp = getQuota($asai).maxWsPerIp ?? 5;\r\n\tconst hk = hostKey(hostdir);\r\n\tconst ipMap = wsPerIp.get(hk) || new Map();\r\n\tconst cur = ipMap.get(ip) || 0;\r\n\tif (cur >= maxPerIp) {\r\n\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/ws', detail: 'maxWsPerIp', ip });\r\n\t\treturn false;\r\n\t}\r\n\tipMap.set(ip, cur + 1);\r\n\twsPerIp.set(hk, ipMap);\r\n\treturn true;\r\n}\r\n\r\nexport function releaseWsSlot(hostdir: string, ip: string): void {\r\n\tconst hk = hostKey(hostdir);\r\n\tconst ipMap = wsPerIp.get(hk);\r\n\tif (!ipMap) return;\r\n\tconst c = ipMap.get(ip) || 0;\r\n\tif (c > 0) ipMap.set(ip, c - 1);\r\n}\r\n\r\n/** WEB 平台最大并发连接数:quota.maxWebConnections 优先,否则 hosts.*.maxws */\r\nexport function getMaxWebConnections($asai: any, hostcfg: any): number {\r\n\tconst q = getQuota($asai);\r\n\tconst fromQuota = Number(q.maxWebConnections);\r\n\tif (fromQuota > 0) return fromQuota;\r\n\treturn Number(hostcfg?.maxws) > 0 ? Number(hostcfg.maxws) : 100;\r\n}\r\n\r\n/**\r\n * 统计当前有效 WS 连接数(不含 incoming;同 token 刷新/重连时排除将被替换的旧连接)\r\n */\r\nexport function countActiveWsConnections(\r\n\twss: WebSocketServer,\r\n\tincoming: WebSocket,\r\n\t$asai: any,\r\n\thostdir: string,\r\n\thostcfg: any,\r\n\tuserinfo: unknown[],\r\n): number {\r\n\tconst [us, , tk] = (userinfo || []) as [string?, unknown?, string?];\r\n\tlet count = 0;\r\n\tfor (const client of wss.clients) {\r\n\t\tif (client === incoming) continue;\r\n\t\tif (client.readyState === WsConst.CLOSED || client.readyState === WsConst.CLOSING) continue;\r\n\t\tconst cInfo = (client as WebSocket & { Userinfo?: unknown[] }).Userinfo;\r\n\t\tconst cUs = cInfo?.[0] as string | undefined;\r\n\t\tconst cTk = cInfo?.[2] as string | undefined;\r\n\t\t// 同账号同 token 重连:旧连接即将被替换,不计入占用\r\n\t\tif (us && tk && cUs === us && cTk === tk) continue;\r\n\t\tif (hostcfg?.ckws && us && tk) {\r\n\t\t\tconst existing = $asai?.connectionsws?.[hostdir]?.[us];\r\n\t\t\tif (existing === client && existing?.Userinfo?.[2] === tk) continue;\r\n\t\t}\r\n\t\tcount += 1;\r\n\t}\r\n\treturn count;\r\n}\r\n\r\nexport function getQuotaSnapshot($asai: any, hostdir: string) {\r\n\tconst hk = hostKey(hostdir);\r\n\treturn {\r\n\t\tenabled: isEnabled($asai),\r\n\t\tapiGlobal: apiGlobal.get(hk) || 0,\r\n\t\tapiPerIp: Object.fromEntries(apiPerIp.get(hk) || []),\r\n\t\twsPerIp: Object.fromEntries(wsPerIp.get(hk) || []),\r\n\t\tconfig: getQuota($asai),\r\n\t};\r\n}\r\n","/**\r\n * 静态文件路径 LRU 缓存 — Map 插入序 O(1) 淘汰,命中后 stat 校验 mtime\r\n */\r\nimport * as fs from 'fs';\r\n\r\ninterface CacheEntry {\r\n\tfilePath: string;\r\n\tmtimeMs: number;\r\n\tis404?: boolean;\r\n\tcachedAt: number;\r\n}\r\n\r\nexport class StaticPathCache {\r\n\tprivate cache = new Map<string, CacheEntry>();\r\n\r\n\tconstructor(\r\n\t\tprivate readonly maxSize = 2000,\r\n\t\tprivate readonly notFoundTtlMs = 30_000,\r\n\t) {}\r\n\r\n\tprivate touch(key: string, entry: CacheEntry): void {\r\n\t\tif (this.cache.has(key)) this.cache.delete(key);\r\n\t\tthis.cache.set(key, entry);\r\n\t\twhile (this.cache.size > this.maxSize) {\r\n\t\t\tconst oldest = this.cache.keys().next().value;\r\n\t\t\tif (!oldest) break;\r\n\t\t\tthis.cache.delete(oldest);\r\n\t\t}\r\n\t}\r\n\r\n\tget(key: string): CacheEntry | null {\r\n\t\tconst entry = this.cache.get(key);\r\n\t\tif (!entry) return null;\r\n\t\tif (entry.is404 && Date.now() - entry.cachedAt > this.notFoundTtlMs) {\r\n\t\t\tthis.cache.delete(key);\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\tthis.cache.delete(key);\r\n\t\tthis.cache.set(key, entry);\r\n\t\treturn entry;\r\n\t}\r\n\r\n\tsetHit(key: string, filePath: string, mtimeMs: number): void {\r\n\t\tthis.touch(key, { filePath, mtimeMs, cachedAt: Date.now() });\r\n\t}\r\n\r\n\tsetMiss(key: string): void {\r\n\t\tthis.touch(key, { filePath: '', mtimeMs: 0, is404: true, cachedAt: Date.now() });\r\n\t}\r\n\r\n\tverify(entry: CacheEntry): fs.Stats | null {\r\n\t\tif (entry.is404 || !entry.filePath) return null;\r\n\t\ttry {\r\n\t\t\tconst stat = fs.statSync(entry.filePath);\r\n\t\t\tif (!stat.isFile() || stat.mtimeMs !== entry.mtimeMs) return null;\r\n\t\t\treturn stat;\r\n\t\t} catch {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t}\r\n}\r\n","/**\r\n * http-security.ts — OWASP / IEC 62443-4-2 响应头与用户鉴权信息解析\r\n */\r\nimport { deUserInfoWithAsai } from '../utils/userinfo';\r\n\r\n/** 默认 CSP:兼容现有 inline 脚本;security.csp=1 时启用 */\r\nconst DEFAULT_CSP =\r\n\t\"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self' ws: wss:; font-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'\";\r\n\r\nexport function applySecurityHeaders(res: any, isHttps = false, hostconfig?: any): void {\r\n\tres.setHeader('X-Content-Type-Options', 'nosniff');\r\n\tres.setHeader('X-Frame-Options', 'SAMEORIGIN');\r\n\tres.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');\r\n\tres.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');\r\n\tres.setHeader('X-XSS-Protection', '0');\r\n\tres.setHeader('Cross-Origin-Opener-Policy', 'same-origin');\r\n\tres.setHeader('Cross-Origin-Resource-Policy', 'same-origin');\r\n\tif (isHttps) {\r\n\t\tres.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');\r\n\t}\r\n\tconst sec = hostconfig?.security;\r\n\tif (sec?.csp) {\r\n\t\tconst csp = typeof sec.cspPolicy === 'string' && sec.cspPolicy.length > 0 ? sec.cspPolicy : DEFAULT_CSP;\r\n\t\tres.setHeader('Content-Security-Policy', csp);\r\n\t}\r\n}\r\n\r\nexport function getHttpUserinfo(req: any, $asai: any): any {\r\n\ttry {\r\n\t\tconst userinfo = req.headers?.['userinfo']?.split('##');\r\n\t\treturn deUserInfoWithAsai(userinfo, $asai);\r\n\t} catch {\r\n\t\treturn '';\r\n\t}\r\n}\r\n\r\nexport function checkHttpHeader(req: any, $asai: any): boolean {\r\n\treq.Userinfo = getHttpUserinfo(req, $asai);\r\n\treturn true;\r\n}\r\n","/**\r\n * http-log.ts — HTTP 请求日志过滤(启动期编译 skip 规则,热路径 O(1))\r\n * IEC 62443-4-2:响应完成时双写 CLF + W3C Extended 访问日志\r\n */\r\nimport { buildAccessEntry, formatCLF, formatW3CAccessRecord } from '../sysserver/lib/common/log-formats';\r\n\r\nexport function formatHttpError(err: unknown): string {\r\n\treturn err instanceof Error ? `${err.name}: ${err.message}` : String(err);\r\n}\r\n\r\nexport function shouldLogRequest(method: string | undefined): boolean {\r\n\treturn method !== 'OPTIONS';\r\n}\r\n\r\nexport function normalizeRequestPath(url: string | undefined): string {\r\n\tif (!url) return '';\r\n\tconst q = url.indexOf('?');\r\n\tconst h = url.indexOf('#');\r\n\tlet end = url.length;\r\n\tif (q >= 0) end = Math.min(end, q);\r\n\tif (h >= 0) end = Math.min(end, h);\r\n\treturn url.slice(0, end);\r\n}\r\n\r\nexport type SkipChecker = (url: string | undefined) => boolean;\r\n\r\n/** 启动时编译 logger.skip,避免每请求遍历规则数组 */\r\nexport function createSkipChecker($asai: any): SkipChecker {\r\n\tconst skip = $asai.hostconfig?.logger?.skip;\r\n\tif (!Array.isArray(skip) || skip.length === 0) return () => false;\r\n\r\n\tconst exact = new Set<string>();\r\n\tconst prefixes: string[] = [];\r\n\tfor (const rule of skip) {\r\n\t\tif (typeof rule !== 'string' || !rule) continue;\r\n\t\tif (rule.endsWith('*')) prefixes.push(rule.slice(0, -1));\r\n\t\telse exact.add(rule);\r\n\t}\r\n\tif (exact.size === 0 && prefixes.length === 0) return () => false;\r\n\r\n\treturn (url: string | undefined) => {\r\n\t\tconst path = normalizeRequestPath(url);\r\n\t\tif (!path) return false;\r\n\t\tif (exact.has(path)) return true;\r\n\t\tfor (let i = 0; i < prefixes.length; i++) {\r\n\t\t\tif (path.startsWith(prefixes[i])) return true;\r\n\t\t}\r\n\t\treturn false;\r\n\t};\r\n}\r\n\r\nexport function logHttp(\r\n\t$asai: any,\r\n\ttype: string,\r\n\tmethod: string | undefined,\r\n\turl: string | undefined,\r\n\tskipChecker: SkipChecker,\r\n\treq?: any,\r\n\tres?: any,\r\n): void {\r\n\tif (!shouldLogRequest(method) || skipChecker(url)) return;\r\n\t$asai.$log(type, method, url);\r\n\tif (req && res && typeof $asai.appendAccessLog === 'function') {\r\n\t\tattachAccessLog($asai, req, res, type);\r\n\t}\r\n}\r\n\r\n/** 响应完成后写入 CLF + W3C 访问日志(需 status/bytes) */\r\nexport function attachAccessLog($asai: any, req: any, res: any, logType: string): void {\r\n\tif (res.__asaiAccessLogged) return;\r\n\tres.__asaiAccessLogged = true;\r\n\tconst onFinish = () => {\r\n\t\ttry {\r\n\t\t\tconst entry = buildAccessEntry(req, res, logType);\r\n\t\t\tvoid $asai.appendAccessLog(formatCLF(entry), formatW3CAccessRecord(entry));\r\n\t\t} catch {\r\n\t\t\t/* 访问日志写入失败不影响请求 */\r\n\t\t}\r\n\t};\r\n\tif (res.writableEnded || res.finished) onFinish();\r\n\telse res.once('finish', onFinish);\r\n}\r\n","/**\r\n * http/static.ts — 静态文件查找、缓存与响应(safe-path 防穿越 + ETag / SPA)\r\n */\r\nimport * as fs from 'fs';\r\nimport * as nodePath from 'path';\r\nimport { formatHttpError } from './log';\r\nimport { StaticPathCache } from './static-path-cache';\r\nimport { findExistingFileUnderRoots } from '../infra/safe-path';\r\nimport { buildStaticRoots, buildStaticSearchDirs } from './server-paths';\r\n\r\nconst STATIC_READ_MAX = 8 * 1024 * 1024;\r\n\r\nexport function parseUrlPath(requrl: string): string {\r\n try {\r\n if (!requrl) return '/';\r\n const safeUrl = requrl.startsWith('http') ? requrl : encodeURI(requrl);\r\n return new URL(safeUrl, 'http://localhost').pathname;\r\n } catch {\r\n return requrl;\r\n }\r\n}\r\n\r\nconst STATIC_ASSET_PREFIXES = ['/assets/', '/webmodel/', '/assets/entry/', '/assets/chunk/'];\r\n\r\nfunction isStaticAssetPath(urlPath: string, indexFile: string): boolean {\r\n const p = parseUrlPath(urlPath);\r\n const base = p.split('/').pop() || '';\r\n if (base === indexFile) return false;\r\n\r\n if (STATIC_ASSET_PREFIXES.some((prefix) => p.startsWith(prefix))) return true;\r\n return /\\.(css|js|mjs|cjs|json|png|jpe?g|gif|svg|ico|woff2?|ttf|map|wasm|zip)(\\?|$)/i.test(p);\r\n}\r\n\r\nfunction sendStaticBuffer(req: any, res: any, data: Buffer, mimeType: string, mtimeMs: number, $asai: any): void {\r\n const etag = `\"${data.length}-${mtimeMs}\"`;\r\n if (req.headers['if-none-match'] === etag) {\r\n res.writeHead(304);\r\n res.end();\r\n return;\r\n }\r\n try {\r\n res.writeHead(200, {\r\n 'Content-Type': mimeType,\r\n 'Content-Length': data.length,\r\n 'Cache-Control': 'public, max-age=3600',\r\n ETag: etag,\r\n 'Last-Modified': new Date(mtimeMs).toUTCString(),\r\n });\r\n res.end(data);\r\n } catch (err) {\r\n $asai.$log('HTTP', 'Static file response error:', formatHttpError(err));\r\n if (!res.headersSent) {\r\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Internal Server Error');\r\n }\r\n }\r\n}\r\n\r\nexport function serveStaticFile(req: any, res: any, foundPath: string, mimeType: string, stat: fs.Stats, $asai: any): void {\r\n if (stat.size <= STATIC_READ_MAX) {\r\n fs.readFile(foundPath, (err, data) => {\r\n if (err) {\r\n $asai.$log('HTTP', 'Static file read error:', formatHttpError(err));\r\n if (!res.headersSent) {\r\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Internal Server Error');\r\n }\r\n return;\r\n }\r\n sendStaticBuffer(req, res, data, mimeType, stat.mtimeMs, $asai);\r\n });\r\n return;\r\n }\r\n\r\n const readStream = fs.createReadStream(foundPath);\r\n const etag = `\"${stat.size}-${stat.mtimeMs}\"`;\r\n if (req.headers['if-none-match'] === etag) {\r\n readStream.destroy();\r\n res.writeHead(304);\r\n res.end();\r\n return;\r\n }\r\n\r\n readStream.on('error', (err) => {\r\n $asai.$log('STREAM', 'Stream error:', formatHttpError(err));\r\n if (!res.headersSent) {\r\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Internal Server Error');\r\n } else if (!res.writableEnded) res.destroy();\r\n });\r\n\r\n req.on('aborted', () => {\r\n if (!readStream.destroyed) readStream.destroy();\r\n });\r\n\r\n try {\r\n res.writeHead(200, {\r\n 'Content-Type': mimeType,\r\n 'Cache-Control': 'public, max-age=3600',\r\n ETag: etag,\r\n 'Last-Modified': stat.mtime.toUTCString(),\r\n });\r\n readStream.pipe(res);\r\n } catch (err) {\r\n $asai.$log('HTTP', 'Static file response error:', formatHttpError(err));\r\n if (!readStream.destroyed) readStream.destroy();\r\n if (!res.headersSent) {\r\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Internal Server Error');\r\n }\r\n }\r\n}\r\n\r\nexport interface StaticServeContext {\r\n hostcfg: any;\r\n hostdir: string;\r\n indexFile: string;\r\n $asai: any;\r\n staticPathCache: StaticPathCache;\r\n}\r\n\r\nexport function createStaticHandler(ctx: StaticServeContext): (req: any, res: any, url: string) => void {\r\n const { hostcfg, hostdir, indexFile, $asai, staticPathCache } = ctx;\r\n const hasRewrite = !!(hostcfg.weburls?.rewrite && hostcfg.weburls?.webdir && hostcfg.weburls?.keys?.length);\r\n const rewriteKeys: string[] = hasRewrite ? hostcfg.weburls?.keys || [] : [];\r\n\r\n const checkWebUrls = (rurl: string): boolean => {\r\n if (!hasRewrite || !rurl) return false;\r\n for (let i = 0; i < rewriteKeys.length; i++) {\r\n if (rurl.startsWith(rewriteKeys[i])) return true;\r\n }\r\n return false;\r\n };\r\n\r\n const showHostDirs = (\r\n req: any,\r\n res: any,\r\n rhostdirs: string[],\r\n rurl: string,\r\n primaryDirs: string[],\r\n rtm: number = 0,\r\n ): void => {\r\n const cleanUrl = parseUrlPath(rurl);\r\n const processedUrl = cleanUrl.endsWith('/') ? cleanUrl + indexFile : cleanUrl;\r\n const cacheKey = `${hostdir}:${rhostdirs.join('|')}:${processedUrl}`;\r\n const roots = rhostdirs.join('|') === primaryDirs.join('|')\r\n ? buildStaticRoots(primaryDirs, $asai)\r\n : buildStaticRoots(rhostdirs, $asai);\r\n\r\n const findValidFile = (urlPath: string): { filePath: string; stat: fs.Stats } | null => {\r\n const hit = staticPathCache.get(cacheKey);\r\n if (hit?.is404) return null;\r\n if (hit && !hit.is404) {\r\n const verified = staticPathCache.verify(hit);\r\n if (verified) return { filePath: hit.filePath, stat: verified };\r\n }\r\n\r\n const rel = urlPath.startsWith('/') ? urlPath.slice(1) : urlPath;\r\n const located = findExistingFileUnderRoots(rel, roots);\r\n if (located) {\r\n staticPathCache.setHit(cacheKey, located.filePath, located.stat.mtimeMs);\r\n return located;\r\n }\r\n\r\n staticPathCache.setMiss(cacheKey);\r\n return null;\r\n };\r\n\r\n const found = findValidFile(processedUrl);\r\n if (!found) {\r\n if (rtm > 0 || !hasRewrite || isStaticAssetPath(processedUrl, indexFile)) {\r\n res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('File not found!');\r\n return;\r\n }\r\n showHostDirs(req, res, [hostcfg.weburls!.webdir!], '/' + indexFile, primaryDirs, rtm + 1);\r\n return;\r\n }\r\n\r\n const mimeType = hostcfg.mimetypes?.[nodePath.extname(found.filePath)] || 'application/octet-stream';\r\n serveStaticFile(req, res, found.filePath, mimeType, found.stat, $asai);\r\n };\r\n\r\n return (req: any, res: any, url: string) => {\r\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');\r\n res.setHeader('Cross-Origin-Opener-Policy', 'cross-origin');\r\n\r\n const dirPath = buildStaticSearchDirs(hostcfg, $asai);\r\n if (!dirPath.length) {\r\n res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Static root not configured');\r\n return;\r\n }\r\n\r\n if (checkWebUrls(url)) {\r\n showHostDirs(req, res, [hostcfg.weburls!.webdir!], '/' + indexFile, dirPath);\r\n } else {\r\n showHostDirs(req, res, dirPath, url, dirPath);\r\n }\r\n };\r\n}\r\n","/**\r\n * 路径安全 — 禁止目录穿越,仅允许落在白名单根目录内(OWASP Path Traversal)\r\n */\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nexport function resolvePathUnderRoots(requestedPath: string, allowedRoots: string[]): string {\r\n\tif (!requestedPath || typeof requestedPath !== 'string') {\r\n\t\tthrow new Error('Invalid path');\r\n\t}\r\n\tif (requestedPath.includes('\\0')) {\r\n\t\tthrow new Error('Invalid path');\r\n\t}\r\n\r\n\tconst cleaned = requestedPath.replace(/\\\\/g, '/').trim();\r\n\tif (/^[a-zA-Z]:/.test(cleaned) || cleaned.startsWith('//')) {\r\n\t\tthrow new Error('Absolute paths are not allowed');\r\n\t}\r\n\r\n\tconst normalized = path.normalize(cleaned.replace(/^\\/+/, ''));\r\n\r\n\tfor (const root of allowedRoots) {\r\n\t\tif (!root) continue;\r\n\t\tconst absRoot = path.resolve(root);\r\n\t\tconst absTarget = path.resolve(absRoot, normalized);\r\n\t\tconst rel = path.relative(absRoot, absTarget);\r\n\t\tif (rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel))) {\r\n\t\t\treturn absTarget;\r\n\t\t}\r\n\t}\r\n\r\n\tthrow new Error('Path not allowed');\r\n}\r\n\r\n/** 在多个根目录中查找首个存在的文件(静态资源需遍历全部 hostdir) */\r\nexport function findExistingFileUnderRoots(\r\n\trequestedPath: string,\r\n\tallowedRoots: string[],\r\n): { filePath: string; stat: fs.Stats } | null {\r\n\tif (!requestedPath || typeof requestedPath !== 'string' || requestedPath.includes('\\0')) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst cleaned = requestedPath.replace(/\\\\/g, '/').trim();\r\n\tif (/^[a-zA-Z]:/.test(cleaned) || cleaned.startsWith('//')) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst normalized = path.normalize(cleaned.replace(/^\\/+/, ''));\r\n\r\n\tfor (const root of allowedRoots) {\r\n\t\tif (!root) continue;\r\n\t\ttry {\r\n\t\t\tconst absRoot = path.resolve(root);\r\n\t\t\tconst absTarget = path.resolve(absRoot, normalized);\r\n\t\t\tconst rel = path.relative(absRoot, absTarget);\r\n\t\t\tif (rel.startsWith('..') || path.isAbsolute(rel)) continue;\r\n\t\t\tconst stat = fs.statSync(absTarget);\r\n\t\t\tif (stat.isFile()) {\r\n\t\t\t\treturn { filePath: absTarget, stat };\r\n\t\t\t}\r\n\t\t} catch {\r\n\t\t\t/* try next root */\r\n\t\t}\r\n\t}\r\n\r\n\treturn null;\r\n}\r\n\r\n/** 从 hostconfig 推导允许读写的根目录 */\r\nexport function getHostAllowedRoots(hostconfig: any): string[] {\r\n\tconst roots = new Set<string>();\r\n\tconst push = (dir: unknown) => {\r\n\t\tif (typeof dir !== 'string' || !dir.trim()) return;\r\n\t\ttry {\r\n\t\t\tconst abs = path.resolve('./' + dir.replace(/\\\\/g, '/'));\r\n\t\t\tif (fs.existsSync(abs)) roots.add(abs);\r\n\t\t} catch {\r\n\t\t\t// skip invalid\r\n\t\t}\r\n\t};\r\n\tfor (const dir of hostconfig?.hostdirs || []) push(dir);\r\n\tpush('webdata');\r\n\tpush('websys');\r\n\tif (hostconfig?.weburls?.webdir) push(hostconfig.weburls.webdir);\r\n\tconst result: string[] = [];\r\n\troots.forEach((r) => result.push(r));\r\n\treturn result;\r\n}\r\n","/**\r\n * 静态资源根目录解析 — 兼容 pkg exe 嵌入资源 + exe/cwd 外挂目录\r\n * 基路径由 app.ts 注入 $asai.runtimeBaseDirs(见 src/utils/runtime-paths.ts)\r\n */\r\nimport * as fs from 'fs';\r\nimport * as nodePath from 'path';\r\n\r\n/** 静态 hostdirs 查找所用的全部基路径 */\r\nexport function getStaticBaseDirs($asai: any): string[] {\r\n const bases: string[] = [];\r\n const seen = new Set<string>();\r\n const add = (p: string | undefined) => {\r\n if (!p) return;\r\n const abs = nodePath.resolve(p);\r\n if (!seen.has(abs)) {\r\n seen.add(abs);\r\n bases.push(abs);\r\n }\r\n };\r\n\r\n if (Array.isArray($asai.runtimeBaseDirs)) {\r\n for (const b of $asai.runtimeBaseDirs) add(b);\r\n }\r\n if ($asai.serverRoot) add($asai.serverRoot);\r\n if ($asai.pkgSnapshotDir) add($asai.pkgSnapshotDir);\r\n\r\n return bases;\r\n}\r\n\r\n/** pkg 部署时 webclient 可能仅存在于 snapshot,不能依赖磁盘 stat */\r\nfunction shouldForceHostdirs($asai: any): boolean {\r\n if ($asai.pkgSnapshotDir) return true;\r\n return $asai.hostconfig?.pkg?.type === 1;\r\n}\r\n\r\nexport function buildStaticSearchDirs(hostcfg: any, $asai: any): string[] {\r\n const bases = getStaticBaseDirs($asai);\r\n const ordered: string[] = [];\r\n const seen = new Set<string>();\r\n\r\n const pushDir = (dir: string) => {\r\n if (!dir || seen.has(dir)) return;\r\n if (shouldForceHostdirs($asai)) {\r\n seen.add(dir);\r\n ordered.push(dir);\r\n return;\r\n }\r\n for (const base of bases) {\r\n try {\r\n if (fs.statSync(nodePath.resolve(base, dir)).isDirectory()) {\r\n seen.add(dir);\r\n ordered.push(dir);\r\n return;\r\n }\r\n } catch {\r\n /* try next base */\r\n }\r\n }\r\n };\r\n\r\n for (const dir of hostcfg.hostdirs || []) pushDir(dir);\r\n if (hostcfg.weburls?.webdir) pushDir(hostcfg.weburls.webdir);\r\n return ordered;\r\n}\r\n\r\nexport function buildStaticRoots(dirs: string[], $asai: any): string[] {\r\n const bases = getStaticBaseDirs($asai);\r\n const roots: string[] = [];\r\n const seen = new Set<string>();\r\n for (const base of bases) {\r\n for (const d of dirs) {\r\n const abs = nodePath.resolve(base, d);\r\n if (!seen.has(abs)) {\r\n seen.add(abs);\r\n roots.push(abs);\r\n }\r\n }\r\n }\r\n return roots;\r\n}\r\n","/**\n * http-connection.ts — HTTP 连接数监控与限流(ckhttp=1 时启用,与 v1 一致)\n */\n\n/** 注册连接监控:超 80% 告警、超 95% 清理空闲连接、达 maxhttp 上限拒绝新连接 */\nexport function setupHttpConnectionMonitor($asai: any, hostdir: string, server: any, hostcfg: any): void {\n\tconst maxHttp = hostcfg.maxhttp || 100;\n\tconst monitorInterval = setInterval(() => {\n\t\tconst connCount = $asai.connectionshttp[hostdir]?.size || 0;\n\t\tif (connCount > maxHttp * 0.8) {\n\t\t\t$asai.$log('HTTP', `HTTP Connection HIGH (${connCount}/${maxHttp})`);\n\t\t}\n\t\tif (connCount > maxHttp * 0.95) {\n\t\t\t$asai.$log('HTTP', 'HTTP Connection CRITICAL! Forcing cleanup');\n\t\t\tif ($asai.connectionshttp[hostdir]) {\n\t\t\t\t$asai.connectionshttp[hostdir].forEach((conn: any) => {\n\t\t\t\t\tif (conn._idleTime && Date.now() - conn._idleTime > 300000) {\n\t\t\t\t\t\tconn.destroy();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}, 300000);\n\n\tif (!$asai.tasksws[hostdir]) $asai.tasksws[hostdir] = {};\n\t$asai.tasksws[hostdir].httpMonitor = monitorInterval;\n\n\tserver.on('connection', (connection: any) => {\n\t\tif (!$asai.connectionshttp[hostdir]) {\n\t\t\t$asai.connectionshttp[hostdir] = new Set();\n\t\t}\n\t\tconst connCount = $asai.connectionshttp[hostdir].size;\n\t\tif (connCount >= maxHttp) {\n\t\t\ttry {\n\t\t\t\t$asai.$log('HTTP', `HTTP Connection MAX rejected (${connCount}/${maxHttp})`);\n\t\t\t\tconnection.destroy();\n\t\t\t} catch (err) {\n\t\t\t\t$asai.$log('HTTP', 'Close connection error:', err);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t$asai.connectionshttp[hostdir].add(connection);\n\t\tconnection.on('close', () => {\n\t\t\t$asai.connectionshttp[hostdir].delete(connection);\n\t\t});\n\t\tconnection.setTimeout(300000);\n\t});\n}\n","/**\r\n * port-release.ts — 启动前/冲突时释放占用端口(调试与部署均生效)\r\n */\r\nimport { execSync } from 'node:child_process';\r\nimport process from 'node:process';\r\nimport { validateHostdir, getHostCFG, getProxyHostCFG } from '../core/host-config';\r\n\r\nconst OWN_PID = process.pid;\r\n\r\nfunction sleepMs(ms: number): void {\r\n\tconst deadline = Date.now() + ms;\r\n\twhile (Date.now() < deadline) {\r\n\t\t/* 等待 OS 释放端口 */\r\n\t}\r\n}\r\n\r\n/** 查找监听指定端口的进程 PID(不含当前进程) */\r\nexport function findListeningPids(port: number): number[] {\r\n\tif (!Number.isInteger(port) || port < 1 || port > 65535) return [];\r\n\ttry {\r\n\t\tif (process.platform === 'win32') {\r\n\t\t\tconst out = execSync(`netstat -ano | findstr /R /C:\":${port} \"`, {\r\n\t\t\t\tencoding: 'utf8',\r\n\t\t\t\tstdio: ['pipe', 'pipe', 'ignore'],\r\n\t\t\t});\r\n\t\t\tconst pids = new Set<number>();\r\n\t\t\tfor (const line of out.split(/\\r?\\n/)) {\r\n\t\t\t\tconst parts = line.trim().split(/\\s+/);\r\n\t\t\t\tif (parts.length < 5 || parts[3] !== 'LISTENING') continue;\r\n\t\t\t\tconst localAddr = parts[1] || '';\r\n\t\t\t\tconst portMatch = localAddr.match(/:(\\d+)$/);\r\n\t\t\t\tconst pid = parseInt(parts[parts.length - 1]!, 10);\r\n\t\t\t\tif (portMatch && parseInt(portMatch[1]!, 10) === port && pid > 0) {\r\n\t\t\t\t\tpids.add(pid);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn [...pids];\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tconst out = execSync(`lsof -nP -iTCP:${port} -sTCP:LISTEN -t`, {\r\n\t\t\t\tencoding: 'utf8',\r\n\t\t\t\tstdio: ['pipe', 'pipe', 'ignore'],\r\n\t\t\t});\r\n\t\t\treturn out\r\n\t\t\t\t.split(/\\r?\\n/)\r\n\t\t\t\t.map((s) => parseInt(s.trim(), 10))\r\n\t\t\t\t.filter((n) => n > 0);\r\n\t\t} catch {\r\n\t\t\treturn [];\r\n\t\t}\r\n\t} catch {\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\nfunction killPid(pid: number): boolean {\r\n\tif (!pid || pid === OWN_PID || pid <= 4) return false;\r\n\ttry {\r\n\t\tif (process.platform === 'win32') {\r\n\t\t\texecSync(`taskkill /PID ${pid} /F`, { stdio: 'ignore' });\r\n\t\t} else {\r\n\t\t\texecSync(`kill -9 ${pid}`, { stdio: 'ignore' });\r\n\t\t}\r\n\t\treturn true;\r\n\t} catch {\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/** 结束占用端口的进程;成功释放或原本空闲则返回 true */\r\nexport function releasePort(\r\n\tport: number,\r\n\topts?: { excludePid?: number; label?: string },\r\n): boolean {\r\n\tconst exclude = opts?.excludePid ?? OWN_PID;\r\n\tconst occupants = findListeningPids(port).filter((p) => p !== exclude && p !== OWN_PID);\r\n\tif (!occupants.length) return true;\r\n\r\n\tconst label = opts?.label ? `[${opts.label}] ` : '';\r\n\tconsole.warn(`[AsaiHost] ${label}端口 ${port} 被占用,正在结束进程: ${occupants.join(', ')}`);\r\n\tfor (const pid of occupants) {\r\n\t\tkillPid(pid);\r\n\t}\r\n\tsleepMs(500);\r\n\r\n\tconst remaining = findListeningPids(port).filter((p) => p !== exclude && p !== OWN_PID);\r\n\treturn remaining.length === 0;\r\n}\r\n\r\n/** 收集本次启动将监听的端口 */\r\nexport function collectStartupPorts($asai: any): number[] {\r\n\tconst ports = new Set<number>();\r\n\tconst hosts = $asai.hostconfig?.hosts;\r\n\tif (hosts) {\r\n\t\tfor (const el of Object.keys(hosts)) {\r\n\t\t\tif (el === 'default') continue;\r\n\t\t\tif (el !== 'asai' && !validateHostdir(el)) continue;\r\n\t\t\tconst cfg = getHostCFG(el, $asai);\r\n\t\t\tif (cfg?.close) continue;\r\n\t\t\tif (cfg?.port) ports.add(Number(cfg.port));\r\n\t\t}\r\n\t\t// default 仅作模板,不单独监听;端口由合并后的具名站点承担\r\n\t}\r\n\tconst proxyhosts = $asai.hostconfig?.proxyhosts;\r\n\tif (proxyhosts) {\r\n\t\tfor (const el of Object.keys(proxyhosts)) {\r\n\t\t\tif (el === 'default') continue;\r\n\t\t\tif (!validateHostdir(el)) continue;\r\n\t\t\tconst cfg = getProxyHostCFG(el, $asai);\r\n\t\t\tif (cfg?.proxyport) ports.add(Number(cfg.proxyport));\r\n\t\t}\r\n\t}\r\n\treturn [...ports];\r\n}\r\n\r\n/** 启动前批量释放配置端口上的残留进程 */\r\nexport function releaseConfiguredPorts($asai: any): void {\r\n\tfor (const port of collectStartupPorts($asai)) {\r\n\t\treleasePort(port, { excludePid: process.pid });\r\n\t}\r\n}\r\n","/**\r\n * proxy-server.ts — 反向代理服务\r\n *\r\n * 将外部请求转发到 proxyhosts 配置的目标地址。\r\n * 性能:Agent 按 proxyhostdir 复用,避免每请求 new Agent 导致连接无法 keepAlive。\r\n */\r\nimport { getProxyHostCFG, getHostIP, getNowTime } from '../core';\r\nimport { getHTTPServer, getHttpUserinfo } from '../http/server';\r\nimport { releasePort } from '../infra/port-release';\r\n\r\n/** 代理响应中需跳过的 hop-by-hop 头 */\r\nconst PROXY_SKIP_HEADERS = new Set([\r\n 'transfer-encoding', 'connection', 'keep-alive',\r\n 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'upgrade',\r\n]);\r\n\r\nexport function startProxyServer($asai: any, proxyhostdir: string): void {\r\n const proxycfg = getProxyHostCFG(proxyhostdir, $asai);\r\n if (!proxycfg.url) return;\r\n if ($asai.serversproxy?.[proxyhostdir]) return;\r\n\r\n try {\r\n const httpServer = getHTTPServer(proxycfg.proxyhttptype, proxycfg, $asai);\r\n const targetHttp = getHTTPServer(proxycfg.url!, proxycfg, $asai);\r\n // 目标地址只解析一次,每请求仅拼接 path\r\n const targetBaseUrl = new URL(proxycfg.url!);\r\n const isHttpsTarget = targetBaseUrl.protocol === 'https:';\r\n const defaultTargetPort = isHttpsTarget ? 443 : 80;\r\n\r\n // Agent 复用:同一代理实例共享连接池\r\n const sharedAgent = new targetHttp.Agent({\r\n keepAlive: proxycfg.keepAlive ?? true,\r\n timeout: proxycfg.timeout ?? 60000,\r\n keepAliveMsecs: proxycfg.keepAliveMsecs ?? 30000,\r\n maxSockets: proxycfg.maxSockets ?? 1000,\r\n maxFreeSockets: proxycfg.maxFreeSockets ?? 100,\r\n rejectUnauthorized: proxycfg.rejectUnauthorized ?? false,\r\n secureProtocol: proxycfg.secureProtocol ?? 'TLS_method',\r\n });\r\n\r\n const proxyServer = (httpServer as any).AsCreateServer((req: any, res: any) => {\r\n if (proxycfg.redirect) {\r\n res.writeHead(301, {\r\n Location: proxycfg.url + req.url,\r\n 'Strict-Transport-Security': 'max-age=31536000',\r\n });\r\n res.end();\r\n return;\r\n }\r\n\r\n const targetUrl = new URL(req.url || '/', targetBaseUrl);\r\n\r\n // [安全] 转发前剥离 hop-by-hop 头(RFC 7230),仅传递端到端头,\r\n // 避免连接复用异常与请求走私风险\r\n const forwardHeaders: Record<string, any> = {};\r\n for (const key of Object.keys(req.headers)) {\r\n if (!PROXY_SKIP_HEADERS.has(key.toLowerCase())) {\r\n forwardHeaders[key] = req.headers[key];\r\n }\r\n }\r\n\r\n const reqParams: any = {\r\n agent: sharedAgent,\r\n method: req.method,\r\n hostname: targetUrl.hostname,\r\n port: targetUrl.port || defaultTargetPort,\r\n path: targetUrl.pathname + targetUrl.search,\r\n headers: forwardHeaders,\r\n };\r\n if (isHttpsTarget) {\r\n reqParams.servername = targetUrl.hostname;\r\n }\r\n\r\n // [优化] 增加 passUserInfo 配置开关(默认关闭),避免透传用户信息给第三方服务\r\n const passUserInfo = proxycfg.passUserInfo ?? false;\r\n\r\n const forwardRequest = targetHttp.request(reqParams, (forwardRes: any) => {\r\n Object.keys(forwardRes.headers).forEach((key) => {\r\n if (!PROXY_SKIP_HEADERS.has(key.toLowerCase())) {\r\n res.setHeader(key, forwardRes.headers[key]!);\r\n }\r\n });\r\n res.statusCode = forwardRes.statusCode!;\r\n if (passUserInfo) {\r\n const userinfo = getHttpUserinfo(req, $asai);\r\n if (userinfo) res.setHeader('Userinfo', Array.isArray(userinfo) ? userinfo.join('##') : userinfo);\r\n }\r\n forwardRes.pipe(res, { end: true });\r\n });\r\n\r\n req.pipe(forwardRequest, { end: true });\r\n\r\n req.on('error', (err: any) => {\r\n $asai.$log('PROXY', 'Client request error:', err);\r\n forwardRequest.destroy();\r\n });\r\n\r\n forwardRequest.on('error', (err: Error) => {\r\n $asai.$log('PROXY', 'Forward request error:', err);\r\n $asai.$log('PROXY', `Target: ${targetUrl.href}, HTTPS: ${isHttpsTarget}`);\r\n if (!res.headersSent) {\r\n res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n }\r\n res.end('Bad Gateway: ' + err.message);\r\n });\r\n\r\n forwardRequest.setTimeout(120000, () => {\r\n $asai.$log('PROXY', 'Forward request timeout');\r\n forwardRequest.destroy();\r\n if (!res.headersSent) {\r\n res.writeHead(504, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n }\r\n res.end('Gateway Timeout');\r\n });\r\n });\r\n\r\n proxyServer.on('error', (err: any) => {\r\n if (err.code === 'EADDRINUSE') {\r\n $asai.$log('PROXY', `\\x1B[41mPort ${proxycfg.proxyport} is already start!\\x1B[0m`);\r\n delete $asai.serversproxy?.[proxyhostdir];\r\n const released = releasePort(proxycfg.proxyport, {\r\n excludePid: process.pid,\r\n label: proxyhostdir,\r\n });\r\n if (released) {\r\n console.warn(`[AsaiHost] 代理端口 ${proxycfg.proxyport} 已释放,正在重新启动 [${proxyhostdir}]`);\r\n setTimeout(() => startProxyServer($asai, proxyhostdir), $asai.hostconfig.tm?.d || 2000);\r\n }\r\n } else {\r\n $asai.$log('PROXY', 'Proxy server error:', err);\r\n }\r\n });\r\n\r\n if (!$asai.serversproxy) $asai.serversproxy = {};\r\n $asai.serversproxy[proxyhostdir] = proxyServer;\r\n\r\n releasePort(proxycfg.proxyport, { excludePid: process.pid, label: proxyhostdir });\r\n\r\n const listenIp = getHostIP(proxycfg.proxyip, $asai);\r\n const listenCallback = () => {\r\n console.log(`[${proxyhostdir}] Start At ${getNowTime()}.`);\r\n console.log(`\\x1B[45;28mProxy Server ${proxycfg.proxyhttptype}${listenIp || 'localhost'}:${proxycfg.proxyport}\\x1B[0m`);\r\n console.log(`\\x1B[46;28mTarget Server ${proxycfg.url}\\x1B[0m`);\r\n console.log(`================================================`);\r\n };\r\n\r\n if (listenIp) {\r\n proxyServer.listen(proxycfg.proxyport, listenIp, listenCallback);\r\n } else {\r\n proxyServer.listen(proxycfg.proxyport, listenCallback);\r\n }\r\n } catch (err) {\r\n $asai.$log('PROXY', 'Proxy server error:', JSON.stringify(err));\r\n }\r\n}\r\n","export { deUserInfoWithAsai } from './userinfo';\r\nexport { wsMock } from './ws-mock';\r\n","/** WebSocket Mock — api 单次响应 / listen 定时推送 */\r\nexport function wsMock($asai: any) {\r\n\tfunction getKeyByData(reqdata: any, hostdir?: string) {\r\n\t\treturn '_wstask_' + (hostdir || '') + '_' + (reqdata?.id || reqdata?.ty + '.' + reqdata?.ac);\r\n\t}\r\n\r\n\tfunction getMockDb(workopt: any) {\r\n\t\tconst { reqdata, mockdata } = workopt;\r\n\t\tconst wsfn = mockdata?.fn ? $asai.asaimock.fn?.[mockdata.fn] : null;\r\n\t\tif (wsfn) return wsfn({ workopt, $asai, mockName: mockdata.fn });\r\n\t\treturn { ...reqdata, ...(mockdata || {}) };\r\n\t}\r\n\r\n\tfunction wsWorkApi(workopt: any) {\r\n\t\t$asai.serversws[workopt.hostdir]?.sendws?.(workopt.reqdataisobj ? getMockDb(workopt) : workopt.reqdata, 0, workopt.ws);\r\n\t}\r\n\r\n\tfunction wsWorkListen(workopt: any, reqkey: any) {\r\n\t\tif (workopt.reqdata?.off) {\r\n\t\t\tif ($asai.tasksws[workopt.hostdir][reqkey]) {\r\n\t\t\t\tclearInterval($asai.tasksws[workopt.hostdir][reqkey]);\r\n\t\t\t\t$asai.tasksws[workopt.hostdir][reqkey] = null;\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif ($asai.tasksws[workopt.hostdir][reqkey]) return;\r\n\r\n\t\tconst newDataMock = getMockDb(workopt);\r\n\t\t$asai.tasksws[workopt.hostdir][reqkey] = setInterval(() => {\r\n\t\t\tconst newData = { ...getMockDb(workopt), tm: Date.now() };\r\n\t\t\t$asai.serversws[workopt.hostdir].sendws(newData, newData.pb || 2, workopt.ws);\r\n\t\t\tif (!$asai.tasksws[workopt.hostdir][reqkey]) {\r\n\t\t\t\tclearInterval($asai.tasksws[workopt.hostdir][reqkey]);\r\n\t\t\t}\r\n\t\t}, newDataMock?.tc || 2000);\r\n\r\n\t\tworkopt.ws?.once?.('close', () => {\r\n\t\t\tif ($asai.tasksws[workopt.hostdir]?.[reqkey]) {\r\n\t\t\t\tclearInterval($asai.tasksws[workopt.hostdir][reqkey]);\r\n\t\t\t\tdelete $asai.tasksws[workopt.hostdir][reqkey];\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tfunction wsWorkMock(workopt: any) {\r\n\t\tworkopt.mockdata = (workopt.reqdataisobj && $asai.asaimock?.db?.[workopt.hostdir]?.[workopt.reqdata?.ty]) || {};\r\n\t\tif (workopt.mockdata?.wc) {\r\n\t\t\twsWorkListen(workopt, getKeyByData(workopt.reqdata, workopt.hostdir));\r\n\t\t} else {\r\n\t\t\twsWorkApi(workopt);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { getKeyByData, wsWorkApi, wsWorkMock, wsWorkListen, getMockDb };\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 1 / CR 2 — 服务端权威用户等级(禁止信任客户端 Userinfo 中的 lv)\r\n */\r\nexport interface ServerUserSnapshot {\r\n\tus: string;\r\n\tlv: number;\r\n\tstatus: string;\r\n}\r\n\r\n/** 从 userStore 加载真实 lv/status,覆盖客户端可伪造的 Userinfo[1] */\r\nexport async function attachServerUserLevel(req: any, $asai: any): Promise<void> {\r\n\tconst userinfo = req?.Userinfo;\r\n\tif (!Array.isArray(userinfo) || !userinfo[0]) return;\r\n\tconst us = String(userinfo[0]);\r\n\ttry {\r\n\t\tconst { createUserStore } = await import('../sysserver/api/login/store/user-store');\r\n\t\tconst user = await createUserStore($asai).findByUsername(us);\r\n\t\tif (user && user.status === 'active') {\r\n\t\t\treq._serverUser = { us: user.us, lv: user.lv, status: user.status } satisfies ServerUserSnapshot;\r\n\t\t\treq.Userinfo[1] = String(user.lv);\r\n\t\t} else {\r\n\t\t\treq._serverUser = null;\r\n\t\t}\r\n\t} catch {\r\n\t\treq._serverUser = null;\r\n\t}\r\n}\r\n\r\nexport function getRequestUserLevel(req: any): number {\r\n\tif (req?._serverUser?.lv != null) return Number(req._serverUser.lv);\r\n\tconst n = Number(req?.Userinfo?.[1] ?? -1);\r\n\treturn Number.isFinite(n) ? n : -1;\r\n}\r\n\r\nexport function getRequestUsername(req: any): string | undefined {\r\n\tif (req?._serverUser?.us) return String(req._serverUser.us);\r\n\tconst us = req?.Userinfo?.[0];\r\n\treturn us ? String(us) : undefined;\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 1 / CR 2 — 可选 HTTP 鉴权与访问控制\r\n * 默认关闭(requireAuth=0),不影响现有未鉴权 API 行为。\r\n */\r\nimport { logSecurityEvent, getClientIp } from './security-audit';\r\nimport { attachServerUserLevel, getRequestUserLevel } from './user-auth';\r\n\r\nexport interface AuthCheckResult {\r\n\tok: boolean;\r\n\tcode?: number;\r\n\tmessage?: string;\r\n}\r\n\r\nfunction getSecurityConfig($asai: any): Record<string, unknown> {\r\n\treturn ($asai?.hostconfig?.security as Record<string, unknown>) || {};\r\n}\r\n\r\nfunction pathMatchesPattern(path: string, pattern: string): boolean {\r\n\tif (pattern.endsWith('*')) {\r\n\t\treturn path.startsWith(pattern.slice(0, -1));\r\n\t}\r\n\treturn path === pattern;\r\n}\r\n\r\n/** 路径是否在 authSkipPaths 白名单内 */\r\nexport function isAuthSkipped($asai: any, pathname: string): boolean {\r\n\tconst sec = getSecurityConfig($asai);\r\n\tconst skipPaths = (sec.authSkipPaths as string[]) || [\r\n\t\t'/api/asailog/*',\r\n\t\t'/api/sys/errorcodes/*',\r\n\t\t'/api/user/login/auth/*',\r\n\t\t'/api/user/login/register/*',\r\n\t\t'/sys/info/*',\r\n\t\t'/jsonp/*',\r\n\t];\r\n\treturn skipPaths.some((p) => pathMatchesPattern(pathname, p));\r\n}\r\n\r\nexport function isAuthRequired($asai: any, pathname: string): boolean {\r\n\tconst sec = getSecurityConfig($asai);\r\n\tif (!sec.requireAuth) return false;\r\n\tif (isAuthSkipped($asai, pathname)) return false;\r\n\treturn true;\r\n}\r\n\r\nfunction parseUserLevel(level: unknown): number {\r\n\tconst n = Number(level);\r\n\treturn Number.isFinite(n) ? n : -1;\r\n}\r\n\r\n/** 校验 Userinfo 头(us##lv##tk),仅在 requireAuth=1 时由路由层调用 */\r\nexport function validateHttpAuth(req: any, $asai: any, pathname: string): AuthCheckResult {\r\n\tif (!isAuthRequired($asai, pathname)) {\r\n\t\treturn { ok: true };\r\n\t}\r\n\r\n\tconst userinfo = req?.Userinfo;\r\n\tconst ip = getClientIp(req);\r\n\r\n\tif (!Array.isArray(userinfo) || userinfo.length < 3 || !userinfo[0]) {\r\n\t\tlogSecurityEvent($asai, {\r\n\t\t\ttype: 'AUTH_MISSING',\r\n\t\t\tpath: pathname,\r\n\t\t\tmethod: req?.method,\r\n\t\t\tip,\r\n\t\t\tdetail: 'Userinfo header missing or invalid',\r\n\t\t});\r\n\t\treturn { ok: false, code: 401, message: 'Authentication required' };\r\n\t}\r\n\r\n\tconst [us] = userinfo;\r\n\tconst sec = getSecurityConfig($asai);\r\n\tconst minLevel = typeof sec.minUserLevel === 'number' ? sec.minUserLevel : 0;\r\n\tconst userLevel = getRequestUserLevel(req);\r\n\r\n\tif (userLevel < minLevel) {\r\n\t\tlogSecurityEvent($asai, {\r\n\t\t\ttype: 'ACCESS_DENIED',\r\n\t\t\tpath: pathname,\r\n\t\t\tmethod: req?.method,\r\n\t\t\tuser: String(us),\r\n\t\t\tlevel: userLevel,\r\n\t\t\tip,\r\n\t\t\tdetail: `minLevel=${minLevel}`,\r\n\t\t});\r\n\t\treturn { ok: false, code: 403, message: 'Insufficient privileges' };\r\n\t}\r\n\r\n\treturn { ok: true };\r\n}\r\n\r\n/** 鉴权前附加服务端权威 lv(CR 2.1) */\r\nexport async function validateHttpAuthAsync(req: any, $asai: any, pathname: string): Promise<AuthCheckResult> {\r\n\tif (Array.isArray(req?.Userinfo) && req.Userinfo[0]) {\r\n\t\tawait attachServerUserLevel(req, $asai);\r\n\t\tif (!req._serverUser && isAuthRequired($asai, pathname)) {\r\n\t\t\tlogSecurityEvent($asai, {\r\n\t\t\t\ttype: 'ACCESS_DENIED',\r\n\t\t\t\tpath: pathname,\r\n\t\t\t\tmethod: req?.method,\r\n\t\t\t\tuser: String(req.Userinfo[0]),\r\n\t\t\t\tip: getClientIp(req),\r\n\t\t\t\tdetail: 'User not found or inactive',\r\n\t\t\t});\r\n\t\t\treturn { ok: false, code: 403, message: 'Invalid user session' };\r\n\t\t}\r\n\t}\r\n\treturn validateHttpAuth(req, $asai, pathname);\r\n}\r\n\r\nexport function sendAuthError(res: any, result: AuthCheckResult): void {\r\n\tres.writeHead(result.code || 401, { 'Content-Type': 'application/json; charset=utf-8' });\r\n\tres.end(JSON.stringify({ error: result.message || 'Unauthorized' }));\r\n}\r\n","/**\n * hosts.default / hosts.<site> 连接与 CORS 参数解析\n * 对应 asaihost.json: ws, ckhttp, ckws, close, maxhttp, maxws, maxonline, oncors\n */\n\nexport interface HostSiteLimits {\n\tclose: boolean;\n\tws: boolean;\n\tckhttp: boolean;\n\tckws: boolean;\n\toncors: boolean;\n\tmaxhttp: number;\n\tmaxws: number;\n\tmaxonline: number;\n}\n\nexport function flagOn(value: unknown): boolean {\n\treturn value === 1 || value === true;\n}\n\n/** 解析合并后的站点配置(getHostCFG 结果) */\nexport function resolveHostSiteLimits(hostcfg: Record<string, unknown> | null | undefined): HostSiteLimits {\n\tconst cfg = hostcfg || {};\n\treturn {\n\t\tclose: flagOn(cfg.close),\n\t\tws: flagOn(cfg.ws),\n\t\tckhttp: flagOn(cfg.ckhttp),\n\t\tckws: flagOn(cfg.ckws),\n\t\toncors: flagOn(cfg.oncors),\n\t\tmaxhttp: positiveInt(cfg.maxhttp, 2000),\n\t\tmaxws: positiveInt(cfg.maxws, 2000),\n\t\tmaxonline: positiveInt(cfg.maxonline, 100),\n\t};\n}\n\nfunction positiveInt(value: unknown, fallback: number): number {\n\tconst n = Number(value);\n\treturn Number.isInteger(n) && n > 0 ? n : fallback;\n}\n\n/** 启动前为 hosts.default 填充缺省值 */\nexport function normalizeHostSiteDefaults(host: Record<string, unknown>): void {\n\tif (host.close == null) host.close = 0;\n\tif (host.ws == null) host.ws = 0;\n\tif (host.ckhttp == null) host.ckhttp = 0;\n\tif (host.ckws == null) host.ckws = 0;\n\tif (host.oncors == null) host.oncors = 0;\n\tif (host.maxhttp == null) host.maxhttp = 2000;\n\tif (host.maxws == null) host.maxws = 2000;\n\tif (host.maxonline == null) host.maxonline = 100;\n\tif (!Array.isArray(host.cors)) host.cors = [];\n}\n\n/** 严格 CORS:oncors=1 时校验 cors 白名单 */\nexport function resolveApiCorsOrigin(\n\treq: { headers?: Record<string, string | string[] | undefined> },\n\thostcfg: Record<string, unknown> | null | undefined,\n\tgetHeader: (req: unknown, key: string) => string,\n): string | null {\n\tconst limits = resolveHostSiteLimits(hostcfg);\n\tif (!limits.oncors) return '*';\n\n\tlet origin = getHeader(req, 'Origin');\n\tif (!origin) {\n\t\tconst referer = getHeader(req, 'Referer');\n\t\tif (referer) {\n\t\t\ttry {\n\t\t\t\torigin = new URL(referer).origin;\n\t\t\t} catch {\n\t\t\t\tconst parts = referer.split('/');\n\t\t\t\tif (parts.length >= 3) origin = `${parts[0]}//${parts[2]}`;\n\t\t\t}\n\t\t}\n\t}\n\treturn origin || null;\n}\n\nexport function isApiCorsAllowed(\n\torigin: string | null,\n\thostcfg: Record<string, unknown> | null | undefined,\n\thostHeader: string,\n): boolean {\n\tif (!origin) return false;\n\tif (origin === '*') return true;\n\tconst corsList = hostcfg?.cors;\n\tif (!Array.isArray(corsList) || !corsList.length) return true;\n\tif (corsList.includes(origin)) return true;\n\tif (hostHeader && origin.includes(hostHeader)) return true;\n\treturn false;\n}\n","/**\n * Api.ts — HTTP API 路由分发\n * /api/* 请求经 CORS 校验后,按 hostserverapis 前缀匹配到对应插件处理器。\n */\nimport { validateHttpAuthAsync, sendAuthError } from '../../infra/access-control';\nimport { acquireApiSlot, releaseApiSlot } from '../../infra/connection-quota';\nimport { isApiCorsAllowed, resolveApiCorsOrigin } from '../../infra/host-limits';\nimport { getClientIp } from '../../infra/security-audit';\n\nexport default ($asai: any, opt: any = {}) => {\n opt?.fn?.($asai);\n\n // 统一头信息获取\n function getHeader(req: any, key: string): string {\n return req.headers[key.toLowerCase()] || '';\n }\n /** API 路由表缓存(hostserverapis 启动后不变) */\n let apiRouteCache: { key: string; path: string }[] | null = null;\n let apiRouteCacheLen = -1;\n\n function findApiHandler($asai: any, pathname: string) {\n const apis = $asai.hostserverapis;\n if (!apis?.length) return undefined;\n if (!apiRouteCache || apiRouteCacheLen !== apis.length) {\n apiRouteCache = apis.map((elp: string) => ({ key: elp, path: `/api/${elp}` }));\n apiRouteCacheLen = apis.length;\n }\n if (!apiRouteCache) return undefined;\n for (let i = 0; i < apiRouteCache.length; i++) {\n const route = apiRouteCache[i];\n if (pathname === route.path || pathname.startsWith(route.path)) {\n return route.key;\n }\n }\n return undefined;\n }\n // 统一错误响应\n function sendError(res: any, code: number, message: string) {\n res.writeHead(code, {\n 'Content-Type': 'application/json; charset=utf-8',\n });\n res.end(JSON.stringify({ error: message }));\n }\n function apiWork(req: any, res: any, hostdir: string) {\n const hostcfg: any = $asai.getHost(hostdir);\n const origin = resolveApiCorsOrigin(req, hostcfg, getHeader);\n const host: any = getHeader(req, 'Host');\n if (isApiCorsAllowed(origin, hostcfg, host)) {\n res.setHeader('Access-Control-Allow-Origin', origin === '*' ? '*' : origin!);\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type,userinfo,authorization,x-file-name');\n\n // 处理预检请求\n if (req.method === 'OPTIONS') {\n res.statusCode = 204;\n return res.end();\n }\n let pm: string = '';\n let isAes: boolean = false;\n let urlParse: any, pathname: string, query: any;\n // try {\n // urlParse = url.parse(req.url, true);\n // pathname = urlParse.pathname;\n // query = urlParse.query;\n // } catch (err) {\n urlParse = new URL(req.url, `http://${getHeader(req, 'Host')}`);\n pathname = urlParse.pathname;\n if ($asai.$lib.aesfns && urlParse.search.startsWith('?aes=')) {\n isAes = true;\n urlParse.search = $asai.$lib.aesfns.reqAES({ data: JSON.parse(decodeURIComponent(urlParse.search.substring(5))) });\n }\n if (urlParse.search.startsWith('?pm=')) {\n query = {\n pm: decodeURIComponent(urlParse.search.substring(4)),\n };\n if (req.url.indexOf('binary') === -1) {\n // pm是路由上面解密\n if (req?.Userinfo && req?.Userinfo[2] && query?.pm) {\n pm = req.Userinfo[2];\n // 解密get加密的请求\n query = $asai.$lib.AsCode.asdecode(query?.pm, pm);\n query = Object.fromEntries(new URLSearchParams('?' + query).entries());\n }\n }\n } else {\n query = Object.fromEntries(new URLSearchParams(urlParse.search).entries());\n }\n // }\n // $asai.hostconfig.logger?.lv?.view && console.log(`\\x1B[45m${pathname}\\x1B[0m`, query);\n\n const apiHandlerKey = findApiHandler($asai, pathname);\n if (!apiHandlerKey) {\n return sendError(res, 404, 'Not Found');\n }\n const clientIp = getClientIp(req);\n const apiSlot = acquireApiSlot($asai, hostdir, clientIp);\n if (!apiSlot.ok) {\n return sendError(res, apiSlot.code || 429, apiSlot.message || 'Quota exceeded');\n }\n const releaseSlot = () => releaseApiSlot(hostdir, clientIp);\n res.once('finish', releaseSlot);\n res.once('close', releaseSlot);\n void (async () => {\n const authResult = await validateHttpAuthAsync(req, $asai, pathname);\n if (!authResult.ok) {\n releaseSlot();\n return sendAuthError(res, authResult);\n }\n // 获取处理器\n let apiFn: any = $asai.hostserverapi[apiHandlerKey]?.($asai, query);\n if (!apiFn) {\n return sendError(res, 501, 'Not Implemented');\n }\n // 设置通用响应头\n res.setHeader('Content-Type', 'application/json; charset=utf-8');\n\n $asai.$log('API', req.method, urlParse.pathname, query);\n // 处理地址栏上带的数据qrdata\n let qrdata: any;\n let postdata: any;\n if (req.url.indexOf('binary') === -1) {\n postdata = '';\n qrdata = query;\n if (req.method === 'POST') {\n // 使用 Buffer 数组拼接,避免大 body 时字符串反复拷贝\n const chunks: Buffer[] = [];\n // [安全] 限制请求体最大体积,防止超大/慢速 body 耗尽内存(DoS)\n const maxBody = $asai.hostconfig?.maxbody || 100 * 1024 * 1024;\n let received = 0;\n let aborted = false;\n req.on('data', (chunk: Buffer) => {\n if (aborted) return;\n received += chunk.length;\n if (received > maxBody) {\n aborted = true;\n sendError(res, 413, 'Payload Too Large');\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n if (aborted) return;\n postdata = Buffer.concat(chunks).toString();\n // ----aes----0011\n isAes = $asai.$lib.aesfns && postdata?.startsWith?.('{\"aes\":');\n if (isAes) {\n const aesData: any = JSON.parse(postdata);\n postdata = $asai.$lib.aesfns.reqAES({ data: aesData });\n if (aesData?.aes === 2) {\n try {\n postdata = JSON.parse(postdata);\n } catch (err) {}\n }\n }\n // ----aes----0012\n if (req?.Userinfo && req?.Userinfo[2]) {\n pm = req.Userinfo[2];\n // 解密post加密的请求\n postdata = $asai.$lib.AsCode.asdecode(postdata, pm);\n }\n // POST请求分发阶段\n if (apiFn?.post && typeof apiFn?.post === 'function') {\n const optTmp: any = { qrdata, data: postdata, pm };\n // ----aes----0021\n if (isAes || $asai.$lib.aesfns?.allaes) {\n optTmp.resAES = $asai.$lib.aesfns?.resAES;\n }\n // ----aes----0022\n apiFn.post(req, res, hostdir, optTmp);\n } else {\n res.end(postdata);\n }\n });\n } else if (req.method === 'GET') {\n // GET请求分发阶段\n if (apiFn?.get && typeof apiFn?.get === 'function') {\n // 保持有qrdata\n const optTmp: any = { qrdata, data: qrdata, pm };\n // ----aes----0061\n if (isAes || $asai.$lib.aesfns?.allaes) {\n optTmp.resAES = $asai.$lib.aesfns?.resAES;\n }\n // ----aes----0062\n apiFn.get(req, res, hostdir, optTmp);\n } else {\n res.end(JSON.stringify(qrdata));\n }\n }\n } else {\n // 二进制接口\n if (Object.keys(query)?.length) {\n qrdata = query;\n }\n if (req.method === 'POST') {\n $asai.$lib.AsNodeTool.upBinary(req)\n .then((postdata: any) => {\n // POST请求分发阶段\n if (apiFn?.post && typeof apiFn?.post === 'function') {\n apiFn.post(req, res, hostdir, {\n qrdata,\n data: postdata,\n });\n } else {\n res.end(postdata);\n }\n })\n .catch((err: any) => {\n return sendError(res, 400, 'Invalid content type');\n });\n }\n }\n })();\n } else {\n $asai.$log('API', req.method, req.url);\n }\n }\n\n return { apiWork };\n};","/**\r\n * Ws.ts — WebSocket 消息路由\r\n * 按 reqdata.ty 前缀匹配 hostserverwss 中的处理器;ping 快速回复 pong。\r\n */\r\nimport { ensureWsRouteIndex } from '../../infra/registry';\r\n\r\nexport default ($asai: any, opt: any = {}) => {\r\n opt?.fn?.($asai);\r\n\r\n /** WS 处理器实例缓存(插件注册后不变,避免每条消息重复 factory 调用) */\r\n const wsHandlerCache = new Map<string, any>();\r\n const routeIndex = ensureWsRouteIndex($asai);\r\n\r\n function getWsHandler(handlerKey: string) {\r\n if (!wsHandlerCache.has(handlerKey)) {\r\n wsHandlerCache.set(handlerKey, $asai.hostserverws[handlerKey]?.($asai));\r\n }\r\n return wsHandlerCache.get(handlerKey);\r\n }\r\n\r\n // 消息解析逻辑抽离为独立函数\r\n function parseMessage(msg: any) {\r\n if (Buffer.isBuffer(msg)) {\r\n msg = msg.toString();\r\n }\r\n if (msg === 'ping') {\r\n } else if (typeof msg === 'string') {\r\n try {\r\n msg = JSON.parse(msg);\r\n } catch (err) {}\r\n }\r\n return _getMessage(msg);\r\n }\r\n\r\n // WebSocket 消息处理器\r\n function wsWork(msg: any, ws: any, hostdir: string, req: any) {\r\n try {\r\n let reqdata = parseMessage(msg);\r\n // console.debug('[WS] Received message', req.Userinfo, reqdata);\r\n let handlerKey: string | undefined;\r\n if (reqdata === 'ping') {\r\n // ping 直接回复 pong,不经过 handlers 处理\r\n ws.send?.('pong');\r\n return;\r\n } else {\r\n const reqdataisobj: boolean = typeof reqdata === 'object' && reqdata !== null;\r\n handlerKey = reqdataisobj\r\n ? routeIndex.matchTy(reqdata?.ty)\r\n : routeIndex.matchString(reqdata);\r\n // 兼容:索引未命中时回退旧逻辑\r\n if (!handlerKey && $asai.hostserverwss?.length) {\r\n handlerKey = $asai.hostserverwss.find((elp: string) => {\r\n if (reqdataisobj) {\r\n return reqdata?.ty?.startsWith(elp);\r\n }\r\n return typeof reqdata === 'string' && reqdata.startsWith(elp);\r\n });\r\n }\r\n // mock数据处理逻辑\r\n if (!handlerKey) {\r\n $asai.asaimock?.wsWorkMock({\r\n msg,\r\n ws,\r\n hostdir,\r\n req,\r\n reqdataisobj,\r\n reqdata,\r\n });\r\n return;\r\n }\r\n }\r\n if (!handlerKey) return;\r\n getWsHandler(handlerKey)?.work?.(reqdata, ws, hostdir, req);\r\n } catch (err) {\r\n ($asai.$log || console.error)?.('WS', 'handler error', err instanceof Error ? err.message : err);\r\n }\r\n }\r\n function _getMessage(msg: any) {\r\n if (msg?.db?.aes && $asai.$lib?.aesfns?.reqAES) {\r\n msg.db = $asai.$lib.aesfns.reqAES({ data: msg.db });\r\n }\r\n return msg;\r\n }\r\n\r\n // command 方法 - 初始化通信命令配置\r\n function commandwork($asai: any) {\r\n // 初始化 command 配置\r\n if (!$asai.command) {\r\n $asai.command = {\r\n commandconfig: {\r\n clientws: {},\r\n },\r\n };\r\n }\r\n return {\r\n commandwork: () => {\r\n // 通信命令工作逻辑(占位)\r\n const log = $asai.$log || console.log;\r\n log('WS', 'Command work initialized');\r\n },\r\n };\r\n }\r\n\r\n return { wsWork, commandwork };\r\n};\r\n","/**\r\n * Sys.ts — /sys/* 系统路由分发\r\n */\r\nimport { validateHttpAuthAsync, sendAuthError } from '../../infra/access-control';\r\n\r\nexport default ($asai: any, opt: any = {}) => {\r\n opt?.fn?.($asai);\r\n\r\n let sysRouteCache: { key: string; route: string }[] | null = null;\r\n let sysRouteCacheLen = -1;\r\n\r\n function findSystemHandler(req: any): any {\r\n const routes = $asai.hostserversyss;\r\n if (!routes?.length) return undefined;\r\n if (!sysRouteCache || sysRouteCacheLen !== routes.length) {\r\n sysRouteCache = routes.map((elp: string) => ({ key: elp, route: `/${elp}` }));\r\n sysRouteCacheLen = routes.length;\r\n }\r\n if (!sysRouteCache) return undefined;\r\n const url = req.url || '';\r\n for (let i = 0; i < sysRouteCache.length; i++) {\r\n const item = sysRouteCache[i];\r\n if (url.startsWith(item.route) && $asai.hostserversys[item.key]) {\r\n return item.key;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n // 统一错误响应\r\n const sendError = (res: any, code: number, message: string) => {\r\n res.writeHead(code, {\r\n 'Content-Type': 'application/json; charset=utf-8',\r\n });\r\n res.end(JSON.stringify({ error: message }));\r\n };\r\n function sysWork(req: any, res: any, hostdir: string) {\r\n // 查找匹配的路由\r\n const handlerKey = findSystemHandler(req);\r\n\r\n if (!handlerKey) {\r\n return sendError(res, 404, 'Not Found');\r\n }\r\n\r\n const urlPath = (req.url || '').split('?')[0];\r\n void (async () => {\r\n const authResult = await validateHttpAuthAsync(req, $asai, urlPath);\r\n if (!authResult.ok) {\r\n return sendAuthError(res, authResult);\r\n }\r\n\r\n // 初始化处理器\r\n const handler = $asai.hostserversys[handlerKey]?.($asai);\r\n if (!handler) {\r\n return sendError(res, 500, 'Handler Initialization Failed');\r\n }\r\n\r\n if (handler?.show && typeof handler?.show === 'function') {\r\n handler.show(req, res, hostdir);\r\n } else {\r\n res.end('postdata');\r\n }\r\n if (!handler) {\r\n res.writeHead(404, {\r\n 'Content-Type': 'application/json; charset=utf-8',\r\n });\r\n res.end(req.url);\r\n } else {\r\n // sysFn = null;// 异步不适用!!\r\n }\r\n })();\r\n }\r\n\r\n return { sysWork };\r\n};","export default ($asai: any, wsname: string) => {\r\n if (!$asai?.clientws) {\r\n $asai.clientws = {};\r\n }\r\n if (!$asai.clientws[wsname]) {\r\n $asai.clientws[wsname] = { tasks: new Map() };\r\n }\r\n function getKeyByData(msgdata: any): string {\r\n return msgdata?.id || msgdata?.ty;\r\n }\r\n function clientwsInit() {\r\n return new Promise((resolve: any, reject: any) => {\r\n $asai.clientws[wsname].socket = new $asai.asaiWs(\r\n $asai.command.commandconfig.clientws[wsname]\r\n );\r\n\r\n $asai.clientws[wsname].socket.onmessage = (event: any) => {\r\n clientwsOnmessage(event.data);\r\n };\r\n\r\n $asai.clientws[wsname].socket.on('error', (err: any) => {\r\n $asai.clientws[wsname].open = 0;\r\n $asai.hostconfig.logger?.lv?.view &&\r\n console.error(\r\n 666.2203,\r\n `${wsname}=${$asai.command.commandconfig.clientws[wsname]} is error.`,\r\n err\r\n );\r\n reject();\r\n });\r\n\r\n $asai.clientws[wsname].socket.on('close', () => {\r\n $asai.clientws[wsname].open = 0;\r\n $asai.hostconfig.logger?.lv?.view &&\r\n console.error(\r\n 666.2205,\r\n `${wsname}=${$asai.command.commandconfig.clientws[wsname]} is close.`\r\n );\r\n reject();\r\n });\r\n\r\n $asai.clientws[wsname].socket.onopen = () => {\r\n $asai.hostconfig.logger?.lv?.view &&\r\n console.log(\r\n 666.2201,\r\n `${wsname}=${$asai.command.commandconfig.clientws[wsname]} is open.`\r\n );\r\n $asai.clientws[wsname].open = 1;\r\n resolve();\r\n };\r\n });\r\n }\r\n\r\n function clientwsSend(message: string) {\r\n if ($asai.clientws[wsname].open) {\r\n $asai.clientws[wsname].socket.send(message);\r\n }\r\n }\r\n function clientwsOnmessage(message: string) {\r\n if ($asai.clientws[wsname].open) {\r\n try {\r\n const messageData: any = JSON.parse(message);\r\n const key: string = getKeyByData(messageData);\r\n const task = $asai.clientws[wsname].tasks.get(key);\r\n if (task) {\r\n task?.callback(messageData);\r\n if (messageData.ty && !messageData.id) {\r\n // watch\r\n } else {\r\n $asai.clientws[wsname].tasks.delete(key);\r\n }\r\n }\r\n } catch (e) {}\r\n }\r\n }\r\n function clientwsApi(messageData: any) {\r\n return new Promise((resolve, reject) => {\r\n if ($asai.clientws[wsname].open) {\r\n try {\r\n const taskOpt: any = {};\r\n taskOpt.timestamp = Date.now();\r\n if (!messageData.id) {\r\n messageData.id = $asai.$lib.As.Uuid('nd');\r\n }\r\n $asai.clientws[wsname].tasks.set(\r\n getKeyByData(messageData),\r\n {\r\n callback: (res: any) => {\r\n resolve(res);\r\n },\r\n ...messageData,\r\n ...taskOpt,\r\n }\r\n );\r\n clientwsSend(JSON.stringify(messageData));\r\n } catch (err) {\r\n reject(err);\r\n }\r\n }\r\n });\r\n }\r\n function clientwsWatch(messageData: any, cb: any) {\r\n if ($asai.clientws[wsname].open) {\r\n try {\r\n $asai.clientws[wsname].tasks.set(getKeyByData(messageData), {\r\n callback: (res: any) => {\r\n cb(res);\r\n },\r\n ...messageData,\r\n });\r\n clientwsSend(JSON.stringify(messageData));\r\n } catch (err) {}\r\n }\r\n }\r\n function clientwsWatchOff(messageData: any) {\r\n if (messageData?.ty === 'clear') {\r\n $asai.clientws[wsname].tasks = new Map();\r\n // $asai.clientws[wsname].tasks.clear();\r\n } else {\r\n const key: string = getKeyByData(messageData);\r\n const task = $asai.clientws[wsname].tasks.get(key);\r\n if (task) {\r\n $asai.clientws[wsname].tasks.delete(key);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n clientwsInit,\r\n clientwsSend,\r\n clientwsApi,\r\n clientwsWatch,\r\n clientwsWatchOff,\r\n };\r\n};","import ServerApi from './server/Api';\r\nimport ServerWs from './server/Ws';\r\nimport ServerSys from './server/Sys';\r\nimport WsClient from './server/WsClient';\r\n\r\nexport default {\r\n ServerApi,\r\n ServerWs,\r\n ServerSys,\r\n WsClient,\r\n};\r\n","export default ($asai: any) => {\r\n function work(msgdata: any, ws: any, hostdir: string, req: any) {\r\n $asai.serversws[hostdir].sendws('pong', 0, ws);\r\n }\r\n return { work };\r\n};\r\n","export default ($asai: any) => {\r\n // 消息广播模式\r\n function chatBoard(msgdata: any, ws: any, hostdir: string, req: any) {\r\n let room: string;\r\n if (msgdata.db?.room && typeof msgdata.db.room === 'string') {\r\n room = msgdata.db.room;\r\n delete msgdata.db.room;\r\n } else {\r\n room = 'asai';\r\n }\r\n if (!$asai.$ws.chat.rooms[room]) {\r\n $asai.$ws.chat.rooms[room] = JSON.parse($asai.$ws.chat.temp);\r\n }\r\n $asai.$ws.chat.rooms[room].db.push(msgdata.db);\r\n $asai.$lib.As.throttle(() => {\r\n msgdata.ty = msgdata.ty.slice(0, -4) + 'broadcast';\r\n msgdata.db = $asai.$ws.chat.rooms[room].db;\r\n delete msgdata.id;\r\n $asai.$log(666.702, 'broadcast', msgdata);\r\n $asai.serversws[hostdir].sendws(msgdata, 2, ws);\r\n $asai.$ws.chat.rooms[room].db = [];\r\n }, $asai.$ws.chat.rooms[room].tm);\r\n }\r\n function work(msgdata: any, ws: any, hostdir: string, req: any) {\r\n if (msgdata.ty.endsWith('send')) {\r\n // 进入消息广播模式\r\n chatBoard(msgdata, ws, hostdir, req);\r\n // 告诉发送者,消息已收到\r\n $asai.serversws[hostdir].sendws(\r\n { id: msgdata.id, db: 1 },\r\n 0,\r\n ws\r\n );\r\n }\r\n $asai.$log('CHAT', 'get send', msgdata);\r\n }\r\n return { work };\r\n};\r\n","import ping from \"./common/ping\";\r\nimport chatWeb from \"./chat/web\";\r\n\r\nexport default {\r\n ping,\r\n \"chat/web\": chatWeb,\r\n};\r\n","import fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { attachServerUserLevel, getRequestUserLevel } from \"../../../infra/user-auth\";\r\nimport { getPermissionThreshold } from \"../login/service/user-level-config\";\r\nimport { isLogStoreEnabled, prefersDiskLogAccess } from \"../../lib/common/log-db\";\r\nimport {\r\n groupsToManageChildren,\r\n listUnifiedGroups,\r\n purgeStoreEntriesForFile,\r\n readWebLogFromStore,\r\n} from \"../../lib/common/LogStore\";\r\n\r\nasync function ensureLv(req: any, $asai: any, min: number): Promise<boolean> {\r\n await attachServerUserLevel(req, $asai);\r\n return getRequestUserLevel(req) >= min;\r\n}\r\n\r\nexport default ($asai: any) => {\r\n const {\r\n ensureFile,\r\n pathExists,\r\n readLogDir,\r\n removeFile,\r\n resolvePathUnderBase,\r\n } = $asai.$lib.AsFs;\r\n const { sendSuccess, sendFail, mnLog } = $asai.$lib?.reqWork?.($asai);\r\n\r\n function mgLog(...arg: any) {\r\n mnLog(\"LOG\", ...arg);\r\n }\r\n\r\n /**\r\n * 获取日志目录路径\r\n */\r\n function getDir(opt: any): string {\r\n let tmpDir: string = opt.qrdata?.dir || opt.data?.dir;\r\n if (tmpDir) {\r\n tmpDir = decodeURIComponent(tmpDir);\r\n } else {\r\n tmpDir = opt.qrdata?.ty || opt.data?.ty;\r\n if (tmpDir) {\r\n tmpDir = decodeURIComponent(tmpDir);\r\n if (tmpDir === \"access-clf\" || tmpDir === \"access-w3c\") {\r\n tmpDir = $asai.hostconfig.logger?.path?.access || \"\";\r\n } else {\r\n tmpDir = $asai.hostconfig.logger?.path?.[tmpDir] || \"\";\r\n }\r\n } else {\r\n tmpDir = $asai.hostconfig.logger?.path?.client || \"\";\r\n }\r\n }\r\n return tmpDir;\r\n }\r\n\r\n /**\r\n * 处理 POST 请求\r\n */\r\n async function post(req: any, res: any, hostdir: string, opt: any) {\r\n const url = req.url;\r\n // ---------- 添加客户端日志 /api/asailog/manage/addclient/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/addclient/\")) {\r\n try {\r\n await $asai.$log(1, opt.data);\r\n sendSuccess(res, \"ok\", opt);\r\n } catch (err) {\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n\r\n // ---------- 添加服务器日志 /api/asailog/manage/add/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/add/\")) {\r\n if (!(await ensureLv(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n mgLog(\"add\", \"server:\", opt.data);\r\n await $asai.$log(\"LOG\", \"ADD\", opt.data);\r\n sendSuccess(res, \"ok\", opt);\r\n } catch (err) {\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n\r\n // ---------- 更新日志文件 /api/asailog/manage/update/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/update/\")) {\r\n if (!(await ensureLv(req, $asai, 3))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const baseDir = getDir(opt);\r\n const relPath = decodeURIComponent(opt.qrdata?.path || opt.data?.path);\r\n const jsonpath = resolvePathUnderBase(baseDir, relPath);\r\n await ensureFile(jsonpath);\r\n mgLog(\"ENSURE\", jsonpath);\r\n const content =\r\n typeof opt.data === \"string\" ? opt.data : String(opt.data ?? \"\");\r\n await fs.writeFile(jsonpath, content, \"utf8\");\r\n mgLog(\"UPDATE\", jsonpath);\r\n sendSuccess(res, jsonpath, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"update\", err);\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n }\r\n\r\n /**\r\n * 处理 GET 请求\r\n */\r\n async function get(req: any, res: any, hostdir: string, opt: any) {\r\n const url = req.url;\r\n\r\n // ---------- 列出日志目录 /api/asailog/manage/selectlist/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/selectlist/\")) {\r\n if (!(await ensureLv(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const ty = decodeURIComponent(opt.qrdata?.ty || opt.data?.ty || \"client\");\r\n if (!prefersDiskLogAccess($asai) && isLogStoreEnabled($asai) && (ty === \"client\" || ty === \"server\" || ty === \"sec\")) {\r\n const kind = ty === \"sec\" ? \"sec\" : \"web\";\r\n const groups = await listUnifiedGroups($asai, { kind: kind as any, source: ty === \"sec\" ? \"sec\" : ty });\r\n const children = groupsToManageChildren(groups);\r\n if (children.length) {\r\n mgLog(\"LIST\", `store:${ty}`, children.length);\r\n return sendSuccess(res, { children, fromStore: true }, opt);\r\n }\r\n }\r\n const dir = path.resolve(getDir(opt));\r\n if (!dir) {\r\n mgLog(\"MISS\", \"dir not configured\");\r\n return sendFail(res, \"no exist!\", opt);\r\n }\r\n mgLog(\"LIST\", dir);\r\n const files = await readLogDir(dir);\r\n mgLog(\"READ\", `${files.children.length} items`);\r\n sendSuccess(res, files, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"selectlist\", err);\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n\r\n // ---------- 读取日志文件 /api/asailog/manage/select/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/select/\")) {\r\n if (!(await ensureLv(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const ty = decodeURIComponent(opt.qrdata?.ty || opt.data?.ty || \"client\");\r\n const relPath = decodeURIComponent(opt.qrdata?.path || opt.data?.path);\r\n if (!prefersDiskLogAccess($asai) && isLogStoreEnabled($asai) && (ty === \"client\" || ty === \"server\" || ty === \"sec\")) {\r\n const data = await readWebLogFromStore($asai, ty, relPath);\r\n if (data) {\r\n mgLog(\"READ\", `store:${ty}/${relPath}`);\r\n return sendSuccess(res, data, opt);\r\n }\r\n }\r\n const baseDir = getDir(opt);\r\n const filepath = resolvePathUnderBase(baseDir, relPath);\r\n const exists = await pathExists(filepath);\r\n if (!exists) {\r\n mgLog(\"MISS\", filepath);\r\n return sendFail(res, \"no exist!\", opt);\r\n }\r\n mgLog(\"READ\", filepath);\r\n const data = await fs.readFile(filepath, \"utf8\");\r\n sendSuccess(res, data, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"select\", err);\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n\r\n // ---------- 删除日志文件 /api/asailog/manage/delete/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/delete/\")) {\r\n if (!(await ensureLv(req, $asai, 3))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const baseDir = getDir(opt);\r\n const relPath = decodeURIComponent(opt.qrdata?.path || opt.data?.path);\r\n const fileName = relPath.split(/[/\\\\]/).pop() || relPath;\r\n if (isLogStoreEnabled($asai)) {\r\n await purgeStoreEntriesForFile($asai, fileName).catch(() => undefined);\r\n }\r\n const filepath = resolvePathUnderBase(baseDir, relPath);\r\n mgLog(\"DELETE\", filepath);\r\n await removeFile(filepath);\r\n mgLog(\"DELETE\", \" completed\");\r\n sendSuccess(res, filepath, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"delete\", err);\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n }\r\n\r\n return { post, get };\r\n};\r\n","/**\r\n * SIEM 只读 Token — 外部 SOC 拉取日志(search/export/compliance),不可删除/归档\r\n */\r\nimport { attachServerUserLevel, getRequestUserLevel } from './user-auth';\r\n\r\nexport function isSiemEnabled($asai: any): boolean {\r\n\tconst cfg = $asai?.hostconfig?.logger?.siem;\r\n\treturn !!(cfg?.enabled && getSiemToken($asai));\r\n}\r\n\r\nexport function getSiemToken($asai: any): string {\r\n\tconst fromEnv = process.env.ASAI_SIEM_TOKEN;\r\n\tif (typeof fromEnv === 'string' && fromEnv.trim()) return fromEnv.trim();\r\n\tconst fromCfg = $asai?.hostconfig?.logger?.siem?.token;\r\n\treturn typeof fromCfg === 'string' ? fromCfg.trim() : '';\r\n}\r\n\r\nexport function isSiemTokenValid($asai: any, req: any): boolean {\r\n\tif (!isSiemEnabled($asai)) return false;\r\n\tconst expected = getSiemToken($asai);\r\n\tif (!expected) return false;\r\n\tconst header = req?.headers?.['x-siem-token'] || req?.headers?.['x-api-key'];\r\n\tif (typeof header === 'string' && header === expected) return true;\r\n\tconst q = req?.query || {};\r\n\tconst qToken = q.siem_token || q.token;\r\n\treturn typeof qToken === 'string' && qToken === expected;\r\n}\r\n\r\nexport type LogAccessMode = 'siem' | 'user' | false;\r\n\r\n/** 读操作:SIEM Token 等效 lv≥2;写/删操作禁止 SIEM */\r\nexport async function ensureLogReadAccess(req: any, $asai: any, minLv = 2): Promise<LogAccessMode> {\r\n\tif (isSiemTokenValid($asai, req)) return 'siem';\r\n\tawait attachServerUserLevel(req, $asai);\r\n\treturn getRequestUserLevel(req) >= minLv ? 'user' : false;\r\n}\r\n\r\nexport async function ensureLogWriteAccess(req: any, $asai: any, minLv: number): Promise<boolean> {\r\n\tif (isSiemTokenValid($asai, req)) return false;\r\n\tawait attachServerUserLevel(req, $asai);\r\n\treturn getRequestUserLevel(req) >= minLv;\r\n}\r\n","/**\r\n * IEC 62443-4-2 干预日志管理 API — asailog/intervention\r\n * 只读查询对 lv>=2 开放,删除操作对 lv>=3 开放并强制留存期校验(见 InterventionLog.deleteInterventionFile)。\r\n * 不提供\"任意写入\"接口:日志只能由业务代码在真实干预发生时通过 $asai.$lib.InterventionLog.logIntervention 自动写入。\r\n *\r\n * ns 参数(可选,默认 'prod'):切换查看命名空间。'prod' 为受5年留存保护的生产日志(默认,\r\n * 保持既有行为不变);'test' 为 testkdd/testlog 等演示/自动化测试触发动作的隔离存储,\r\n * 用于在不触碰生产留存证据的前提下验证日志引擎全部功能(列表/查看/链校验/删除留存策略)。\r\n */\r\nimport { attachServerUserLevel, getRequestUserLevel, getRequestUsername } from '../../../infra/user-auth';\r\nimport { ensureLogReadAccess, ensureLogWriteAccess } from '../../../infra/siem-auth';\r\nimport { getPermissionThreshold } from '../login/service/user-level-config';\r\nimport { isLogStoreEnabled, prefersDiskLogAccess } from '../../lib/common/log-db';\r\nimport { groupsToInterventionFiles, listUnifiedGroups } from '../../lib/common/LogStore';\r\n\r\nfunction getNs(raw: any): \"prod\" | \"test\" {\r\n return raw === \"test\" ? \"test\" : \"prod\";\r\n}\r\n\r\nasync function ensureServerUser(req: any, $asai: any): Promise<void> {\r\n if (Array.isArray(req?.Userinfo) && req.Userinfo[0]) {\r\n await attachServerUserLevel(req, $asai);\r\n }\r\n}\r\n\r\nexport default ($asai: any) => {\r\n const { sendSuccess, sendFail } = $asai.$lib?.reqWork?.($asai) || {};\r\n const IL = $asai.$lib.InterventionLog;\r\n\r\n async function get(req: any, res: any, hostdir: string, opt: any) {\r\n const url = req.url || \"\";\r\n\r\n if (url.startsWith(\"/api/asailog/intervention/selectlist/\")) {\r\n if (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const ns = getNs(opt.qrdata?.ns || opt.data?.ns);\r\n let list = await IL.listInterventionFiles($asai, ns);\r\n if (isLogStoreEnabled($asai) && !prefersDiskLogAccess($asai)) {\r\n const groups = await listUnifiedGroups($asai, { kind: 'intervention', ns });\r\n const fromStore = groupsToInterventionFiles(groups, ns);\r\n const names = new Set(list.map((f: any) => f.name));\r\n for (const f of fromStore) {\r\n if (!names.has(f.name)) list.push(f);\r\n }\r\n }\r\n return sendSuccess(res, { ns, files: list }, opt);\r\n } catch (err: any) {\r\n return sendFail(res, err?.message || err, opt);\r\n }\r\n }\r\n\r\n if (url.startsWith(\"/api/asailog/intervention/select/\")) {\r\n if (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const name = decodeURIComponent(opt.qrdata?.name || opt.data?.name || \"\");\r\n const ns = getNs(opt.qrdata?.ns || opt.data?.ns);\r\n if (!name) return sendFail(res, \"name required\", opt);\r\n const content = await IL.readInterventionFile($asai, name, ns);\r\n return sendSuccess(res, { ns, ...content }, opt);\r\n } catch (err: any) {\r\n return sendFail(res, err?.message || err, opt);\r\n }\r\n }\r\n\r\n if (url.startsWith(\"/api/asailog/intervention/types/\")) {\r\n if (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n return sendSuccess(res, IL.getInterventionTaxonomy($asai), opt);\r\n } catch (err: any) {\r\n return sendFail(res, err?.message || err, opt);\r\n }\r\n }\r\n }\r\n\r\n async function post(req: any, res: any, hostdir: string, opt: any) {\r\n const url = req.url || \"\";\r\n\r\n if (url.startsWith(\"/api/asailog/intervention/delete/\")) {\r\n if (!(await ensureLogWriteAccess(req, $asai, getPermissionThreshold($asai, 'adminWrite')))) return sendFail(res, \"Forbidden\", opt);\r\n await ensureServerUser(req, $asai);\r\n const lv = getRequestUserLevel(req);\r\n const us = getRequestUsername(req);\r\n try {\r\n const body = typeof opt.data === \"string\" ? JSON.parse(opt.data || \"{}\") : opt.data || {};\r\n const name = String(body.name || \"\");\r\n const ns = getNs(body.ns);\r\n if (!name) return sendFail(res, \"name required\", opt);\r\n const result = await IL.deleteInterventionFile(\r\n $asai,\r\n name,\r\n {\r\n us: us ? String(us) : undefined,\r\n lv,\r\n reason: body.reason ? String(body.reason).slice(0, 256) : undefined,\r\n force: !!body.force,\r\n },\r\n ns,\r\n );\r\n return sendSuccess(res, { ns, ...result }, opt);\r\n } catch (err: any) {\r\n return sendFail(res, err?.message || err, opt);\r\n }\r\n }\r\n }\r\n\r\n return { get, post };\r\n};\r\n","/**\r\n * IEC 62443-4-2 统一日志 API — /api/asailog/store/*\r\n */\r\nimport { ensureLogReadAccess, ensureLogWriteAccess } from '../../../infra/siem-auth';\r\nimport { getPermissionThreshold } from '../login/service/user-level-config';\r\nimport { getRequestUsername } from '../../../infra/user-auth';\r\nimport {\r\n\tgetUnifiedEntry,\r\n\tgetUnifiedStats,\r\n\tlistUnifiedGroups,\r\n\tqueryUnifiedLogs,\r\n\treadWebLogFromStore,\r\n\tgroupsToInterventionFiles,\r\n\tgroupsToManageChildren,\r\n\tsearchUnifiedLogs,\r\n\texportLogContent,\r\n\tgetComplianceReport,\r\n\tarchiveInterventionYear,\r\n} from '../../lib/common/LogStore';\r\nimport { getLogStoreConfig, getLogStoreMeta, getEffectiveStoreType, isLogStoreEnabled } from '../../lib/common/log-db';\r\nimport type { LogKind } from '../../lib/common/log-db';\r\n\r\nfunction parseQuery(opt: any): Record<string, string> {\r\n\tconst q = opt.qrdata || opt.data || {};\r\n\tconst out: Record<string, string> = {};\r\n\tfor (const [k, v] of Object.entries(q)) {\r\n\t\tif (v != null && v !== '') out[k] = String(v);\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nfunction parseBody(opt: any): Record<string, unknown> {\r\n\tif (!opt?.data) return {};\r\n\tif (typeof opt.data === 'string') {\r\n\t\ttry { return JSON.parse(opt.data); } catch { return {}; }\r\n\t}\r\n\treturn typeof opt.data === 'object' ? opt.data : {};\r\n}\r\n\r\nexport default ($asai: any) => {\r\n\tconst { sendSuccess, sendFail } = $asai.$lib?.reqWork?.($asai) || {};\r\n\tconst IL = $asai.$lib.InterventionLog;\r\n\r\n\tasync function get(req: any, res: any, hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tconst q = parseQuery(opt);\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/config/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\treturn sendSuccess(res, getLogStoreMeta($asai), opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/stats/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\tif (!isLogStoreEnabled($asai)) {\r\n\t\t\t\treturn sendSuccess(res, { store: 'disabled', message: 'logger.store not configured', config: getLogStoreMeta($asai) }, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst storeType = getEffectiveStoreType($asai);\r\n\t\t\t\tconst stats = await getUnifiedStats($asai);\r\n\t\t\t\treturn sendSuccess(res, { store: storeType, stats, config: getLogStoreMeta($asai) }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/compliance/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst ns = q.ns === 'test' ? 'test' : 'prod';\r\n\t\t\t\tconst report = await getComplianceReport($asai, ns);\r\n\t\t\t\treturn sendSuccess(res, report, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/search/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\tif (!isLogStoreEnabled($asai)) return sendFail(res, 'Log store not enabled', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst result = await searchUnifiedLogs($asai, {\r\n\t\t\t\t\tkind: q.kind ? (q.kind as LogKind) : undefined,\r\n\t\t\t\t\tns: q.ns ? (q.ns as 'prod' | 'test' | '') : undefined,\r\n\t\t\t\t\tsource: q.source || q.ty || undefined,\r\n\t\t\t\t\tkeyword: q.keyword || q.q || undefined,\r\n\t\t\t\t\tevent_type: q.event_type || undefined,\r\n\t\t\t\t\tseverity_min: q.severity_min != null ? Number(q.severity_min) : undefined,\r\n\t\t\t\t\tdate_from: q.date_from || undefined,\r\n\t\t\t\t\tdate_to: q.date_to || undefined,\r\n\t\t\t\t\toutcome: q.outcome || undefined,\r\n\t\t\t\t\tlimit: q.limit != null ? Number(q.limit) : 200,\r\n\t\t\t\t\toffset: q.offset != null ? Number(q.offset) : 0,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, result, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/export/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst kind = (q.kind || 'intervention') as LogKind | 'intervention';\r\n\t\t\t\tconst format = (q.format || 'raw') as 'cef' | 'raw' | 'json';\r\n\t\t\t\tconst fileName = decodeURIComponent(q.name || q.path || '');\r\n\t\t\t\tconst ns = q.ns === 'test' ? 'test' : 'prod';\r\n\t\t\t\tconst source = q.source || q.ty || 'server';\r\n\t\t\t\tif (!fileName && kind === 'intervention') return sendFail(res, 'name required', opt);\r\n\t\t\t\tconst payload = await exportLogContent($asai, {\r\n\t\t\t\t\tkind,\r\n\t\t\t\t\tns: kind === 'intervention' ? ns : undefined,\r\n\t\t\t\t\tfileName: fileName || undefined,\r\n\t\t\t\t\tsource,\r\n\t\t\t\t\tformat,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, payload, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/taxonomy/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\treturn sendSuccess(res, IL.getInterventionTaxonomy($asai), opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/formats/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst { getLogFormatTaxonomy } = await import('../../lib/common/log-formats');\r\n\t\t\t\treturn sendSuccess(res, getLogFormatTaxonomy($asai), opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/selectlist/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\tif (!isLogStoreEnabled($asai)) return sendFail(res, 'Log store not enabled', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst kind = q.kind ? String(q.kind) : undefined;\r\n\t\t\t\tconst ns = q.ns ? String(q.ns) : undefined;\r\n\t\t\t\tconst source = q.source || q.ty ? String(q.source || q.ty) : undefined;\r\n\t\t\t\tconst groups = await listUnifiedGroups($asai, { kind: kind as any, ns, source });\r\n\t\t\t\tif (kind === 'intervention' || ns) {\r\n\t\t\t\t\treturn sendSuccess(res, { files: groupsToInterventionFiles(groups, ns || 'prod'), ns: ns || 'prod' }, opt);\r\n\t\t\t\t}\r\n\t\t\t\tif (kind === 'web' || kind === 'sec' || kind === 'access' || source) {\r\n\t\t\t\t\tconst children = kind === 'access'\r\n\t\t\t\t\t\t? groups.filter((g) => g.kind === 'access').map((g) => ({\r\n\t\t\t\t\t\t\tname: g.file_name,\r\n\t\t\t\t\t\t\tpath: g.file_name,\r\n\t\t\t\t\t\t\tsize: g.entryCount,\r\n\t\t\t\t\t\t\tentryCount: g.entryCount,\r\n\t\t\t\t\t\t\tsource: g.source,\r\n\t\t\t\t\t\t\tfromStore: true,\r\n\t\t\t\t\t\t}))\r\n\t\t\t\t\t\t: groupsToManageChildren(groups);\r\n\t\t\t\t\treturn sendSuccess(res, { children, source }, opt);\r\n\t\t\t\t}\r\n\t\t\t\treturn sendSuccess(res, { groups }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/select/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\tif (!isLogStoreEnabled($asai)) return sendFail(res, 'Log store not enabled', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst id = q.id;\r\n\t\t\t\tif (id != null) {\r\n\t\t\t\t\tconst row = await getUnifiedEntry($asai, id);\r\n\t\t\t\t\tif (!row) return sendFail(res, 'not found', opt);\r\n\t\t\t\t\treturn sendSuccess(res, { entry: row }, opt);\r\n\t\t\t\t}\r\n\t\t\t\tconst kind = String(q.kind || '');\r\n\t\t\t\tconst fileName = decodeURIComponent(q.name || q.path || '');\r\n\t\t\t\tconst ns = q.ns ? String(q.ns) : '';\r\n\t\t\t\tconst source = q.source || q.ty ? String(q.source || q.ty) : 'server';\r\n\r\n\t\t\t\tif (kind === 'web' || kind === 'sec' || (!kind && fileName.startsWith('log-'))) {\r\n\t\t\t\t\tconst content = await readWebLogFromStore($asai, source, fileName);\r\n\t\t\t\t\treturn sendSuccess(res, content, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (kind === 'intervention' || fileName.includes('.cef.log')) {\r\n\t\t\t\t\tconst content = await IL.readInterventionFile($asai, fileName, ns === 'test' ? 'test' : 'prod');\r\n\t\t\t\t\treturn sendSuccess(res, { ns: ns || 'prod', ...content, fromStore: true }, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst rows = await queryUnifiedLogs($asai, {\r\n\t\t\t\t\tkind: kind as any,\r\n\t\t\t\t\tns: ns as any,\r\n\t\t\t\t\tsource,\r\n\t\t\t\t\tfile_name: fileName,\r\n\t\t\t\t\tlimit: Number(q.limit) || 200,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, { entries: rows }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tasync function post(req: any, res: any, hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tif (!url.startsWith('/api/asailog/store/archive/')) return;\r\n\t\tif (!(await ensureLogWriteAccess(req, $asai, getPermissionThreshold($asai, 'adminWrite')))) return sendFail(res, 'Forbidden', opt);\r\n\t\ttry {\r\n\t\t\tconst body = parseBody(opt);\r\n\t\t\tconst year = Number(body.year);\r\n\t\t\tif (!year || year < 2000 || year > 2100) return sendFail(res, 'invalid year', opt);\r\n\t\t\tconst ns = body.ns === 'test' ? 'test' : 'prod';\r\n\t\t\tconst result = await archiveInterventionYear($asai, {\r\n\t\t\t\tyear,\r\n\t\t\t\tns,\r\n\t\t\t\tdryRun: !!body.dryRun,\r\n\t\t\t\toperator: getRequestUsername(req),\r\n\t\t\t});\r\n\t\t\treturn sendSuccess(res, result, opt);\r\n\t\t} catch (err: any) {\r\n\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { get, post };\r\n};\r\n","import * as fs from 'node:fs';\r\nimport * as nodePath from 'node:path';\r\n\r\nexport type ErrorCodeEntry = {\r\n id?: string;\r\n lg?: string;\r\n detail?: string;\r\n category?: string;\r\n level?: string;\r\n wsLang?: string;\r\n};\r\n\r\nexport type ErrorCodesFile = {\r\n version?: string;\r\n description?: string;\r\n errors?: Record<string, ErrorCodeEntry>;\r\n};\r\n\r\nlet registry: ErrorCodesFile | null = null;\r\n\r\nfunction resolveFilePath($asai: any): string {\r\n const root = $asai?.serverRoot || process.cwd();\r\n return nodePath.join(root, 'websys/sys/errorcodes.json');\r\n}\r\n\r\nexport function loadErrorCodes($asai: any): ErrorCodesFile {\r\n if (registry) return registry;\r\n const filePath = resolveFilePath($asai);\r\n try {\r\n const raw = fs.readFileSync(filePath, 'utf8');\r\n registry = JSON.parse(raw) as ErrorCodesFile;\r\n } catch {\r\n registry = { version: '0', errors: {} };\r\n }\r\n if ($asai) $asai.errorcodes = registry;\r\n return registry;\r\n}\r\n\r\nexport function getError(ec: string): ErrorCodeEntry | null {\r\n return registry?.errors?.[ec] || null;\r\n}\r\n\r\nexport function hasError(ec: string): boolean {\r\n return !!getError(ec);\r\n}\r\n\r\nexport function logError($asai: any, ec: string, params?: string[]): void {\r\n const entry = getError(ec);\r\n const logFn = $asai?.$log || console.warn;\r\n if (entry) {\r\n logFn(`[EC:${ec}]`, entry.id || '', entry.detail || '', params?.length ? params : '');\r\n } else {\r\n logFn(`[EC:${ec}]`, '(unregistered)', params?.length ? params : '');\r\n }\r\n}\r\n\r\nexport function normalizeErrPayload(err: unknown): { ec?: string; pm?: string[]; raw?: unknown } {\r\n if (err && typeof err === 'object') {\r\n const o = err as Record<string, unknown>;\r\n if (typeof o.ec === 'string') {\r\n const pm = Array.isArray(o.pm)\r\n ? o.pm.map(String)\r\n : o.pm != null\r\n ? [String(o.pm)]\r\n : undefined;\r\n return { ec: o.ec, pm };\r\n }\r\n }\r\n if (typeof err === 'string' && hasError(err)) {\r\n return { ec: err };\r\n }\r\n return { raw: err };\r\n}\r\n\r\nexport default {\r\n loadErrorCodes,\r\n getError,\r\n hasError,\r\n logError,\r\n normalizeErrPayload,\r\n};\r\n","import { loadErrorCodes } from '../../lib/common/ErrorCode';\r\n\r\n/** 公开 GET — 供前端 initerrcodes 拉取 websys/sys/errorcodes.json(开发环境跨域走 API CORS) */\r\nexport default ($asai: any) => {\r\n\tconst { sendSuccess, sendFail } = $asai.$lib?.reqWork?.($asai) || {};\r\n\r\n\tfunction get(req: any, res: any, _hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tif (url.startsWith('/api/sys/errorcodes/')) {\r\n\t\t\ttry {\r\n\t\t\t\treturn sendSuccess(res, loadErrorCodes($asai), opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn { get };\r\n};\r\n","export default ($asai: any) => {\r\n const { sendSuccess, sendFail, mnLog } = $asai?.$lib?.reqWork?.($asai) || {};\r\n function mgLog(...arg: any[]) {\r\n mnLog?.(\"SQLite\", ...arg);\r\n }\r\n\r\n return $asai.$lib.AsDb($asai, {\r\n type: \"sqlite\",\r\n opt: {\r\n database: \"./webdata/webdb/testkdd/sqlite/asaisqlitetest.db\",\r\n create: 1,\r\n },\r\n field: {\r\n key: \"ai_sn\",\r\n class: \"ai_fl\",\r\n data: [\"ai_sn\", \"ai_fl\", \"ai_bt\", \"ai_nr\", \"ai_tm\", \"ai_t1\", \"ai_dj\", \"ai_xy\", \"ai_hi\", \"ai_xi\", \"ai_xo\"],\r\n },\r\n post: async (req: any, res: any, hostdir: string, opt: any, _DataServer: any) => {\r\n if (req.url.startsWith(\"/api/asaisqlite/manage/post\")) {\r\n try {\r\n mgLog(\"POST\", \"custom handler triggered\");\r\n sendSuccess?.(res, { data: \"post\" }, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"post handler\", err);\r\n }\r\n return \"ok\";\r\n }\r\n },\r\n get: async (req: any, res: any, hostdir: string, opt: any, DataServer: any) => {\r\n if (req.url.startsWith(\"/api/asaisqlite/manage/get\")) {\r\n try {\r\n const dataObj: any = opt.data;\r\n mgLog(\"SELECT\", dataObj.table);\r\n const resdb = await DataServer.sqlDb({\r\n type: \"select\",\r\n table: dataObj.table,\r\n });\r\n mgLog(\"SELECT\", \"completed\");\r\n sendSuccess?.(res, resdb, opt);\r\n } catch (errdb) {\r\n mgLog(\"ERROR\", \"select\", errdb);\r\n sendFail?.(res, errdb, opt);\r\n }\r\n return \"ok\";\r\n }\r\n },\r\n });\r\n};\r\n","/**\r\n * IEC 62443-4-2 CR 6.2 — 健康与连续监控指标(Prometheus 文本格式)\r\n */\r\nimport os from 'node:os';\r\n\r\nfunction promLine(name: string, value: number | string, labels?: Record<string, string>): string {\r\n\tconst lbl = labels\r\n\t\t? `{${Object.entries(labels)\r\n\t\t\t\t.map(([k, v]) => `${k}=\"${String(v).replace(/\"/g, '\\\\\"')}\"`)\r\n\t\t\t\t.join(',')}}`\r\n\t\t: '';\r\n\treturn `${name}${lbl} ${value}`;\r\n}\r\n\r\nexport default ($asai: any) => {\r\n\tconst { sendSuccess, sendFail } = $asai.$lib?.reqWork?.($asai) || {};\r\n\r\n\tasync function get(req: any, res: any, _hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\r\n\t\tif (url.startsWith('/api/sys/health/metrics/')) {\r\n\t\t\ttry {\r\n\t\t\t\tconst mem = process.memoryUsage();\r\n\t\t\t\tlet httpTotal = 0;\r\n\t\t\t\tlet wsTotal = 0;\r\n\t\t\t\tfor (const set of Object.values($asai.connectionshttp || {})) {\r\n\t\t\t\t\thttpTotal += (set as Set<unknown>)?.size || 0;\r\n\t\t\t\t}\r\n\t\t\t\tfor (const set of Object.values($asai.connectionsws || {})) {\r\n\t\t\t\t\twsTotal += (set as Set<unknown>)?.size || 0;\r\n\t\t\t\t}\r\n\t\t\t\tconst lines = [\r\n\t\t\t\t\t'# HELP asai_uptime_seconds Process uptime',\r\n\t\t\t\t\t'# TYPE asai_uptime_seconds gauge',\r\n\t\t\t\t\tpromLine('asai_uptime_seconds', Math.floor(process.uptime())),\r\n\t\t\t\t\t'# HELP asai_memory_rss_bytes Resident memory',\r\n\t\t\t\t\t'# TYPE asai_memory_rss_bytes gauge',\r\n\t\t\t\t\tpromLine('asai_memory_rss_bytes', mem.rss),\r\n\t\t\t\t\t'# HELP asai_http_connections Active HTTP connections',\r\n\t\t\t\t\t'# TYPE asai_http_connections gauge',\r\n\t\t\t\t\tpromLine('asai_http_connections', httpTotal),\r\n\t\t\t\t\t'# HELP asai_ws_connections Active WebSocket connections',\r\n\t\t\t\t\t'# TYPE asai_ws_connections gauge',\r\n\t\t\t\t\tpromLine('asai_ws_connections', wsTotal),\r\n\t\t\t\t\t'# HELP asai_loadavg_1m System load average 1m',\r\n\t\t\t\t\t'# TYPE asai_loadavg_1m gauge',\r\n\t\t\t\t\tpromLine('asai_loadavg_1m', os.loadavg()[0] ?? 0),\r\n\t\t\t\t];\r\n\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n\t\t\t\treturn res.end(lines.join('\\n') + '\\n');\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/sys/health/status/')) {\r\n\t\t\treturn sendSuccess(\r\n\t\t\t\tres,\r\n\t\t\t\t{\r\n\t\t\t\t\tuptime: process.uptime(),\r\n\t\t\t\t\tnode: process.version,\r\n\t\t\t\t\tplatform: process.platform,\r\n\t\t\t\t\tmemory: process.memoryUsage(),\r\n\t\t\t\t\tquota: {\r\n\t\t\t\t\t\thttp: Object.fromEntries(\r\n\t\t\t\t\t\t\tObject.entries($asai.connectionshttp || {}).map(([k, v]) => [k, (v as Set<unknown>)?.size || 0]),\r\n\t\t\t\t\t\t),\r\n\t\t\t\t\t\tws: Object.fromEntries(\r\n\t\t\t\t\t\t\tObject.entries($asai.connectionsws || {}).map(([k, v]) => [k, (v as Set<unknown>)?.size || 0]),\r\n\t\t\t\t\t\t),\r\n\t\t\t\t\t},\r\n\t\t\t\t},\r\n\t\t\t\topt,\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { get };\r\n};\r\n","/**\r\n * IEC 62443-4-2 CR 3.5 / CR 7.6 — 输入校验与消毒\r\n * 供 API/SYS handler 复用,防止注入与异常 payload。\r\n */\r\n\r\nfunction hasControlChars(value: string): boolean {\r\n\tfor (let i = 0; i < value.length; i++) {\r\n\t\tconst c = value.charCodeAt(i);\r\n\t\tif (c === 0x7f) return true;\r\n\t\tif (c <= 0x1f && c !== 0x09 && c !== 0x0a && c !== 0x0d) return true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nexport function rejectControlChars(value: string, field = 'input'): string {\r\n\tif (typeof value !== 'string') return value as unknown as string;\r\n\tif (hasControlChars(value)) {\r\n\t\tthrow new Error(`Invalid ${field}: control characters not allowed`);\r\n\t}\r\n\treturn value;\r\n}\r\n\r\nexport function sanitizeString(value: unknown, maxLen = 4096): string {\r\n\tif (value == null) return '';\r\n\tconst str = String(value);\r\n\trejectControlChars(str);\r\n\treturn str.length > maxLen ? str.slice(0, maxLen) : str;\r\n}\r\n\r\nexport function sanitizePathSegment(segment: unknown): string {\r\n\tconst str = sanitizeString(segment, 256);\r\n\tif (str.includes('..') || str.includes('/') || str.includes('\\\\')) {\r\n\t\tthrow new Error('Invalid path segment');\r\n\t}\r\n\treturn str;\r\n}\r\n\r\nexport function parseJsonSafe(raw: string, maxLen = 1024 * 1024): unknown {\r\n\tif (typeof raw !== 'string') throw new Error('Invalid JSON body');\r\n\tif (raw.length > maxLen) throw new Error('JSON body too large');\r\n\ttry {\r\n\t\treturn JSON.parse(raw);\r\n\t} catch {\r\n\t\tthrow new Error('Invalid JSON');\r\n\t}\r\n}\r\n\r\nexport function assertObject(value: unknown, label = 'payload'): Record<string, unknown> {\r\n\tif (!value || typeof value !== 'object' || Array.isArray(value)) {\r\n\t\tthrow new Error(`${label} must be a plain object`);\r\n\t}\r\n\treturn value as Record<string, unknown>;\r\n}\r\n","import { createHmac, randomInt, randomUUID } from 'node:crypto';\r\nimport type { SessionRecord } from '../store/types';\r\n\r\nexport function getSessionSecret($asai: any): string {\r\n\tconst secret =\r\n\t\tprocess.env.ASAI_SESSION_SECRET ||\r\n\t\t$asai?.hostconfig?.security?.sessionSecret;\r\n\tif (!secret) {\r\n\t\tthrow new Error('[session] ASAI_SESSION_SECRET 未配置');\r\n\t}\r\n\treturn secret;\r\n}\r\n\r\nexport function getSessionTtlMs($asai: any): number {\r\n\tconst hours = $asai?.hostconfig?.security?.sessionTtlHours ?? 24;\r\n\treturn Number(hours) * 3600 * 1000;\r\n}\r\n\r\nconst PRI_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r\n\r\n/**\r\n * 生成会话对称 key(pri)。AsCode.asencode/asdecode 依赖 key 内字符互不重复\r\n * (decode 用 keys.indexOf 定位字符,重复字符会解出错误位置),\r\n * 因此不能用 randomBytes().toString('base64url')(大概率出现重复字符),\r\n * 改为对唯一字符字母表做加密安全洗牌后取前 length 位,天然保证无重复。\r\n */\r\nfunction generatePriKey(length = 32): string {\r\n\tconst arr = PRI_ALPHABET.split('');\r\n\tfor (let i = arr.length - 1; i > 0; i--) {\r\n\t\tconst j = randomInt(i + 1);\r\n\t\t[arr[i], arr[j]] = [arr[j], arr[i]];\r\n\t}\r\n\treturn arr.slice(0, Math.min(length, arr.length)).join('');\r\n}\r\n\r\nexport function createSessionKeys($asai: any): { pri: string; pub: string; sessionId: string } {\r\n\tconst sessionId = randomUUID();\r\n\tconst pri = generatePriKey();\r\n\tconst sn = $asai?.hostconfig?.asaisn;\r\n\tif (!sn) throw new Error('[session] ASAI_ASAISN 未配置');\r\n\t// legacy Userinfo 协议(us##lv##tk)要求 tk 经 asaisn 解密后得到\"和客户端一致\"的对称 key:\r\n\t// 客户端 inittoken() 用 code.pri 加密 us/lv,因此 pub 必须承载 pri(而非 sessionId),\r\n\t// 否则服务端 deUserInfoWithAsai 解出的 key 与客户端不一致,导致所有 lv 鉴权接口恒为 Forbidden。\r\n\tconst pub = $asai.$lib.AsCode.asencode(pri, sn);\r\n\treturn { pri, pub, sessionId };\r\n}\r\n\r\nexport function signSession(sessionId: string, $asai: any): string {\r\n\treturn createHmac('sha256', getSessionSecret($asai)).update(sessionId).digest('hex');\r\n}\r\n\r\nexport function buildSessionRecord($asai: any, us: string, ip: string): SessionRecord {\r\n\tconst { pri, pub, sessionId } = createSessionKeys($asai);\r\n\tconst now = Date.now();\r\n\treturn {\r\n\t\tid: sessionId,\r\n\t\tus,\r\n\t\tip,\r\n\t\tcreatedAt: now,\r\n\t\texpiresAt: now + getSessionTtlMs($asai),\r\n\t\tlastActivityAt: now,\r\n\t\tpri,\r\n\t\tpub,\r\n\t};\r\n}\r\n\r\nexport function isSessionValid(session: SessionRecord): boolean {\r\n\treturn session.expiresAt > Date.now();\r\n}\r\n","import { USER_LV } from './user-levels';\r\nimport { getPermissionThreshold } from './user-level-config';\r\n\r\nconst API_ADMIN_PREFIXES = ['/api/user/login/admin/'];\r\n\r\nexport function getMinLevelForApiPath(pathname: string, $asai?: any): number {\r\n\tif (API_ADMIN_PREFIXES.some((p) => pathname.startsWith(p))) {\r\n\t\tif (pathname.includes('/admin/update') || pathname.includes('/admin/kick') || pathname.includes('/admin/delete')) {\r\n\t\t\treturn $asai ? getPermissionThreshold($asai, 'adminWrite') : USER_LV.DEVELOPER;\r\n\t\t}\r\n\t\treturn $asai ? getPermissionThreshold($asai, 'adminRead') : USER_LV.ADMIN;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nexport function hasLevel(userLevel: number, required: number): boolean {\r\n\treturn Number.isFinite(userLevel) && userLevel >= required;\r\n}\r\n","import { logSecurityEvent, getClientIp } from '../../../infra/security-audit';\r\nimport {\r\n\tlogAccountPurge,\r\n\tlogSecurityConfigIntervention,\r\n\tlogSessionTerminate,\r\n\tlogUserRbacChange,\r\n} from '../../lib/common/intervention-hooks';\r\nimport { sanitizeString } from '../../../infra/input-sanitize';\r\nimport { attachServerUserLevel, getRequestUserLevel } from '../../../infra/user-auth';\r\nimport {\r\n\tgetPasswordPolicy,\r\n\tgetPublicSecurityConfig,\r\n\tisPasswordExpired,\r\n\tresolveRoleForLevel,\r\n} from '../../../infra/security-policy';\r\nimport { createUserStore, ensureBootstrapAdmin } from './store/user-store';\r\nimport {\r\n\thashPassword,\r\n\tnextPassHistory,\r\n\tvalidatePasswordChange,\r\n\tverifyPassword,\r\n} from './service/password';\r\nimport { buildSessionRecord } from './service/session';\r\nimport { getMinLevelForApiPath, hasLevel } from './service/rbac';\r\nimport {\r\n\tgetPermissionThreshold,\r\n\tgetUserLevelConfigSync,\r\n\tisValidUserLv,\r\n\tloadUserLevelConfig,\r\n\tsaveUserLevelConfig,\r\n} from './service/user-level-config';\r\nimport { isUserOnlineOnWs } from '../../../ws/auth';\r\n\r\nfunction parseBody(opt: any): Record<string, unknown> {\r\n\tif (!opt?.data) return {};\r\n\tif (typeof opt.data === 'string') {\r\n\t\ttry {\r\n\t\t\treturn JSON.parse(opt.data);\r\n\t\t} catch {\r\n\t\t\treturn {};\r\n\t\t}\r\n\t}\r\n\treturn typeof opt.data === 'object' ? opt.data : {};\r\n}\r\n\r\nfunction getSecurity($asai: any) {\r\n\treturn $asai?.hostconfig?.security || {};\r\n}\r\n\r\nfunction getQuota($asai: any) {\r\n\tconst sec = getSecurity($asai);\r\n\treturn sec.quota || {};\r\n}\r\n\r\nasync function canLogin($asai: any, us: string): Promise<{ ok: boolean; message?: string }> {\r\n\tconst quota = getQuota($asai);\r\n\tif (!quota.enabled) return { ok: true };\r\n\r\n\tconst store = createUserStore($asai);\r\n\tconst total = await store.countSessions();\r\n\tconst maxLogin = quota.maxLoginSessions ?? $asai?.hostconfig?.hosts?.default?.maxonline ?? 100;\r\n\tif (total >= maxLogin) {\r\n\t\treturn { ok: false, message: 'LOGIN_QUOTA_FULL' };\r\n\t}\r\n\r\n\tconst perUser = await store.countSessionsByUser(us);\r\n\tconst maxPerUser = quota.maxSessionsPerUser ?? 3;\r\n\tif (perUser >= maxPerUser) {\r\n\t\treturn { ok: false, message: 'USER_SESSION_LIMIT' };\r\n\t}\r\n\treturn { ok: true };\r\n}\r\n\r\nfunction publicUser($asai: any, user: any) {\r\n\tconst role = user.role || resolveRoleForLevel($asai, user.lv).name;\r\n\treturn {\r\n\t\tus: user.us,\r\n\t\tlv: user.lv,\r\n\t\trole,\r\n\t\temail: user.email,\r\n\t\tstatus: user.status,\r\n\t\tmustChangePassword: !!user.mustChangePassword,\r\n\t};\r\n}\r\n\r\nlet bootstrapPromise: Promise<void> | null = null;\r\n\r\nfunction ensureReady($asai: any): Promise<void> {\r\n\tif (!bootstrapPromise) {\r\n\t\tbootstrapPromise = Promise.all([ensureBootstrapAdmin($asai), loadUserLevelConfig($asai)]).then(() => undefined);\r\n\t}\r\n\treturn bootstrapPromise;\r\n}\r\n\r\nexport default ($asai: any) => {\r\n\tconst { sendSuccess, sendFail, sendErr } = $asai.$lib?.reqWork?.($asai) || {};\r\n\tconst store = createUserStore($asai);\r\n\r\n\tasync function checkAdmin(req: any, pathname: string, minOverride?: number): Promise<boolean> {\r\n\t\tawait attachServerUserLevel(req, $asai);\r\n\t\tconst minLv = minOverride ?? getMinLevelForApiPath(pathname, $asai);\r\n\t\treturn hasLevel(getRequestUserLevel(req), minLv);\r\n\t}\r\n\r\n\tasync function post(req: any, res: any, hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tconst ip = getClientIp(req);\r\n\t\tconst body = parseBody(opt);\r\n\r\n\t\tif (url.startsWith('/api/user/login/changepass/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\ttry {\r\n\t\t\t\tconst us = sanitizeString(body.us, 64);\r\n\t\t\t\tconst pass = sanitizeString(body.pass, 128);\r\n\t\t\t\tconst newPass = sanitizeString(body.newPass, 128);\r\n\t\t\t\tif (!us || !pass || !newPass) return sendErr(res, 'AUTH_CREDENTIALS_REQUIRED', undefined, opt);\r\n\r\n\t\t\t\tconst user = await store.findByUsername(us);\r\n\t\t\t\tif (!user || !verifyPassword(pass, user.passHash, user.passSalt)) {\r\n\t\t\t\t\treturn sendErr(res, 'AUTH_INVALID_CREDENTIALS', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst policy = getPasswordPolicy($asai);\r\n\t\t\t\tconst policyErr = validatePasswordChange(newPass, $asai, user.passHistory);\r\n\t\t\t\tif (policyErr === 'PASSWORD_TOO_SHORT') {\r\n\t\t\t\t\treturn sendErr(res, policyErr, [String(policy.minLength)], opt);\r\n\t\t\t\t}\r\n\t\t\t\tif (policyErr) return sendErr(res, policyErr, undefined, opt);\r\n\r\n\t\t\t\tconst { passHash, passSalt } = hashPassword(newPass);\r\n\t\t\t\tconst passHistory = nextPassHistory(pass, user.passHistory, policy.historyCount);\r\n\t\t\t\tawait store.updateUser(us, {\r\n\t\t\t\t\tpassHash,\r\n\t\t\t\t\tpassSalt,\r\n\t\t\t\t\tmustChangePassword: 0,\r\n\t\t\t\t\tpasswordChangedAt: Date.now(),\r\n\t\t\t\t\tpassHistory,\r\n\t\t\t\t});\r\n\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: us, ip, detail: 'password_changed' });\r\n\t\t\t\treturn sendSuccess(res, { ok: true }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/register/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\tconst sec = getSecurity($asai);\r\n\t\t\tif (sec.allowRegister === 0) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_REG_DISABLED', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst us = sanitizeString(body.us, 64);\r\n\t\t\t\tconst pass = sanitizeString(body.pass, 128);\r\n\t\t\t\tconst email = body.email ? sanitizeString(body.email, 128) : undefined;\r\n\t\t\t\tconst policyErr = validatePasswordChange(pass, $asai);\r\n\t\t\t\tif (policyErr === 'PASSWORD_TOO_SHORT') {\r\n\t\t\t\t\treturn sendErr(res, policyErr, [String(getPasswordPolicy($asai).minLength)], opt);\r\n\t\t\t\t}\r\n\t\t\t\tif (policyErr) return sendErr(res, policyErr, undefined, opt);\r\n\t\t\t\tconst { passHash, passSalt } = hashPassword(pass);\r\n\t\t\t\tconst user = await store.createUser({\r\n\t\t\t\t\tus,\r\n\t\t\t\t\temail,\r\n\t\t\t\t\tpassHash,\r\n\t\t\t\t\tpassSalt,\r\n\t\t\t\t\tlv: 0,\r\n\t\t\t\t\tpasswordChangedAt: Date.now(),\r\n\t\t\t\t\tpassHistory: '[]',\r\n\t\t\t\t});\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: us, ip, detail: 'register_ok' });\r\n\t\t\t\treturn sendSuccess(res, { user: publicUser($asai, user) }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\tconst msg = err?.message || String(err);\r\n\t\t\t\tif (msg.includes('exists') || msg.includes('已存在')) {\r\n\t\t\t\t\treturn sendErr(res, 'USER_ALREADY_EXISTS', undefined, opt);\r\n\t\t\t\t}\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/auth/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\ttry {\r\n\t\t\t\tconst us = sanitizeString(body.us, 64);\r\n\t\t\t\tconst pass = sanitizeString(body.pass, 128);\r\n\t\t\t\tif (!us || !pass) return sendErr(res, 'AUTH_CREDENTIALS_REQUIRED', undefined, opt);\r\n\r\n\t\t\t\tconst user = await store.findByUsername(us);\r\n\t\t\t\tif (!user || !verifyPassword(pass, user.passHash, user.passSalt)) {\r\n\t\t\t\t\tif (user) {\r\n\t\t\t\t\t\tconst sec = getSecurity($asai);\r\n\t\t\t\t\t\tconst lockoutMax = sec.lockoutMaxFails ?? 5;\r\n\t\t\t\t\t\tconst lockoutMin = sec.lockoutMinutes ?? 15;\r\n\t\t\t\t\t\tconst failCount = (user.failCount || 0) + 1;\r\n\t\t\t\t\t\tconst patch: any = { failCount };\r\n\t\t\t\t\t\tif (failCount >= lockoutMax) {\r\n\t\t\t\t\t\t\tpatch.status = 'locked';\r\n\t\t\t\t\t\t\tpatch.lockedUntil = Date.now() + lockoutMin * 60 * 1000;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tawait store.updateUser(us, patch);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlogSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: us, ip });\r\n\t\t\t\t\treturn sendErr(res, 'AUTH_INVALID_CREDENTIALS', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (user.status === 'disabled') {\r\n\t\t\t\t\treturn sendErr(res, 'AUTH_ACCOUNT_DISABLED', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (user.status === 'locked' && user.lockedUntil && user.lockedUntil > Date.now()) {\r\n\t\t\t\t\treturn sendErr(res, 'AUTH_ACCOUNT_LOCKED', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst policy = getPasswordPolicy($asai);\r\n\t\t\t\tconst mustChange =\r\n\t\t\t\t\t!!user.mustChangePassword ||\r\n\t\t\t\t\tisPasswordExpired(user.passwordChangedAt, policy.maxAgeDays);\r\n\r\n\t\t\t\tconst hostcfg = $asai.getHost?.(hostdir) || {};\r\n\t\t\t\tif (hostcfg.ckws && isUserOnlineOnWs($asai, us, hostdir)) {\r\n\t\t\t\t\tlogSecurityEvent($asai, {\r\n\t\t\t\t\t\ttype: 'AUTH_FAIL',\r\n\t\t\t\t\t\tpath: url,\r\n\t\t\t\t\t\tmethod: 'POST',\r\n\t\t\t\t\t\tuser: us,\r\n\t\t\t\t\t\tip,\r\n\t\t\t\t\t\tdetail: 'user_already_online',\r\n\t\t\t\t\t});\r\n\t\t\t\t\treturn sendErr(res, 'USER_ALREADY_LOGGED', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst quotaCheck = await canLogin($asai, us);\r\n\t\t\t\tif (!quotaCheck.ok) {\r\n\t\t\t\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: url, method: 'POST', user: us, ip, detail: quotaCheck.message });\r\n\t\t\t\t\treturn sendErr(res, quotaCheck.message || 'LOGIN_QUOTA_FULL', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tawait store.updateUser(us, { failCount: 0, status: 'active', lockedUntil: undefined });\r\n\t\t\t\tconst session = buildSessionRecord($asai, us, ip);\r\n\t\t\t\tsession.lastActivityAt = Date.now();\r\n\t\t\t\tawait store.addSession(session);\r\n\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: us, ip, detail: 'login_ok' });\r\n\r\n\t\t\t\treturn sendSuccess(\r\n\t\t\t\t\tres,\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuser: { ...publicUser($asai, user), mustChangePassword: mustChange },\r\n\t\t\t\t\t\tcode: mustChange ? null : [session.pri, session.pub],\r\n\t\t\t\t\t\tsessionId: mustChange ? null : session.id,\r\n\t\t\t\t\t\tmustChangePassword: mustChange,\r\n\t\t\t\t\t},\r\n\t\t\t\t\topt,\r\n\t\t\t\t);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/logout/')) {\r\n\t\t\ttry {\r\n\t\t\t\tconst bodySid = body.sessionId ? sanitizeString(body.sessionId, 64) : '';\r\n\t\t\t\tif (bodySid) await store.removeSession(bodySid);\r\n\t\t\t\tconst us = req?.Userinfo?.[0];\r\n\t\t\t\tif (us) logSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: String(us), ip, detail: 'logout' });\r\n\t\t\t\treturn sendSuccess(res, 'ok', opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/kick/')) {\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminWrite')))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst sessionId = sanitizeString(body.sessionId, 64);\r\n\t\t\t\tif (!sessionId) return sendErr(res, 'AUTH_CREDENTIALS_REQUIRED', undefined, opt);\r\n\t\t\t\tconst sessions = await store.getSessions();\r\n\t\t\t\tconst target = sessions.find((s) => s.id === sessionId);\r\n\t\t\t\tawait store.removeSession(sessionId);\r\n\t\t\t\tconst operator = String(req?.Userinfo?.[0] || '');\r\n\t\t\t\tawait logSessionTerminate($asai, {\r\n\t\t\t\t\toperator,\r\n\t\t\t\t\tsessionId,\r\n\t\t\t\t\ttargetUs: target?.us,\r\n\t\t\t\t\tip,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, { ok: true }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/delete/')) {\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminWrite')))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst targetUs = sanitizeString(body.us, 64);\r\n\t\t\t\tif (!targetUs || targetUs === 'admin') return sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t\tconst ok = await store.deleteUser(targetUs);\r\n\t\t\t\tif (!ok) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\t\t\t\tconst operator = String(req?.Userinfo?.[0] || '');\r\n\t\t\t\tawait logAccountPurge($asai, { operator, targetUs, ip });\r\n\t\t\t\treturn sendSuccess(res, { ok: true }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/levels/')) {\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminWrite')))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst levels = Array.isArray(body.levels) ? body.levels : undefined;\r\n\t\t\t\tconst thresholds =\r\n\t\t\t\t\tbody.thresholds && typeof body.thresholds === 'object' ? (body.thresholds as Record<string, unknown>) : undefined;\r\n\t\t\t\tconst routeRights = Array.isArray(body.routeRights) ? body.routeRights : undefined;\r\n\t\t\t\tconst operator = String(req?.Userinfo?.[0] || '');\r\n\t\t\t\tconst cfg = await saveUserLevelConfig(\r\n\t\t\t\t\t$asai,\r\n\t\t\t\t\t{ levels: levels as any, thresholds: thresholds as any, routeRights: routeRights as any },\r\n\t\t\t\t\toperator,\r\n\t\t\t\t);\r\n\t\t\t\tawait logSecurityConfigIntervention($asai, {\r\n\t\t\t\t\tsection: 'user_levels',\r\n\t\t\t\t\tdetail: JSON.stringify({ levels: levels?.length, thresholds: !!thresholds, routeRights: routeRights?.length }),\r\n\t\t\t\t\toperator,\r\n\t\t\t\t\tip,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, cfg, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/update/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\tif (!(await checkAdmin(req, url))) {\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'ACCESS_DENIED', path: url, method: 'POST', ip });\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst targetUs = sanitizeString(body.us, 64);\r\n\t\t\t\tconst patch: any = {};\r\n\t\t\t\tif (body.lv != null) {\r\n\t\t\t\t\tconst newLv = Number(body.lv);\r\n\t\t\t\t\tif (!Number.isFinite(newLv) || !isValidUserLv($asai, newLv)) {\r\n\t\t\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpatch.lv = newLv;\r\n\t\t\t\t\tpatch.role = resolveRoleForLevel($asai, newLv).name;\r\n\t\t\t\t}\r\n\t\t\t\tif (body.status) patch.status = sanitizeString(body.status, 16);\r\n\t\t\t\tif (body.resetLock) {\r\n\t\t\t\t\tpatch.failCount = 0;\r\n\t\t\t\t\tpatch.status = 'active';\r\n\t\t\t\t\tpatch.lockedUntil = undefined;\r\n\t\t\t\t}\r\n\t\t\t\tif (body.mustChangePassword != null) patch.mustChangePassword = body.mustChangePassword ? 1 : 0;\r\n\t\t\t\tconst updated = await store.updateUser(targetUs, patch);\r\n\t\t\t\tif (!updated) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\t\t\t\tif (Object.keys(patch).length) {\r\n\t\t\t\t\tawait logUserRbacChange($asai, {\r\n\t\t\t\t\t\toperator: String(req?.Userinfo?.[0] || ''),\r\n\t\t\t\t\t\ttargetUs,\r\n\t\t\t\t\t\tpatch,\r\n\t\t\t\t\t\tip,\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t\treturn sendSuccess(res, { user: publicUser($asai, updated) }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/profile/')) {\r\n\t\t\tconst us = req?.Userinfo?.[0];\r\n\t\t\tif (!us) return sendErr(res, 'AUTH_UNAUTHORIZED', undefined, opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst user = await store.findByUsername(String(us));\r\n\t\t\t\tif (!user) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\r\n\t\t\t\tif (body.newPass) {\r\n\t\t\t\t\tconst newPass = sanitizeString(body.newPass, 128);\r\n\t\t\t\t\tconst policy = getPasswordPolicy($asai);\r\n\r\n\t\t\t\t\tif (body.pass) {\r\n\t\t\t\t\t\tif (!verifyPassword(String(body.pass), user.passHash, user.passSalt)) {\r\n\t\t\t\t\t\t\treturn sendErr(res, 'AUTH_INVALID_PASSWORD', undefined, opt);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else if (!user.mustChangePassword) {\r\n\t\t\t\t\t\treturn sendErr(res, 'AUTH_INVALID_PASSWORD', undefined, opt);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst policyErr = validatePasswordChange(newPass, $asai, user.passHistory);\r\n\t\t\t\t\tif (policyErr === 'PASSWORD_TOO_SHORT') {\r\n\t\t\t\t\t\treturn sendErr(res, policyErr, [String(policy.minLength)], opt);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (policyErr) return sendErr(res, policyErr, undefined, opt);\r\n\r\n\t\t\t\t\tconst { passHash, passSalt } = hashPassword(newPass);\r\n\t\t\t\t\tconst passHistory = nextPassHistory(String(body.pass || newPass), user.passHistory, policy.historyCount);\r\n\t\t\t\t\tawait store.updateUser(String(us), {\r\n\t\t\t\t\t\tpassHash,\r\n\t\t\t\t\t\tpassSalt,\r\n\t\t\t\t\t\tmustChangePassword: 0,\r\n\t\t\t\t\t\tpasswordChangedAt: Date.now(),\r\n\t\t\t\t\t\tpassHistory,\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst fresh = await store.findByUsername(String(us));\r\n\t\t\t\treturn sendSuccess(res, { user: fresh ? publicUser($asai, fresh) : null }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tasync function get(req: any, res: any, hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tconst ip = getClientIp(req);\r\n\r\n\t\tif (url.startsWith('/api/user/login/config/')) {\r\n\t\t\tconst lang = String(req?.headers?.['accept-language'] || opt?.headers?.['accept-language'] || 'zh-CN').split(',')[0];\r\n\t\t\treturn sendSuccess(res, getPublicSecurityConfig($asai, lang), opt);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/levels/')) {\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminRead')))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\tawait loadUserLevelConfig($asai);\r\n\t\t\treturn sendSuccess(res, getUserLevelConfigSync($asai), opt);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/sessions/')) {\r\n\t\t\tif (!(await checkAdmin(req, url))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\tconst sessions = await store.getSessions();\r\n\t\t\treturn sendSuccess(\r\n\t\t\t\tres,\r\n\t\t\t\t{\r\n\t\t\t\t\tsessions: sessions.map((s) => ({\r\n\t\t\t\t\t\tid: s.id,\r\n\t\t\t\t\t\tus: s.us,\r\n\t\t\t\t\t\tip: s.ip,\r\n\t\t\t\t\t\tcreatedAt: s.createdAt,\r\n\t\t\t\t\t\texpiresAt: s.expiresAt,\r\n\t\t\t\t\t\tlastActivityAt: s.lastActivityAt,\r\n\t\t\t\t\t})),\r\n\t\t\t\t},\r\n\t\t\t\topt,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/list/')) {\r\n\t\t\tif (!(await checkAdmin(req, url))) {\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'ACCESS_DENIED', path: url, method: 'GET', ip });\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\tconst users = await store.listUsers();\r\n\t\t\treturn sendSuccess(res, { users: users.map((u) => publicUser($asai, u)) }, opt);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/quota/')) {\r\n\t\t\tif (!(await checkAdmin(req, url))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\tconst sessions = await store.getSessions();\r\n\t\t\tconst quota = getQuota($asai);\r\n\t\t\treturn sendSuccess(\r\n\t\t\t\tres,\r\n\t\t\t\t{\r\n\t\t\t\t\tsessions: sessions.length,\r\n\t\t\t\t\tmaxLoginSessions: quota.maxLoginSessions ?? 100,\r\n\t\t\t\t\tquotaEnabled: !!quota.enabled,\r\n\t\t\t\t\thttp: $asai.connectionshttp,\r\n\t\t\t\t\tws: $asai.connectionsws,\r\n\t\t\t\t},\r\n\t\t\t\topt,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/profile/')) {\r\n\t\t\tconst us = req?.Userinfo?.[0];\r\n\t\t\tif (!us) return sendErr(res, 'AUTH_UNAUTHORIZED', undefined, opt);\r\n\t\t\tconst user = await store.findByUsername(String(us));\r\n\t\t\treturn sendSuccess(res, { user: user ? publicUser($asai, user) : null }, opt);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { post, get };\r\n};\r\n","import logManage from \"./common/logmanage\";\r\nimport interventionLog from \"./common/interventionlog\";\r\nimport unifiedLog from \"./common/unifiedlog\";\r\nimport errorcodes from \"./common/errorcodes\";\r\nimport sqliteManage from \"./common/sqlitemanage\";\r\nimport health from \"./common/health\";\r\nimport userLogin from \"./login/index\";\r\n\r\nexport default {\r\n \"asailog/manage\": logManage,\r\n \"asailog/intervention\": interventionLog,\r\n \"asailog/store\": unifiedLog,\r\n \"sys/errorcodes\": errorcodes,\r\n \"sys/health\": health,\r\n \"asaisqlite/manage\": sqliteManage,\r\n \"user/login\": userLogin,\r\n};\r\n","export default {\n ctxErr(ec: string, params?: string | string[] | null, _opt: any = null) {\n const pm =\n params == null\n ? undefined\n : Array.isArray(params)\n ? params.map(String)\n : [String(params)];\n return { code: 907, data: { ec, pm } };\n },\n ctxFail(val: any, opt: any = null) {\n if (val && typeof val === 'object' && typeof val.ec === 'string') {\n return { code: 907, data: val };\n }\n if (val instanceof Error) {\n val = val.message || String(val);\n } else if (val && typeof val === 'object' && typeof val.message === 'string') {\n val = val.message;\n }\n return { code: 907, data: val };\n },\n ctxEmpty(val: string, opt: any = null) {\n return { code: 908, data: val };\n },\n ctxSuccess(val: any, opt: any = null) {\n if (typeof opt?.resAES === 'function') {\n val = opt.resAES(val);\n }\n return { code: 909, data: val };\n },\n getPath(str: string = '-') {\n return str?.replace(/[^a-zA-Z0-9.\\-_\\\\\\/]/g, '');\n },\n getName(str: string = '-') {\n return str?.replace(/[^a-zA-Z0-9.\\-_]/g, '');\n },\n\n toDirPath(relativePath: string) {\n const pathArr = relativePath.split('/');\n pathArr.pop();\n const dirPath = pathArr.join('/') + '//';\n return dirPath;\n },\n toAbsolutePath(relativePath: string) {\n relativePath = process.cwd() + relativePath;\n relativePath = relativePath.replace(/\\\\/g, '/');\n return relativePath;\n },\n //创建多层文件夹 同步\n ensureDir(fs: any, relativePath: string) {\n const absPathDir = this.toDirPath(relativePath);\n const absPath = this.toAbsolutePath(relativePath);\n if (!fs.existsSync(absPath)) {\n let pathTmp: string = '';\n absPathDir.split('/').forEach((el: string) => {\n if (el) {\n if (pathTmp) {\n pathTmp += '/';\n }\n pathTmp += el;\n if (!fs.existsSync(pathTmp)) {\n if (!fs.mkdirSync(pathTmp, { recursive: true })) {\n return absPath;\n }\n }\n }\n });\n }\n return absPath;\n },\n makeDir(fs: any, filePaths: string) {\n return new Promise((resolve, reject) => {\n try {\n const newPath = this.ensureDir(fs, filePaths);\n resolve(newPath);\n } catch (err: any) {\n reject(err);\n }\n });\n },\n getFilePath(str: string = '-') {\n let filePath = '';\n let filePaths = '';\n if (str.startsWith('/')) {\n // 这个情况,替换文件,如果需要解析的话,需要自己前端处理\n filePath = this.getPath(str);\n } else if (str.indexOf('/') > -1) {\n // 不安全的!!!\n if (str.startsWith('../')) {\n filePath = this.getPath('/' + str);\n } else {\n filePath = '/webdata/upload/' + this.getPath(str);\n }\n } else {\n filePath = '/webdata/upload/' + this.getName(str);\n }\n filePaths = this.toAbsolutePath(filePath);\n return { filePath, filePaths };\n },\n // 防抖与节流\n // debounce(() => {}, {\n // timeout: null,\n // starttime: 0,\n // endtime: 0,\n // wait: 300,\n // immediate: false,\n // });\n dtImmediate(fn: any, opt: any) {\n if (opt?.immediate) {\n // 立即执行一次\n fn();\n opt.immediate = false;\n }\n },\n dtClearTimeout(opt: any) {\n clearTimeout(opt.timeout);\n opt.timeout = null;\n },\n dtSetTimeout(fn: any, opt: any) {\n return setTimeout(() => {\n fn();\n this.dtClearTimeout(opt);\n }, opt.wait);\n },\n // 防抖:连续触发过程中,仅在数据持续指定长度时间不变时fn一次\n debounce(fn: any, opt: any) {\n this.dtImmediate(fn, opt);\n opt.endtime = new Date().valueOf();\n if (opt.endtime - opt.starttime < opt.wait) {\n this.dtClearTimeout(opt);\n }\n if (!opt?.timeout) {\n opt.starttime = opt.endtime;\n opt.timeout = this.dtSetTimeout(fn, opt);\n }\n },\n // 节流:指定长度时间内有多次触发,只fn最后一次触发\n throttle(fn: any, opt: any) {\n this.dtImmediate(fn, opt);\n if (!opt?.timeout) {\n opt.timeout = this.dtSetTimeout(fn, opt);\n }\n },\n /**\n * 简化版\n * @param startsWord 定义起始字符,如:as\n * @param hex 指定进制,如:10 16 32\n * @returns 12位,前缀字符+时间戳换算+随机数补位,如:eelgullaqnb0\n */\n Uuid(startsWord: string = '', index: number = 0, hex: number = 32): string {\n let ids: string = Date.now().toString(36);\n if (index > 0) {\n ids += index.toString(36);\n }\n ids = ids.slice(-9);\n if (startsWord) {\n ids = startsWord.slice(-3) + ids;\n }\n let strLen: number = ids.length;\n while (strLen < 16) {\n ids += ((Math.random() * hex) | 0).toString(hex).slice(-1);\n strLen++;\n }\n return ids;\n },\n getIp(req: any) {\n const forwarded = req.headers['x-forwarded-for'];\n return forwarded ? forwarded.split(',')[0] : req.connection.remoteAddress;\n },\n};\n","export default {\r\n // 加密\r\n asencode(str: string, keys: string) {\r\n const strlen: number = str?.length || 0;\r\n const keyslen: number = keys?.length || 0;\r\n let newstr: string = '';\r\n for (let i = 0; i < strlen; i++) {\r\n const rnum: number = Math.round(Math.random() * 1000) % keyslen;\r\n const rnumx: number = Number(rnum.toString().slice(-1)) + 1;\r\n const ylen: number = keyslen - rnumx;\r\n let tmpnum = str.codePointAt(i) as number;\r\n const y1: number = tmpnum % ylen;\r\n tmpnum = (tmpnum - y1) / ylen;\r\n const y2: number = tmpnum % ylen;\r\n tmpnum = (tmpnum - y2) / ylen;\r\n newstr +=\r\n keys[(tmpnum % ylen) + rnumx] +\r\n keys[y2 + rnumx] +\r\n keys[y1 + rnumx] +\r\n keys.charAt(rnum);\r\n }\r\n return newstr;\r\n },\r\n\r\n // 解密\r\n asdecode(str: string, keys: string) {\r\n try {\r\n const strlen: number = str.length;\r\n const keyslen: number = keys.length;\r\n let newstr: string = '';\r\n for (let i = 0; i < strlen; i++) {\r\n const rnum: number = keys.indexOf(str[i + 3]);\r\n const rnumx: number = Number(rnum.toString().slice(-1)) + 1;\r\n const ylen: number = keyslen - rnumx;\r\n newstr += String?.fromCodePoint(\r\n (keys.indexOf(str[i++]) - rnumx) * ylen * ylen +\r\n (keys.indexOf(str[i++]) - rnumx) * ylen +\r\n (keys.indexOf(str[i++]) - rnumx)\r\n );\r\n }\r\n return newstr;\r\n } catch (error) {\r\n return '';\r\n }\r\n },\r\n getCodeData(data: any, keys: string) {\r\n try {\r\n data = JSON.parse(data);\r\n return JSON.parse(\r\n this.asdecode(data.data, this.asdecode(data.code, keys))\r\n );\r\n } catch (error) {\r\n return;\r\n }\r\n },\r\n sendCodeData(data: any, keys: string, code: string) {\r\n return {\r\n code: code,\r\n data: this.asencode(\r\n JSON.stringify(data),\r\n this.asdecode(code, keys)\r\n ),\r\n };\r\n },\r\n // 打乱字符\r\n asnewkey(str: string) {\r\n const newarr: string[] = [];\r\n str.split('').forEach((el: string) => {\r\n newarr.splice(Math.round(Math.random() * newarr.length), 0, el);\r\n });\r\n return newarr.join('');\r\n },\r\n};\r\n","import crypto from 'crypto';\r\n\r\nexport default ($asai: any, cfg: any = null) => {\r\n const AES_KEY = Buffer.from($asai.hostconfig.aes.keybase64, 'base64');\r\n const AES_AAD = Buffer.from($asai.hostconfig.aes.aad, 'utf8');\r\n\r\n function safeJsonParse(value: any) {\r\n if (typeof value !== 'string') return value;\r\n try {\r\n return JSON.parse(value);\r\n } catch {\r\n return value;\r\n }\r\n }\r\n\r\n function decodeBase64(value: string): Buffer {\r\n if (typeof value !== 'string') {\r\n throw new TypeError('Expected base64 string.');\r\n }\r\n return Buffer.from(value, 'base64');\r\n }\r\n\r\n function encrypt(plaintext: string) {\r\n const iv = crypto.randomBytes($asai.hostconfig.aes.ivlength);\r\n const cipher = crypto.createCipheriv($asai.hostconfig.aes.algorithm, AES_KEY, iv);\r\n cipher.setAAD(AES_AAD);\r\n const encryptedBuffer = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\r\n return {\r\n data: encryptedBuffer.toString('base64'),\r\n iv: iv.toString('base64'),\r\n auth: cipher.getAuthTag().toString('base64')\r\n };\r\n }\r\n\r\n function decrypt(encrypto: any) {\r\n const iv = decodeBase64(encrypto.iv);\r\n const authTag = decodeBase64(encrypto.auth);\r\n const encrypted = decodeBase64(encrypto.data);\r\n const decipher = crypto.createDecipheriv($asai.hostconfig.aes.algorithm, AES_KEY, iv);\r\n decipher.setAAD(AES_AAD);\r\n decipher.setAuthTag(authTag);\r\n const decryptedBuffer = Buffer.concat([decipher.update(encrypted), decipher.final()]);\r\n return decryptedBuffer.toString('utf8');\r\n }\r\n\r\n function validateFields(payload: any, fields: string[]) {\r\n return fields.every((key) => typeof payload?.[key] === 'string' && payload[key].length > 0);\r\n }\r\n\r\n function reqAES(opt: any, fn: any = (data: any) => data) {\r\n const reqData = safeJsonParse(opt.data);\r\n try {\r\n if (validateFields(reqData, [\"data\", \"iv\", \"auth\"])) {\r\n let aesData: any = decrypt(reqData)\r\n if (reqData?.aes === 2) {\r\n aesData = JSON.parse(aesData);\r\n }\r\n return fn(aesData);\r\n } else {\r\n return fn(reqData);\r\n }\r\n } catch (error: any) {\r\n return reqData;\r\n }\r\n }\r\n function resAES(data: any) {\r\n try {\r\n let aesty: number = 1;\r\n if (data && typeof data === 'object') {\r\n data = JSON.stringify(data);\r\n aesty = 2;\r\n }\r\n return Object.assign({ aes: aesty }, encrypt(data));\r\n } catch (error: any) {\r\n return data;\r\n }\r\n }\r\n\r\n return { encrypt, decrypt, reqAES, resAES };\r\n};","import { getDataServerForAsDb } from \"../../db/data-store\";\r\n\r\nexport default ($asai: any, cfg: any) => {\r\n const DataServer: any = getDataServerForAsDb($asai, {\r\n type: cfg?.type || \"sqlite\",\r\n opt: {\r\n ...(cfg?.opt || {\r\n database: \"./webdata/webdb/sqlite/asaisqlite.db\",\r\n create: 1,\r\n }),\r\n },\r\n storeKey: cfg?.storeKey,\r\n });\r\n\r\n function reqwherestr(str: any) {\r\n if (cfg?.type === \"sqlite\" || cfg?.type === \"mysql\") {\r\n return `'${str}'`;\r\n }\r\n return str;\r\n }\r\n\r\n function reqfield(queryData: any) {\r\n if (queryData?.fd) {\r\n return queryData.fd.split(\"-\");\r\n }\r\n return cfg.field.data;\r\n }\r\n\r\n function reqwhere(queryData: any) {\r\n const wheretmp: any[] = [];\r\n if ((cfg?.type === \"sqlite\" || cfg?.type === \"mysql\") && queryData?.wlv) {\r\n const wlvarr = queryData.wlv.split(\"-\");\r\n wheretmp.push([wlvarr[0], \">\", Number(wlvarr[1] || 0)]);\r\n }\r\n if (queryData?.fl) {\r\n wheretmp.push([cfg.field.class, \"LIKE\", reqwherestr(`${queryData.fl}%`)]);\r\n }\r\n if (queryData?.ss && queryData?.ssty) {\r\n wheretmp.push([queryData.ssty, \"LIKE\", reqwherestr(`%${queryData.ss}%`)]);\r\n }\r\n if (wheretmp.length > 1) {\r\n wheretmp.unshift(\"and\");\r\n }\r\n return wheretmp;\r\n }\r\n\r\n function reqorder(queryData: any) {\r\n const ordertmp: any[] = [];\r\n if (queryData?.sx) {\r\n ordertmp.push([queryData.sx, queryData?.sxty == 1 ? \"DESC\" : \"ASC\"]);\r\n }\r\n return ordertmp;\r\n }\r\n\r\n function reqlimit(queryData: any) {\r\n let limittmp = \"\";\r\n let limitps: number = queryData?.ps;\r\n if (queryData?.pg) {\r\n limitps = limitps || 20;\r\n limittmp = `${(queryData.pg - 1) * limitps},${limitps}`;\r\n } else if (limitps) {\r\n limittmp += limitps;\r\n }\r\n return limittmp;\r\n }\r\n\r\n function getSqlParamsByUrl(req: any, opt: any) {\r\n let tmpSqlParams: any;\r\n const reqArr: any = req?.url?.split(\"?\")[0]?.split(\"/\") || [];\r\n const table = (opt?.qrdata?.table || opt?.data?.table || reqArr[3]).replaceAll(\"_\", \"/\");\r\n if (!table) return tmpSqlParams;\r\n\r\n tmpSqlParams = {\r\n type: \"select\",\r\n table,\r\n };\r\n\r\n if (reqArr[5]) {\r\n if (reqArr[4] === \"insert\") {\r\n tmpSqlParams.type = reqArr[4];\r\n if (cfg?.type === \"file\") {\r\n tmpSqlParams.field = cfg.field.data;\r\n tmpSqlParams.value = [[reqwherestr(reqArr[5]), reqwherestr(opt.data)]];\r\n } else {\r\n tmpSqlParams.field = [];\r\n tmpSqlParams.value = [];\r\n const tmpValue: any[] = [];\r\n const dbData: any = typeof opt.data === \"string\" ? JSON.parse(opt.data) : opt.data;\r\n Object.entries(dbData).forEach((el: any) => {\r\n if (cfg.field.data.includes(el[0])) {\r\n tmpSqlParams.field.push(el[0]);\r\n tmpValue.push(el[1]);\r\n }\r\n });\r\n if (!tmpSqlParams.field.includes(cfg.field.key)) {\r\n tmpSqlParams.field.push(cfg.field.key);\r\n tmpValue.push(reqArr[5]);\r\n }\r\n tmpSqlParams.value.push(tmpValue);\r\n }\r\n } else if (reqArr[4] === \"update\") {\r\n tmpSqlParams.type = reqArr[4];\r\n tmpSqlParams.where = [[cfg.field.key, \"=\", reqwherestr(reqArr[5])]];\r\n if (cfg?.type === \"file\") {\r\n tmpSqlParams.set = [[cfg.field.key, reqwherestr(opt.data)]];\r\n } else {\r\n tmpSqlParams.set = [];\r\n const dbData: any = typeof opt.data === \"string\" ? JSON.parse(opt.data) : opt.data;\r\n Object.entries(dbData).forEach((el: any) => {\r\n if (cfg.field.data.includes(el[0])) {\r\n if (Array.isArray(el[1])) {\r\n tmpSqlParams.set.push([el[0], ...el[1]]);\r\n } else {\r\n tmpSqlParams.set.push([el[0], el[1]]);\r\n }\r\n }\r\n });\r\n }\r\n } else if (reqArr[4] === \"delete\") {\r\n tmpSqlParams.type = reqArr[4];\r\n tmpSqlParams.where = [[cfg.field.key, \"=\", reqwherestr(reqArr[5])]];\r\n } else {\r\n if (cfg?.as > 1) {\r\n tmpSqlParams.as = +cfg.as - 1;\r\n }\r\n tmpSqlParams.field = cfg.field.data;\r\n tmpSqlParams.where = [[cfg.field.key, \"=\", reqwherestr(reqArr[5])]];\r\n }\r\n } else {\r\n tmpSqlParams.as = cfg?.as;\r\n tmpSqlParams.field = reqfield(opt.data);\r\n tmpSqlParams.where = reqwhere(opt.data);\r\n tmpSqlParams.order = reqorder(opt.data);\r\n tmpSqlParams.limit = reqlimit(opt.data);\r\n }\r\n\r\n return tmpSqlParams;\r\n }\r\n\r\n function dbFresh(req: any, resdb: any) {\r\n if (req?.url?.includes(\"/selectlist/\")) {\r\n const list = Array.isArray(resdb) ? resdb : resdb?.data;\r\n if (Array.isArray(list)) {\r\n const mapped = list.map((el: any) => {\r\n const rawName = el.name ?? el.file ?? \"\";\r\n let tmpName: string = String(rawName).substring(String(rawName).lastIndexOf(\"/\") + 1);\r\n const dot = tmpName.lastIndexOf(\".\");\r\n return dot > -1 ? tmpName.substring(0, dot) : tmpName;\r\n });\r\n if (Array.isArray(resdb)) return mapped;\r\n resdb.data = mapped;\r\n }\r\n }\r\n return resdb;\r\n }\r\n\r\n function dbCodePm(req: any, resdb: any) {\r\n if (req?.Userinfo && req?.Userinfo[2]) {\r\n resdb.data = $asai.$lib.AsCode.asencode(JSON.stringify(resdb.data), req.Userinfo[2]);\r\n }\r\n return resdb;\r\n }\r\n\r\n function runDefaultPost(req: any, res: any, opt: any) {\r\n const params = getSqlParamsByUrl(req, opt);\r\n if (params) {\r\n DataServer.sqlDb(params)\r\n .then((resdb: any) => {\r\n res.end(JSON.stringify($asai.$lib.As.ctxSuccess(dbCodePm(req, dbFresh(req, resdb)), opt)));\r\n })\r\n .catch((errdb: any) => {\r\n const msg = String(errdb?.message || errdb || \"\");\r\n if (params?.type === \"select\" && msg.includes(\"no such table\")) {\r\n res.end(JSON.stringify($asai.$lib.As.ctxSuccess([], opt)));\r\n return;\r\n }\r\n res.end(JSON.stringify($asai.$lib.As.ctxFail(errdb)));\r\n });\r\n } else {\r\n res.end(JSON.stringify({ code: 901 }));\r\n }\r\n }\r\n\r\n function runDefaultGet(req: any, res: any, opt: any) {\r\n const params = getSqlParamsByUrl(req, opt);\r\n if (params && typeof DataServer.sqlDb === \"function\") {\r\n try {\r\n DataServer.sqlDb(params)\r\n .then((resdb: any) => {\r\n let resData: any = dbFresh(req, resdb);\r\n if (params?.as === 2 && params?.field?.length > 1) {\r\n let limitArr: any[] = [];\r\n if (params.limit?.split(\",\")?.length < 2) {\r\n limitArr = [0, +params.limit?.split(\",\")?.[0]];\r\n } else {\r\n limitArr = params.limit.split(\",\");\r\n limitArr = [+limitArr[0], +limitArr[0] + +limitArr[1]];\r\n }\r\n if (resData.data?.length) {\r\n resData.data = resData.data.slice(+limitArr[0], +limitArr[1]);\r\n }\r\n }\r\n resData = dbCodePm(req, resData);\r\n res.end(JSON.stringify($asai.$lib.As.ctxSuccess(resData, opt)));\r\n })\r\n .catch((errdb: any) => {\r\n const msg = String(errdb?.message || errdb || \"\");\r\n if (params?.type === \"select\" && msg.includes(\"no such table\")) {\r\n res.end(JSON.stringify($asai.$lib.As.ctxSuccess([], opt)));\r\n return;\r\n }\r\n res.end(JSON.stringify($asai.$lib.As.ctxFail(errdb)));\r\n });\r\n } catch {\r\n res.end(JSON.stringify({ code: 901 }));\r\n }\r\n } else {\r\n res.end(JSON.stringify({ code: 901 }));\r\n }\r\n }\r\n\r\n function post(req: any, res: any, hostdir: string, opt: any) {\r\n if (cfg?.post && typeof cfg.post === \"function\") {\r\n Promise.resolve(cfg.post(req, res, hostdir, opt, DataServer))\r\n .then((reqstat) => {\r\n if (!reqstat) runDefaultPost(req, res, opt);\r\n })\r\n .catch((errdb: any) => {\r\n res.end(JSON.stringify($asai.$lib.As.ctxFail(errdb)));\r\n });\r\n return;\r\n }\r\n runDefaultPost(req, res, opt);\r\n }\r\n\r\n function get(req: any, res: any, hostdir: string, opt: any) {\r\n if (cfg?.get && typeof cfg.get === \"function\") {\r\n Promise.resolve(cfg.get(req, res, hostdir, opt, DataServer))\r\n .then((reqstat) => {\r\n if (!reqstat) runDefaultGet(req, res, opt);\r\n })\r\n .catch((errdb: any) => {\r\n res.end(JSON.stringify($asai.$lib.As.ctxFail(errdb)));\r\n });\r\n return;\r\n }\r\n runDefaultGet(req, res, opt);\r\n }\r\n\r\n return { DataServer, post, get };\r\n};\r\n","export default ($asai: any) => {\n /** tsx 下 CJS/ESM 互操作时 default 导出常在 .default 上 */\n function hostDefault<T>(mod: T): T {\n if (mod && typeof mod === \"object\" && \"default\" in (mod as object)) {\n const d = (mod as unknown as { default: T }).default;\n if (d !== undefined) return d;\n }\n return mod;\n }\n /**\n * 从请求选项中提取文件路径\n */\n function getPathFromOpt(opt: any): string {\n const rawPath = opt.qrdata?.path || opt.data?.path;\n return decodeURIComponent(rawPath);\n }\n\n /**\n * 发送成功响应\n */\n function sendSuccess(res: any, data: any, opt: any) {\n const response = $asai.$lib.As.ctxSuccess(data, opt);\n res.end(JSON.stringify(response));\n }\n\n /**\n * 发送结构化错误码响应(data: { ec, pm? })\n */\n function sendErr(res: any, ec: string, params?: string | string[], opt?: any) {\n const ErrorCode = $asai.$lib?.ErrorCode;\n ErrorCode?.loadErrorCodes?.($asai);\n ErrorCode?.logError?.($asai, ec, Array.isArray(params) ? params.map(String) : params != null ? [String(params)] : undefined);\n const response = $asai.$lib.As.ctxErr(ec, params, opt);\n res.end(JSON.stringify(response));\n }\n\n /**\n * 发送失败响应(兼容字符串;已注册错误码自动转为 { ec })\n */\n function sendFail(res: any, err: any, opt?: any) {\n const ErrorCode = $asai.$lib?.ErrorCode;\n ErrorCode?.loadErrorCodes?.($asai);\n const normalized = ErrorCode?.normalizeErrPayload?.(err);\n if (normalized?.ec) {\n return sendErr(res, normalized.ec, normalized.pm, opt);\n }\n const response = $asai.$lib.As.ctxFail(err);\n res.end(JSON.stringify(response));\n }\n\n /**\n * 统一日志输出(前缀 ➦ 标识来自 jsonmanage 模块)\n */\n function mnLog(...arg: any) {\n ($asai?.$log || console.log)(...arg);\n }\n return { hostDefault, getPathFromOpt, sendSuccess, sendFail, sendErr, mnLog };\n};\n","/**\r\n * 原生 fs 工具 — 替代 asaifs / fs-extra,供 app / work / host 共用\r\n */\r\nimport fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\n\r\n/** 确保父目录存在;文件不存在时创建空文件 */\r\nexport async function ensureFile(filePath: string): Promise<void> {\r\n const normalized = path.normalize(filePath);\r\n await fs.mkdir(path.dirname(normalized), { recursive: true });\r\n const fh = await fs.open(normalized, \"a\");\r\n await fh.close();\r\n}\r\n\r\nexport async function pathExists(filePath: string): Promise<boolean> {\r\n try {\r\n await fs.access(path.normalize(filePath));\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport async function readJson<T = unknown>(filePath: string): Promise<T> {\r\n const raw = await fs.readFile(path.normalize(filePath), \"utf8\");\r\n return JSON.parse(raw) as T;\r\n}\r\n\r\n/** 将相对路径约束在 baseDir 内,防止目录穿越 */\r\nexport function resolvePathUnderBase(baseDir: string, relPath: string): string {\r\n if (!relPath || typeof relPath !== \"string\") {\r\n throw new Error(\"Invalid path\");\r\n }\r\n if (relPath.includes(\"\\0\")) {\r\n throw new Error(\"Invalid path\");\r\n }\r\n const base = path.resolve(baseDir);\r\n const target = path.resolve(base, relPath.replace(/\\\\/g, \"/\"));\r\n const rel = path.relative(base, target);\r\n if (rel.startsWith(\"..\") || path.isAbsolute(rel)) {\r\n throw new Error(\"Path not allowed\");\r\n }\r\n return target;\r\n}\r\n\r\n/** 单层目录列举,返回与旧 asaifs.readDir 兼容的结构 */\r\nexport async function readLogDir(dir: string) {\r\n const resolved = path.resolve(dir);\r\n const stats = await fs.stat(resolved);\r\n if (!stats.isDirectory()) {\r\n throw new Error(\"Not a directory\");\r\n }\r\n const dirName = path.basename(resolved);\r\n const entries = await fs.readdir(resolved, { withFileTypes: true });\r\n const children = await Promise.all(\r\n entries.map(async (entry) => {\r\n const fullPath = path.join(resolved, entry.name);\r\n const st = await fs.stat(fullPath);\r\n const dot = entry.name.lastIndexOf(\".\");\r\n const type = entry.isDirectory()\r\n ? \"dir\"\r\n : dot > -1\r\n ? entry.name.substring(dot)\r\n : \"file\";\r\n return {\r\n name: entry.name,\r\n size: st.size,\r\n time: st.mtime.toISOString(),\r\n path: path.normalize(fullPath),\r\n type,\r\n created: st.birthtime.toISOString(),\r\n permissions: st.mode.toString(8).slice(-3),\r\n };\r\n }),\r\n );\r\n return {\r\n name: dirName,\r\n size: stats.size,\r\n time: stats.mtime.toISOString(),\r\n path: path.normalize(resolved),\r\n type: \"dir\",\r\n created: stats.birthtime.toISOString(),\r\n permissions: stats.mode.toString(8).slice(-3),\r\n children,\r\n };\r\n}\r\n\r\n/** 删除文件;ENOENT 时不抛错 */\r\nexport async function removeFile(filePath: string): Promise<void> {\r\n try {\r\n await fs.unlink(path.normalize(filePath));\r\n } catch (err: unknown) {\r\n if ((err as NodeJS.ErrnoException)?.code !== \"ENOENT\") throw err;\r\n }\r\n}\r\n\r\n/** 兼容旧 asaifs.remove */\r\nexport const remove = removeFile;\r\n\r\n/** 写入文本文件 */\r\nexport async function write(filePath: string, content: string): Promise<void> {\r\n const normalized = path.normalize(filePath);\r\n await fs.mkdir(path.dirname(normalized), { recursive: true });\r\n await fs.writeFile(normalized, content, \"utf8\");\r\n}\r\n\r\n/** 读取文本文件 */\r\nexport async function read(filePath: string): Promise<string> {\r\n return fs.readFile(path.normalize(filePath), \"utf8\");\r\n}\r\n\r\n/** 写入 JSON 文件 */\r\nexport async function writeJson(filePath: string, data: unknown): Promise<void> {\r\n await write(filePath, JSON.stringify(data, null, 2));\r\n}\r\n","/**\r\n * 运行时路径解析 — 不依赖 import.meta.url / __dirname\r\n *\r\n * 兼容两种部署:\r\n * 1. pkg 单文件 exe(process.pkg)— 嵌入资源 + exe 同目录外挂\r\n * 2. 开发 / node index.js — 入口脚本目录 + cwd\r\n */\r\nimport * as fs from 'fs';\r\nimport * as nodePath from 'path';\r\n\r\ntype PkgProcess = NodeJS.Process & {\r\n pkg?: { entrypoint?: string; defaultEntrypoint?: string };\r\n};\r\n\r\n/** 是否 pkg 打包运行 */\r\nexport function isPkgRuntime(): boolean {\r\n return typeof (process as PkgProcess).pkg !== 'undefined';\r\n}\r\n\r\n/**\r\n * pkg snapshot 根目录(嵌入的 webclient/index.html、assets 在此)\r\n * 见 https://yao-pkg.github.io/pkg/guide/snapshot-fs\r\n */\r\nexport function getPkgSnapshotDir(): string | undefined {\r\n if (!isPkgRuntime()) return undefined;\r\n const entry =\r\n (process as PkgProcess).pkg?.entrypoint ??\r\n (process as PkgProcess).pkg?.defaultEntrypoint;\r\n if (!entry) return undefined;\r\n return nodePath.resolve(nodePath.dirname(entry));\r\n}\r\n\r\n/** 进程入口脚本所在目录(tsx / node;pkg 下为 snapshot 内 index.js 目录) */\r\nexport function getEntryDir(): string {\r\n const snapshot = getPkgSnapshotDir();\r\n if (snapshot) return snapshot;\r\n\r\n const entry = process.argv[1];\r\n if (!entry) {\r\n return nodePath.dirname(process.execPath);\r\n }\r\n return nodePath.resolve(nodePath.dirname(entry));\r\n}\r\n\r\n/** exe / node 可执行文件所在目录(外挂 websys/webclient 常在此) */\r\nexport function getExecDir(): string {\r\n return nodePath.dirname(process.execPath);\r\n}\r\n\r\n/**\r\n * 静态/配置查找的全部基路径(去重)\r\n * 按优先级:cwd → exe 旁 → snapshot(pkg 嵌入资源,最后作兜底)\r\n */\r\nexport function getRuntimeBaseDirs(): string[] {\r\n const bases: string[] = [];\r\n const seen = new Set<string>();\r\n const add = (p: string | undefined) => {\r\n if (!p) return;\r\n const abs = nodePath.resolve(p);\r\n if (!seen.has(abs)) {\r\n seen.add(abs);\r\n bases.push(abs);\r\n }\r\n };\r\n\r\n add(process.cwd());\r\n add(getExecDir());\r\n\r\n if (isPkgRuntime()) {\r\n add(getPkgSnapshotDir());\r\n } else {\r\n const entryDir = getEntryDir();\r\n if (entryDir !== getExecDir()) {\r\n add(entryDir);\r\n }\r\n }\r\n\r\n return bases;\r\n}\r\n\r\n/** 首选 webserver 根:优先含 websys 的基路径,否则 exe 旁或入口目录 */\r\nexport function getPrimaryServerRoot(): string {\r\n for (const base of getRuntimeBaseDirs()) {\r\n try {\r\n if (fs.statSync(nodePath.join(base, 'websys')).isDirectory()) {\r\n return base;\r\n }\r\n } catch {\r\n /* try next */\r\n }\r\n }\r\n if (isPkgRuntime()) {\r\n return getExecDir();\r\n }\r\n return getEntryDir();\r\n}\r\n","import As from \"./common/As\";\r\nimport AsCode from \"./common/AsCode\";\r\nimport AsAES from \"./common/AsAES\";\r\nimport AsDb from \"./common/AsDb\";\r\nimport reqWork from \"./common/reqWork\";\r\nimport ErrorCode from \"./common/ErrorCode\";\r\nimport * as AsFs from \"./common/AsFs\";\r\nimport * as AsPath from \"./common/AsPath\";\r\nimport * as InterventionLog from \"./common/InterventionLog\";\r\nimport * as LogStore from \"./common/LogStore\";\r\nimport * as InterventionHooks from \"./common/intervention-hooks\";\r\n\r\nexport default {\r\n As,\r\n AsCode,\r\n AsAES,\r\n AsDb,\r\n AsFs,\r\n AsPath,\r\n reqWork,\r\n ErrorCode,\r\n InterventionLog,\r\n LogStore,\r\n InterventionHooks,\r\n};\r\n","import * as path from 'path';\r\nimport type Idb from './type';\r\n\r\n/** 统一对外接口(各驱动至少实现 sqlDb) */\r\nexport interface DbInstance {\r\n sqlDb(sql: Idb): Promise<unknown>;\r\n}\r\n\r\n/** 支持回调查询的驱动接口 */\r\nexport interface QueryableDb extends DbInstance {\r\n query(sql: Idb, callback: (err: string | null, result: unknown) => void): void;\r\n}\r\n\r\n/** 将 query 回调风格封装为 Promise,并统一空结果处理 */\r\nexport function promisifySqlDb(\r\n query: QueryableDb['query'],\r\n sql: Idb\r\n): Promise<unknown> {\r\n return new Promise((resolve, reject) => {\r\n query(sql, (err, result) => {\r\n if (err) {\r\n reject(err);\r\n return;\r\n }\r\n if (!result || (Array.isArray(result) && result.length === 0)) {\r\n resolve('');\r\n return;\r\n }\r\n resolve(result);\r\n });\r\n });\r\n}\r\n\r\n/** 将 Idb.field 规范为字符串数组 */\r\nexport function toFieldArray(field: Idb['field']): string[] {\r\n if (!field) return [];\r\n return typeof field === 'string' ? field.split(',') : field;\r\n}\r\n\r\n/** 将 Idb.where 规范为 Excel 等值条件 [字段, 值][] */\r\nexport function toWherePairs(where: Idb['where']): [string, unknown][] {\r\n if (!where || !Array.isArray(where)) return [];\r\n const pairs: [string, unknown][] = [];\r\n for (const item of where) {\r\n if (typeof item === 'string') continue;\r\n if (Array.isArray(item) && item.length >= 3) {\r\n pairs.push([item[0], item[2]]);\r\n }\r\n }\r\n return pairs;\r\n}\r\n\r\n/** 将 Idb.set 规范为键值对象 */\r\nexport function toSetObject(set: Idb['set']): Record<string, unknown> {\r\n if (!set) return {};\r\n if (typeof set === 'string') return {};\r\n const obj: Record<string, unknown> = {};\r\n for (const item of set) {\r\n if (typeof item === 'string') continue;\r\n if (Array.isArray(item)) {\r\n if (item.length >= 3 && typeof item[1] === 'string') {\r\n obj[item[0]] = item[2];\r\n } else if (item.length >= 2) {\r\n obj[item[0]] = item[1];\r\n }\r\n }\r\n }\r\n return obj;\r\n}\r\n\r\n/** 将 Idb.value 与 field 组合为插入行对象数组 */\r\nexport function toInsertRows(sql: Idb): Record<string, unknown>[] {\r\n const fields = toFieldArray(sql.field);\r\n const values = sql.value;\r\n if (!fields.length || !Array.isArray(values)) return [];\r\n return (values as unknown[][]).map((row) => {\r\n const rowObj: Record<string, unknown> = {};\r\n fields.forEach((field, index) => {\r\n rowObj[field] = row[index];\r\n });\r\n return rowObj;\r\n });\r\n}\r\n\r\n/**\r\n * 判断目标路径是否在基准目录内(跨平台:Win/Linux/macOS)\r\n * 使用 path.resolve + path.relative,兼容正反斜杠与不同盘符\r\n */\r\nexport function isPathInside(baseDir: string, targetPath: string): boolean {\r\n const base = path.resolve(baseDir);\r\n const target = path.resolve(targetPath);\r\n const relative = path.relative(base, target);\r\n if (!relative) return true;\r\n return !relative.startsWith('..') && !path.isAbsolute(relative);\r\n}\r\n\r\n/**\r\n * 拼接 table 相对路径(始终使用 /,与 API 路由约定一致)\r\n * path.resolve 在 Win/Linux/macOS 上均支持正斜杠\r\n */\r\nexport function joinTablePath(table: string, ...segments: string[]): string {\r\n const parts = [table.replace(/\\\\/g, '/'), ...segments.map((s) => String(s).replace(/\\\\/g, '/'))];\r\n return parts.filter(Boolean).join('/');\r\n}\r\n\r\n/** 判断 field 定义中是否已包含 id 列(兼容字符串 includes 语义) */\r\nexport function fieldHasId(field: Idb['field']): boolean {\r\n if (!field) return false;\r\n if (typeof field === 'string') return field.includes('id');\r\n return field.includes('id');\r\n}\r\n\r\n/** 判断错误是否为「表不存在」类错误 */\r\nexport function isTableMissingError(err: { code?: string; message?: string } | null | undefined): boolean {\r\n if (!err) return false;\r\n const msg = err.message || '';\r\n if (err.code === 'ER_NO_SUCH_TABLE' || err.code === 'SQLITE_ERROR') {\r\n return msg.includes('no such table') || msg.includes(\"doesn't exist\");\r\n }\r\n return msg.includes('no such table') || msg.includes(\"doesn't exist\");\r\n}\r\n","import type Idb from './type';\r\nimport { fieldHasId, toFieldArray } from './common';\r\n\r\ntype JoinType = 'where' | 'order' | 'value' | 'set' | 'field';\r\n\r\n/** 为表名加引号,避免 SQLite 保留字(如 order)导致语法错误 */\r\nfunction quoteTable(table: string): string {\r\n const safe = String(table).replace(/\"/g, '\"\"');\r\n return `\"${safe}\"`;\r\n}\r\n\r\n/** 拼接 WHERE 子句(支持 or/and 链式条件) */\r\nfunction buildWhereClause(where: NonNullable<Idb['where']>): string {\r\n if (!Array.isArray(where) || !where.length) return '';\r\n\r\n const parts: string[] = [];\r\n let connector = 'and';\r\n\r\n for (let i = 0; i < where.length; i++) {\r\n const item = where[i];\r\n if (item === 'or' || item === 'and') {\r\n connector = item;\r\n continue;\r\n }\r\n if (!Array.isArray(item)) continue;\r\n const [field, op, val] = item as [string, string, unknown];\r\n if (!parts.length) {\r\n parts.push(`${field} ${op} ${val}`);\r\n } else {\r\n parts.push(`${connector} ${field} ${op} ${val}`);\r\n }\r\n }\r\n\r\n return parts.length ? ` where ${parts.join(' ')}` : '';\r\n}\r\n\r\n/** 拼接 ORDER BY 子句 */\r\nfunction buildOrderClause(order: NonNullable<Idb['order']>): string {\r\n if (!Array.isArray(order) || !order.length) return '';\r\n const items = order.map((el, i) => {\r\n const prefix = i > 0 ? ',' : '';\r\n return `${prefix} ${el[0]} ${el[1]}`;\r\n });\r\n return ` order by${items.join('')}`;\r\n}\r\n\r\n/** 将单个 INSERT 单元格格式化为 SQL 字面量(兼容 qStr 预加引号与 qNum 裸数字) */\r\nfunction formatInsertCell(value: unknown): string {\r\n if (value == null) return \"''\";\r\n const s = String(value);\r\n if (/^-?\\d+(\\.\\d+)?$/.test(s)) return s;\r\n if (s.startsWith(\"'\") && s.endsWith(\"'\")) return s;\r\n return `'${s.replace(/'/g, \"''\")}'`;\r\n}\r\n\r\n/** 拼接 INSERT VALUES 子句,如 values ('a','1'),('b','2') */\r\nfunction buildValueClause(values: NonNullable<Idb['value']>): string {\r\n if (!Array.isArray(values) || !values.length) return '';\r\n const rows = (values as unknown[][]).map((row) => `(${row.map(formatInsertCell).join(',')})`);\r\n return ` values ${rows.join(',')}`;\r\n}\r\n\r\n/** 拼接 UPDATE SET 子句 */\r\nfunction buildSetClause(sets: NonNullable<Idb['set']>): string {\r\n if (!Array.isArray(sets) || !sets.length) return '';\r\n\r\n const parts = sets.map((item, i) => {\r\n const prefix = i > 0 ? ',' : '';\r\n const el = item as [string, unknown, unknown?];\r\n const [field, opOrVal, val] = el;\r\n\r\n if (typeof val === 'number' && opOrVal) {\r\n return `${prefix}${field}=${field}${opOrVal}${val}`;\r\n }\r\n if (typeof val === 'string' && opOrVal) {\r\n if (opOrVal === 'CONCAT') {\r\n return `${prefix}${field}=${opOrVal}(${field},'${val}')`;\r\n }\r\n return `${prefix}${field}=${field}${opOrVal}'${val}'`;\r\n }\r\n if (typeof opOrVal === 'number') {\r\n return `${prefix}${field}=${opOrVal}`;\r\n }\r\n return `${prefix}${field}='${opOrVal}'`;\r\n });\r\n\r\n return ` set ${parts.join('')}`;\r\n}\r\n\r\n/** 拼接字段列表 (a,b,c) */\r\nfunction buildFieldClause(fields: NonNullable<Idb['field']>): string {\r\n const list = toFieldArray(fields);\r\n return list.length ? ` (${list.join(',')})` : '';\r\n}\r\n\r\nexport default {\r\n /**\r\n * 将 Idb 中的指定片段转为 SQL 字符串片段\r\n */\r\n joinSql(sql: Idb, type: JoinType): string {\r\n const val = sql[type];\r\n if (Array.isArray(val)) {\r\n if (!val.length) return '';\r\n switch (type) {\r\n case 'where':\r\n return buildWhereClause(val as NonNullable<Idb['where']>);\r\n case 'order':\r\n return buildOrderClause(val as NonNullable<Idb['order']>);\r\n case 'value':\r\n return buildValueClause(val as NonNullable<Idb['value']>);\r\n case 'set':\r\n return buildSetClause(val as NonNullable<Idb['set']>);\r\n case 'field':\r\n return buildFieldClause(val as NonNullable<Idb['field']>);\r\n }\r\n }\r\n if (!val) return '';\r\n\r\n const raw = String(val);\r\n switch (type) {\r\n case 'where':\r\n return ` where ${raw}`;\r\n case 'order':\r\n return ` order by ${raw}`;\r\n case 'value':\r\n return ` values (${raw})`;\r\n case 'set':\r\n return ` set ${raw}`;\r\n case 'field':\r\n return ` (${raw})`;\r\n default:\r\n return '';\r\n }\r\n },\r\n\r\n /**\r\n * 将完整 Idb 对象转换为可执行 SQL 字符串\r\n * 注意:值为字符串拼接,调用方需确保输入可信或自行转义\r\n */\r\n makeSql(sql: Idb): string {\r\n const table = quoteTable(sql.table);\r\n const op = sql.type;\r\n switch (op) {\r\n case 'insert':\r\n return `insert into ${table}${this.joinSql(sql, 'field')}${this.joinSql(sql, 'value')}`;\r\n case 'delete':\r\n return `delete from ${table}${this.joinSql(sql, 'where')}`;\r\n case 'update':\r\n return `update ${table}${this.joinSql(sql, 'set')}${this.joinSql(sql, 'where')}`;\r\n case 'select': {\r\n const fields = sql.field ? ` ${sql.field}` : ' *';\r\n const limit = sql.limit ? ` limit ${sql.limit}` : '';\r\n return `select${fields} from ${table}${this.joinSql(sql, 'where')}${this.joinSql(sql, 'order')}${limit}`;\r\n }\r\n default:\r\n return op;\r\n }\r\n },\r\n\r\n /**\r\n * 生成建表 SQL(自动补 id 主键与 asdate 时间戳列)\r\n */\r\n createSql(sql: Idb, dialect: 'mysql' | 'sqlite' | string = 'mysql'): string {\r\n const autoId = dialect === 'sqlite' ? 'AUTOINCREMENT' : 'AUTO_INCREMENT';\r\n const fields = toFieldArray(sql.field);\r\n const columns: string[] = [];\r\n\r\n if (!fieldHasId(sql.field)) {\r\n columns.push(`id INTEGER PRIMARY KEY ${autoId}`);\r\n }\r\n fields.forEach((name) => columns.push(`${name} text`));\r\n const asdateCol =\r\n dialect === 'sqlite' ? 'asdate text DEFAULT CURRENT_TIMESTAMP' : 'asdate text default(CURRENT_TIMESTAMP)';\r\n columns.push(asdateCol);\r\n\r\n return `create table if not exists ${quoteTable(sql.table)} (${columns.join(',')})`;\r\n },\r\n};\r\n","import type Idb from '../type';\r\nimport Sql from '../Sql';\r\nimport { isTableMissingError, promisifySqlDb } from '../common';\r\nimport mysql from 'mysql';\r\n\r\ninterface MySQLConfig {\r\n host?: string;\r\n user?: string;\r\n password?: string;\r\n database?: string;\r\n create?: boolean | number;\r\n [key: string]: unknown;\r\n}\r\n\r\nclass DbMySQL {\r\n private readonly config: MySQLConfig;\r\n private pool: ReturnType<typeof mysql.createPool>;\r\n\r\n constructor(config: MySQLConfig) {\r\n this.config = config;\r\n this.pool = mysql.createPool(config);\r\n }\r\n\r\n private getErr(sql: Idb, err: { message?: string } | null | undefined): string | null {\r\n if (this.config.create && isTableMissingError(err as { code?: string; message?: string })) {\r\n this.createTable(sql);\r\n }\r\n return err?.message || null;\r\n }\r\n\r\n private getResult(rows: unknown): unknown {\r\n return rows ?? null;\r\n }\r\n\r\n query(sql: Idb, callback: (err: string | null, result: unknown) => void): void {\r\n this.pool.getConnection((error, connection) => {\r\n if (error) {\r\n callback(this.getErr(sql, error), this.getResult(null));\r\n return;\r\n }\r\n\r\n connection.query(Sql.makeSql(sql), (err, rows) => {\r\n try {\r\n callback(this.getErr(sql, err), this.getResult(rows));\r\n } finally {\r\n connection.release();\r\n }\r\n });\r\n });\r\n }\r\n\r\n sqlDb(sql: Idb): Promise<unknown> {\r\n return promisifySqlDb(this.query.bind(this), sql);\r\n }\r\n\r\n /** 关闭连接池,释放所有连接 */\r\n close(callback?: (err: Error | null) => void): void {\r\n this.pool.end(callback);\r\n }\r\n\r\n /** 表不存在时自动创建数据库与表(需 config.create 为 true) */\r\n private createTable(sql: Idb): void {\r\n if (!this.config.create) return;\r\n\r\n const conn = mysql.createConnection({\r\n host: this.config.host,\r\n user: this.config.user,\r\n password: this.config.password,\r\n });\r\n\r\n conn.connect((err) => {\r\n if (err) {\r\n conn.end();\r\n return;\r\n }\r\n\r\n conn.query(`CREATE DATABASE IF NOT EXISTS ${this.config.database};`, (dbErr) => {\r\n if (dbErr) {\r\n conn.end();\r\n return;\r\n }\r\n\r\n this.pool = mysql.createPool(this.config);\r\n this.pool.getConnection((poolErr, connection) => {\r\n if (poolErr || !connection) {\r\n conn.end();\r\n return;\r\n }\r\n\r\n connection.query(Sql.createSql(sql, 'mysql'), () => {\r\n connection.release();\r\n conn.end();\r\n });\r\n });\r\n });\r\n });\r\n }\r\n}\r\n\r\nexport default DbMySQL;\r\n","import type Idb from '../type';\r\nimport Sql from '../Sql';\r\nimport { isTableMissingError, promisifySqlDb } from '../common';\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport sqlite3Import from 'sqlite3';\r\n\r\n/** CJS/ESM 互操作:sqlite3 的 verbose() 在 default 导出上 */\r\nconst sqlite3: typeof sqlite3Import =\r\n (sqlite3Import as unknown as { default?: typeof sqlite3Import }).default ?? sqlite3Import;\r\n\r\n/** SQLite 单文件锁:默认单连接 + 串行队列;多连接池仅 opt.usePool=true 时启用且上限为 1 */\r\nconst DEFAULT_BUSY_TIMEOUT_MS = 10000;\r\nconst DEFAULT_ACQUIRE_TIMEOUT_MS = 15000;\r\n\r\n/**\r\n * 打开连接后设置 WAL / busy_timeout,避免并发 CRUD 时 SQLITE_BUSY 导致连接占满与 acquire 超时\r\n */\r\nfunction configureSqliteConnection(db: any, busyTimeoutMs: number = DEFAULT_BUSY_TIMEOUT_MS): Promise<void> {\r\n const busyMs = Math.max(0, Math.floor(busyTimeoutMs));\r\n return new Promise((resolve, reject) => {\r\n db.serialize(() => {\r\n db.run('PRAGMA journal_mode = WAL');\r\n db.run(`PRAGMA busy_timeout = ${busyMs}`);\r\n db.run('PRAGMA synchronous = NORMAL', (err: Error | null) => {\r\n if (err) reject(err);\r\n else resolve();\r\n });\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * 连接池配置接口\r\n */\r\ninterface PoolConfig {\r\n database: string; // 数据库文件路径\r\n poolMin?: number; // 最小连接数(默认 1)\r\n poolMax?: number; // 最大连接数(默认 1,SQLite 同文件不宜多连接)\r\n idleTimeout?: number; // 空闲连接超时回收时间(ms,默认 30000)\r\n acquireTimeout?: number; // 获取连接超时时间(ms,默认 15000)\r\n busyTimeout?: number; // SQLITE_BUSY 等待时间(ms,默认 10000)\r\n enableCreateTable?: boolean; // 是否允许自动建表\r\n $asai?: any; // 外部日志对象\r\n}\r\n\r\n/**\r\n * 数据库连接包装器(异步创建)\r\n */\r\nclass PooledConnection {\r\n public db: any; // sqlite3.Database 实例\r\n public config: PoolConfig;\r\n public lastUsed: number; // 最后使用时间戳\r\n public inUse: boolean; // 是否正在被使用\r\n private isValid: boolean; // 连接是否有效\r\n\r\n private constructor(db: any, config: PoolConfig) {\r\n this.db = db;\r\n this.config = config;\r\n this.lastUsed = Date.now();\r\n this.inUse = false;\r\n this.isValid = true;\r\n }\r\n\r\n /**\r\n * 异步创建连接,确保目录存在并打开数据库\r\n */\r\n static async create(config: PoolConfig): Promise<PooledConnection> {\r\n function dbLog(...args: any[]) {\r\n (config?.$asai?.$log || console.log)('SQLITE', ...args);\r\n }\r\n\r\n const absolutePath = path.resolve(config.database);\r\n const dir = path.dirname(absolutePath);\r\n if (!fs.existsSync(dir)) {\r\n fs.mkdirSync(dir, { recursive: true });\r\n dbLog('MKDIR', dir);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const db = new sqlite3.Database(absolutePath, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, async (err: any) => {\r\n if (err) {\r\n dbLog('open failed', '[ERROR] Failed to open database:', absolutePath, err.message);\r\n reject(err);\r\n return;\r\n }\r\n try {\r\n await configureSqliteConnection(db, config.busyTimeout ?? DEFAULT_BUSY_TIMEOUT_MS);\r\n dbLog('OPEN', absolutePath);\r\n resolve(new PooledConnection(db, config));\r\n } catch (pragmaErr: any) {\r\n db.close(() => {});\r\n reject(pragmaErr);\r\n }\r\n });\r\n });\r\n }\r\n\r\n /** 测试连接是否有效(执行 SELECT 1) */\r\n async test(): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n if (!this.isValid) return resolve(false);\r\n this.db.get('SELECT 1', (err: any) => {\r\n this.isValid = !err;\r\n resolve(this.isValid);\r\n });\r\n });\r\n }\r\n\r\n /** 关闭连接 */\r\n async close(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n this.db.close((err: any) => {\r\n if (err) reject(err);\r\n else resolve();\r\n });\r\n });\r\n }\r\n\r\n /** 标记连接为无效 */\r\n invalidate() {\r\n this.isValid = false;\r\n }\r\n}\r\n\r\n/**\r\n * SQLite 连接池\r\n * - 管理多个数据库连接,支持连接复用、空闲回收、等待队列\r\n */\r\nexport class SQLitePool {\r\n private config: Required<PoolConfig>;\r\n private pool: PooledConnection[] = [];\r\n private waitingQueue: Array<{\r\n resolve: (conn: PooledConnection) => void;\r\n reject: (err: Error) => void;\r\n timer: NodeJS.Timeout;\r\n }> = [];\r\n private idleCheckerTimer: NodeJS.Timeout | null = null;\r\n private isDestroyed = false;\r\n private initPromise: Promise<void>; // 初始化完成 Promise\r\n\r\n constructor(config: PoolConfig) {\r\n this.config = {\r\n database: config.database,\r\n poolMin: config.poolMin ?? 1,\r\n poolMax: config.poolMax ?? 1,\r\n idleTimeout: config.idleTimeout ?? 30000,\r\n acquireTimeout: config.acquireTimeout ?? DEFAULT_ACQUIRE_TIMEOUT_MS,\r\n busyTimeout: config.busyTimeout ?? DEFAULT_BUSY_TIMEOUT_MS,\r\n enableCreateTable: config.enableCreateTable ?? true,\r\n $asai: config.$asai ?? null,\r\n };\r\n\r\n this.initPromise = this.initializePool();\r\n this.startIdleChecker();\r\n }\r\n\r\n /** 统一日志输出(前缀 ♣ 标识来自 SQLite 连接池模块) */\r\n private dbLog(...args: any[]) {\r\n (this.config?.$asai?.$log || console.log)('sqlite', ...args);\r\n }\r\n\r\n /** 初始化连接池,创建最小连接数 */\r\n private async initializePool() {\r\n const promises: Promise<void>[] = [];\r\n for (let i = 0; i < this.config.poolMin; i++) {\r\n promises.push(this.createConnection());\r\n }\r\n const results = await Promise.allSettled(promises);\r\n const successCount = results.filter((r) => r.status === 'fulfilled').length;\r\n if (successCount === 0) {\r\n this.dbLog('Initialization failed', '[POOL] Initialization failed: no connections created');\r\n } else {\r\n this.dbLog('Initialized', '[POOL] Initialized, size:', this.pool.length);\r\n }\r\n }\r\n\r\n /** 创建一个新连接并加入池中 */\r\n private async createConnection(): Promise<void> {\r\n if (this.pool.length >= this.config.poolMax) return;\r\n try {\r\n const conn = await PooledConnection.create(this.config);\r\n const isValid = await conn.test();\r\n if (isValid) {\r\n this.pool.push(conn);\r\n } else {\r\n await conn.close().catch(() => {});\r\n throw new Error('Connection test failed');\r\n }\r\n } catch (err: any) {\r\n this.dbLog('Database create failed', '[CONN] Failed to create connection:', err.message);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * 获取一个可用连接\r\n * - 优先返回空闲连接\r\n * - 若连接数未达上限则创建新连接\r\n * - 否则进入等待队列\r\n */\r\n async acquire(): Promise<PooledConnection> {\r\n await this.initPromise;\r\n\r\n if (this.isDestroyed) {\r\n throw new Error('Pool has been destroyed');\r\n }\r\n\r\n const now = Date.now();\r\n const staleCheckMs = Math.min(this.config.idleTimeout, 5000);\r\n\r\n // 1. 寻找空闲连接;仅对长时间空闲的连接做有效性检测,减少 SELECT 1 开销\r\n for (const conn of this.pool) {\r\n if (!conn.inUse) {\r\n if (now - conn.lastUsed > staleCheckMs) {\r\n const isValid = await conn.test();\r\n if (!isValid) {\r\n this.removeConnection(conn);\r\n continue;\r\n }\r\n }\r\n conn.inUse = true;\r\n conn.lastUsed = now;\r\n return conn;\r\n }\r\n }\r\n\r\n // 2. 未达最大连接数则创建新连接\r\n if (this.pool.length < this.config.poolMax) {\r\n try {\r\n const conn = await PooledConnection.create(this.config);\r\n const isValid = await conn.test();\r\n if (isValid) {\r\n conn.inUse = true;\r\n conn.lastUsed = Date.now();\r\n this.pool.push(conn);\r\n return conn;\r\n } else {\r\n await conn.close().catch(() => {});\r\n }\r\n } catch (e: any) {\r\n this.dbLog('create failed', '[ACQUIRE] Failed to create new connection, waiting:', e.message);\r\n }\r\n }\r\n\r\n // 3. 进入等待队列\r\n return new Promise((resolve, reject) => {\r\n const timer = setTimeout(() => {\r\n const idx = this.waitingQueue.findIndex((item) => item.timer === timer);\r\n if (idx !== -1) {\r\n this.waitingQueue.splice(idx, 1);\r\n }\r\n reject(new Error(`Acquire timeout (${this.config.acquireTimeout}ms)`));\r\n }, this.config.acquireTimeout);\r\n\r\n this.waitingQueue.push({ resolve, reject, timer });\r\n });\r\n }\r\n\r\n /** 释放连接回池中 */\r\n release(conn: PooledConnection) {\r\n if (!conn) return;\r\n conn.inUse = false;\r\n conn.lastUsed = Date.now();\r\n\r\n if (this.waitingQueue.length > 0) {\r\n const next = this.waitingQueue.shift()!;\r\n clearTimeout(next.timer);\r\n conn.inUse = true;\r\n conn.lastUsed = Date.now();\r\n next.resolve(conn);\r\n }\r\n }\r\n\r\n /** 从池中移除并关闭指定连接 */\r\n private removeConnection(conn: PooledConnection) {\r\n const index = this.pool.indexOf(conn);\r\n if (index !== -1) {\r\n this.pool.splice(index, 1);\r\n conn.close().catch(() => {});\r\n }\r\n }\r\n\r\n /** 启动空闲连接回收定时器(每 60 秒检查一次) */\r\n private startIdleChecker() {\r\n this.idleCheckerTimer = setInterval(async () => {\r\n if (this.isDestroyed) return;\r\n\r\n const now = Date.now();\r\n const toRemove: PooledConnection[] = [];\r\n\r\n for (const conn of this.pool) {\r\n if (!conn.inUse && now - conn.lastUsed > this.config.idleTimeout && this.pool.length > this.config.poolMin) {\r\n toRemove.push(conn);\r\n }\r\n }\r\n\r\n for (const conn of toRemove) {\r\n this.removeConnection(conn);\r\n }\r\n\r\n if (toRemove.length > 0) {\r\n this.dbLog('Reclaimed', '[IDLE] Reclaimed', toRemove.length, 'idle connections, current pool size:', this.pool.length);\r\n }\r\n }, 60000);\r\n }\r\n\r\n /** 获取连接池当前状态 */\r\n getStatus() {\r\n const inUse = this.pool.filter((c) => c.inUse).length;\r\n return {\r\n total: this.pool.length,\r\n inUse,\r\n idle: this.pool.length - inUse,\r\n waiting: this.waitingQueue.length,\r\n min: this.config.poolMin,\r\n max: this.config.poolMax,\r\n };\r\n }\r\n\r\n /** 销毁连接池,释放所有资源 */\r\n async destroy() {\r\n if (this.isDestroyed) return;\r\n this.isDestroyed = true;\r\n\r\n if (this.idleCheckerTimer) {\r\n clearInterval(this.idleCheckerTimer);\r\n this.idleCheckerTimer = null;\r\n }\r\n\r\n for (const waiter of this.waitingQueue) {\r\n clearTimeout(waiter.timer);\r\n waiter.reject(new Error('Pool has been closed'));\r\n }\r\n this.waitingQueue = [];\r\n\r\n await Promise.allSettled(this.pool.map((conn) => conn.close()));\r\n this.pool = [];\r\n this.dbLog('Destroyed', '[POOL] Destroyed');\r\n }\r\n}\r\n\r\n/**\r\n * 数据库操作主类(兼容原 Index.ts 接口)\r\n * - 支持连接池模式与单连接模式\r\n * - 提供与文件数据库相同的 query / sqlDb 接口\r\n */\r\nclass DbSQLite3 {\r\n private config: any;\r\n private pool: SQLitePool | null = null;\r\n private singleDb: any = null;\r\n private singleDbReady: Promise<void> | null = null;\r\n /** 串行化同库 CRUD,避免 node-sqlite3 回调并发导致锁等待与连接泄漏 */\r\n private opChain: Promise<void> = Promise.resolve();\r\n\r\n constructor(config: any) {\r\n this.config = config;\r\n const verbose = sqlite3.verbose();\r\n\r\n if (config.usePool === true) {\r\n this.pool = new SQLitePool({\r\n database: config.database,\r\n poolMin: config.poolMin ?? 1,\r\n poolMax: config.poolMax ?? 1,\r\n idleTimeout: config.idleTimeout,\r\n acquireTimeout: config.acquireTimeout ?? DEFAULT_ACQUIRE_TIMEOUT_MS,\r\n busyTimeout: config.busyTimeout ?? DEFAULT_BUSY_TIMEOUT_MS,\r\n enableCreateTable: config.create,\r\n $asai: config.$asai,\r\n });\r\n } else {\r\n // 默认单连接(SQLite 推荐)\r\n this.singleDbReady = this.initSingleConnection(config.database, verbose);\r\n }\r\n }\r\n\r\n private runSerialized<T>(task: () => Promise<T>): Promise<T> {\r\n const run = this.opChain.then(() => task());\r\n this.opChain = run.then(\r\n () => undefined,\r\n () => undefined,\r\n );\r\n return run;\r\n }\r\n\r\n private dbLog(...args: any[]) {\r\n (this.config?.$asai?.$log || console.log)('sqlite', ...args);\r\n }\r\n\r\n private async initSingleConnection(databasePath: string, verbose: any): Promise<void> {\r\n const absolutePath = path.resolve(databasePath);\r\n const dir = path.dirname(absolutePath);\r\n if (!fs.existsSync(dir)) {\r\n fs.mkdirSync(dir, { recursive: true });\r\n this.dbLog('mkdir', '[MKDIR]', dir);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n this.singleDb = new verbose.Database(absolutePath, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, async (err: any) => {\r\n if (err) {\r\n this.dbLog('open failed', '[ERROR] Failed to open single connection:', absolutePath, err.message);\r\n reject(err);\r\n return;\r\n }\r\n try {\r\n await configureSqliteConnection(this.singleDb, this.config.busyTimeout ?? DEFAULT_BUSY_TIMEOUT_MS);\r\n this.dbLog('open', '[OPEN] Single connection:', absolutePath);\r\n resolve();\r\n } catch (pragmaErr) {\r\n this.singleDb.close(() => {});\r\n reject(pragmaErr);\r\n }\r\n });\r\n });\r\n }\r\n\r\n private getErr(_sql: Idb, err: { message?: string; code?: string } | null | undefined): string | null {\r\n return err?.message || null;\r\n }\r\n\r\n private getResult(rows: any): any {\r\n return rows ?? 'OK';\r\n }\r\n\r\n /**\r\n * 执行 SQL 查询(回调风格)\r\n */\r\n query(sql: Idb, callback: (err: string | null, result: any) => void) {\r\n const sqlStr = Sql.makeSql(sql);\r\n\r\n const executeQuery = (db: any, release?: () => void) => {\r\n const finish = (err: any, rows: any) => {\r\n release?.();\r\n callback(this.getErr(sql, err), this.getResult(rows));\r\n };\r\n\r\n try {\r\n if (sql.type === 'select') {\r\n db.all(sqlStr, finish);\r\n } else {\r\n db.run(sqlStr, (err: any) => {\r\n finish(err, 'OK');\r\n });\r\n }\r\n } catch (e) {\r\n release?.();\r\n callback(this.getErr(sql, e as { message?: string; code?: string }), this.getResult('sql error'));\r\n }\r\n };\r\n\r\n if (this.pool) {\r\n this.pool\r\n .acquire()\r\n .then((conn) => {\r\n executeQuery(conn.db, () => this.pool!.release(conn));\r\n })\r\n .catch((err) => {\r\n callback(this.getErr(sql, err), this.getResult('pool error'));\r\n });\r\n } else {\r\n (this.singleDbReady || Promise.resolve())\r\n .then(() => {\r\n executeQuery(this.singleDb);\r\n })\r\n .catch((err) => {\r\n callback(this.getErr(sql, err), this.getResult('connection error'));\r\n });\r\n }\r\n }\r\n\r\n /** 执行 SQL 操作(Promise 风格,串行 + 缺表时自动建表并重试一次) */\r\n sqlDb(sql: Idb): Promise<unknown> {\r\n return this.runSerialized(() => this.executeSqlDb(sql));\r\n }\r\n\r\n private async executeSqlDb(sql: Idb): Promise<unknown> {\r\n try {\r\n return await promisifySqlDb(this.query.bind(this), sql);\r\n } catch (err: any) {\r\n const errObj = { message: String(err?.message || err || '') };\r\n if (this.config.create && sql.type === 'insert' && isTableMissingError(errObj)) {\r\n await this.createTable(sql);\r\n return promisifySqlDb(this.query.bind(this), sql);\r\n }\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * 自动建表(当表不存在时触发)\r\n */\r\n private async createTable(sql: Idb): Promise<void> {\r\n const createSql = Sql.createSql(sql, 'sqlite');\r\n if (!createSql) return;\r\n\r\n if (this.pool) {\r\n let conn: PooledConnection | null = null;\r\n try {\r\n conn = await this.pool.acquire();\r\n await new Promise<void>((resolve, reject) => {\r\n conn!.db.run(createSql, (err: any) => {\r\n if (err) reject(err);\r\n else resolve();\r\n });\r\n });\r\n this.dbLog('Created', '[TABLE] Created:', createSql);\r\n } catch (e) {\r\n this.dbLog('Creation failed', '[TABLE] Creation failed:', e);\r\n } finally {\r\n if (conn) this.pool.release(conn);\r\n }\r\n } else {\r\n await this.singleDbReady;\r\n await new Promise<void>((resolve, reject) => {\r\n this.singleDb.run(createSql, (err: any) => {\r\n if (err) reject(err);\r\n else resolve();\r\n });\r\n });\r\n }\r\n }\r\n\r\n /** 获取连接池状态(仅连接池模式有效) */\r\n getPoolStatus() {\r\n if (this.pool) {\r\n return this.pool.getStatus();\r\n }\r\n return { mode: 'single-connection' };\r\n }\r\n\r\n /** 关闭所有连接 */\r\n async close() {\r\n if (this.pool) {\r\n await this.pool.destroy();\r\n } else if (this.singleDb) {\r\n await new Promise<void>((resolve, reject) => {\r\n this.singleDb.close((err: any) => {\r\n if (err) reject(err);\r\n else resolve();\r\n });\r\n });\r\n }\r\n }\r\n}\r\n\r\nexport default DbSQLite3;\r\n","import type Idb from '../type';\r\nimport { isPathInside, joinTablePath } from '../common';\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\ninterface DbFileConfig {\r\n dir: string; // 数据存储根目录(相对于进程工作目录)\r\n ext?: string; // 文件扩展名,如 \".json\",\".*\" 表示无扩展名\r\n del?: number; // 非 0 表示启用软删除(重命名为 .delete.ext)\r\n create?: boolean; // 是否自动创建不存在的目录\r\n $asai?: any; // 外部注入的日志对象,用于自定义日志输出\r\n}\r\n\r\nclass DbFile {\r\n private readonly config: DbFileConfig;\r\n private readonly fileExt: string;\r\n private readonly fileDel: boolean;\r\n private readonly createDir: boolean;\r\n private readonly baseDirAbs: string;\r\n\r\n constructor(config: DbFileConfig) {\r\n this.config = config;\r\n this.fileExt = config.ext === '.*' ? '' : config.ext || '';\r\n this.fileDel = (config.del || 0) !== 0;\r\n this.createDir = config.create || false;\r\n this.baseDirAbs = path.resolve(process.cwd(), config.dir);\r\n }\r\n\r\n private dbLog(...args: any[]) {\r\n (this.config?.$asai?.$log || console.log)('FILE', ...args);\r\n }\r\n\r\n checkFile(file: string): boolean {\r\n return fs.existsSync(this.getAbsPath(file, false));\r\n }\r\n\r\n /** 解析相对路径并限制在数据根目录内,防止路径穿越(跨平台) */\r\n private resolvePath(relPath: string): string {\r\n if (!relPath) {\r\n return this.baseDirAbs;\r\n }\r\n const abs = path.isAbsolute(relPath)\r\n ? path.normalize(relPath)\r\n : path.resolve(this.baseDirAbs, relPath);\r\n if (!isPathInside(this.baseDirAbs, abs)) {\r\n return this.baseDirAbs;\r\n }\r\n return abs;\r\n }\r\n\r\n /** 将 table 与文件名片段拼为平台无关相对路径 */\r\n private tableFilePath(table: string, ...segments: string[]): string {\r\n return joinTablePath(table, ...segments);\r\n }\r\n\r\n private normalizeRelPath(relPath: string): string {\r\n if (!relPath) {\r\n return '';\r\n }\r\n return path.isAbsolute(relPath) ? path.relative(this.baseDirAbs, relPath) : relPath;\r\n }\r\n\r\n private ensureDir(relPath: string): string {\r\n const relative = this.normalizeRelPath(relPath);\r\n const dirPath = path.dirname(relative);\r\n const absDir = this.resolvePath(dirPath === '.' ? '' : dirPath);\r\n if (this.createDir && !fs.existsSync(absDir)) {\r\n this.dbLog('mkdir', '[MKDIR]', absDir);\r\n fs.mkdirSync(absDir, { recursive: true });\r\n }\r\n return absDir;\r\n }\r\n\r\n private getAbsPath(file: string, autoCreateDir: boolean = true): string {\r\n let rel = file;\r\n if (this.fileExt && !rel.endsWith(this.fileExt)) {\r\n rel += this.fileExt;\r\n }\r\n if (autoCreateDir) {\r\n this.ensureDir(rel);\r\n }\r\n return this.resolvePath(rel);\r\n }\r\n\r\n deldir(relativePath: string): void {\r\n const absPath = this.resolvePath(relativePath);\r\n if (!fs.existsSync(absPath)) {\r\n return;\r\n }\r\n\r\n this.dbLog('delete', '[RMDIR]', absPath);\r\n const entries = fs.readdirSync(absPath, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const current = path.join(absPath, entry.name);\r\n if (entry.isDirectory()) {\r\n this.deldir(path.join(relativePath, entry.name));\r\n } else {\r\n this.dbLog('delete', '[UNLINK]', current);\r\n fs.unlinkSync(current);\r\n }\r\n }\r\n fs.rmdirSync(absPath);\r\n }\r\n\r\n private getReadPath(file: string, sql: Idb): { path: string; dir: string } {\r\n const candidates: Array<{ dir: string }> = [];\r\n\r\n if (sql?.filename) {\r\n candidates.push({ dir: path.join(file, sql.filename) });\r\n candidates.push({ dir: path.join(file + '.delete' + this.fileExt, sql.filename) });\r\n } else {\r\n candidates.push({ dir: file });\r\n candidates.push({ dir: file + this.fileExt + '.delete' });\r\n }\r\n\r\n for (const candidate of candidates) {\r\n const abs = this.getAbsPath(candidate.dir, false);\r\n if (fs.existsSync(abs)) {\r\n return { path: abs, dir: candidate.dir };\r\n }\r\n }\r\n\r\n return { path: '', dir: '' };\r\n }\r\n\r\n private getDelPath(file: string, sql: Idb): { path: string; dir: string } {\r\n const read = this.getReadPath(file, sql);\r\n if (!read.path) {\r\n return { path: '', dir: read.dir };\r\n }\r\n if (sql?.filename) {\r\n return { path: path.dirname(read.path), dir: path.dirname(read.dir) };\r\n }\r\n return { path: read.path, dir: read.dir };\r\n }\r\n\r\n private getNewPath(file: string, sql: Idb): string {\r\n if (sql?.filename) {\r\n return this.getAbsPath(path.join(file, sql.filename), true);\r\n }\r\n return this.getAbsPath(file, true);\r\n }\r\n\r\n write(file: string, data: any, sql: Idb): string | Error {\r\n try {\r\n const filePath = sql?.type === 'insert' ? this.getNewPath(file, sql) : this.getReadPath(file, sql).path || this.getNewPath(file, sql);\r\n this.dbLog('write', '[WRITE]', filePath);\r\n fs.writeFileSync(filePath, data, 'utf8');\r\n return 'ok';\r\n } catch (e) {\r\n this.dbLog('write failed', '[WRITE ERROR]', e);\r\n return e as Error;\r\n }\r\n }\r\n\r\n read(file: string, sql: Idb, encoding: BufferEncoding = 'utf8'): any {\r\n try {\r\n const read = this.getReadPath(file, sql);\r\n if (!read.path) {\r\n return { error: 'empty' };\r\n }\r\n this.dbLog('read', '[READ]', read.path);\r\n const data = fs.readFileSync(read.path, { encoding }) || '';\r\n const fileName = this.fileExt && read.dir.endsWith(this.fileExt) ? read.dir : read.dir + this.fileExt;\r\n return [{ data, file: fileName }];\r\n } catch (e) {\r\n this.dbLog('read failed', '[READ ERROR]', e);\r\n return e;\r\n }\r\n }\r\n\r\n del(file: string, sql: Idb): string | Error {\r\n try {\r\n const del = this.getDelPath(file, sql);\r\n if (!del.path) {\r\n return '';\r\n }\r\n\r\n if (this.fileDel && sql?.deltrue) {\r\n const target = del.path + '.delete' + this.fileExt;\r\n this.dbLog('soft delete', '[SOFT DELETE]', `${del.path} -> ${target}`);\r\n fs.renameSync(del.path, target);\r\n } else if (sql?.filename) {\r\n this.deldir(del.dir);\r\n } else {\r\n this.dbLog('delete', '[DELETE]', del.path);\r\n fs.unlinkSync(del.path);\r\n }\r\n return 'ok';\r\n } catch (e) {\r\n this.dbLog('delete failed', '[DELETE ERROR]', e);\r\n return e as Error;\r\n }\r\n }\r\n\r\n re(file: string, sql: Idb): string | Error {\r\n try {\r\n const del = this.getDelPath(file, sql);\r\n if (!del.path) {\r\n return '';\r\n }\r\n if (this.fileDel) {\r\n const extPattern = this.fileExt ? this.fileExt.replace(/\\./g, '\\\\.') : '';\r\n const original = del.path.replace(new RegExp(`\\.delete${extPattern}$`), '');\r\n if (original !== del.path) {\r\n this.dbLog('restore', '[RESTORE]', `${del.path} -> ${original}`);\r\n fs.renameSync(del.path, original);\r\n }\r\n } else {\r\n this.dbLog('force delete', '[FORCE DELETE]', del.path);\r\n fs.unlinkSync(del.path);\r\n }\r\n return 'ok';\r\n } catch (e) {\r\n this.dbLog('restore failed', '[RESTORE ERROR]', e);\r\n return e as Error;\r\n }\r\n }\r\n\r\n list(dir: string, sql: Idb): any {\r\n try {\r\n const absDir = this.resolvePath(dir);\r\n this.dbLog('list', '[LIST]', absDir);\r\n let entries: fs.Dirent[];\r\n try {\r\n entries = fs.readdirSync(absDir, { withFileTypes: true });\r\n } catch {\r\n return sql?.list ? { open: [], delete: [] } : [];\r\n }\r\n\r\n const result: any = { open: [], delete: [] };\r\n const deleteSuffix = '.delete' + this.fileExt;\r\n for (const entry of entries) {\r\n if (!entry.isFile()) continue;\r\n const fileName = entry.name;\r\n const isDelete = fileName.endsWith(deleteSuffix);\r\n const baseName = isDelete ? fileName.slice(0, -deleteSuffix.length) : fileName;\r\n if (this.fileExt && !baseName.endsWith(this.fileExt)) continue;\r\n const fullPath = path.join(absDir, fileName);\r\n try {\r\n const data = fs.readFileSync(fullPath, 'utf8');\r\n const entryData = { data, file: baseName };\r\n if (isDelete) {\r\n if (sql?.list) result.delete.push(entryData);\r\n } else {\r\n result.open.push(entryData);\r\n }\r\n } catch {\r\n // 单文件读取失败时忽略\r\n }\r\n }\r\n return sql?.list ? result : result.open;\r\n } catch (e) {\r\n this.dbLog('list failed', '[LIST ERROR]', e);\r\n return e;\r\n }\r\n }\r\n\r\n /** 从 where 首条条件中提取文件名(去掉 SQL 风格引号) */\r\n private getFileNameFromWhere(where: Idb['where']): string {\r\n if (!where || !Array.isArray(where)) return '';\r\n const first = where.find((item) => Array.isArray(item)) as [string, string, unknown] | undefined;\r\n const raw = first?.[2];\r\n if (typeof raw === 'string') {\r\n return raw.replace(/^'+|'+$/g, '');\r\n }\r\n return String(raw ?? '');\r\n }\r\n\r\n sqlDb(sql: Idb): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n let result: any;\r\n const tableDir = this.tableFilePath(sql.table);\r\n\r\n if (sql.type === 'insert') {\r\n const [file, data] = (sql.value as string[][])[0];\r\n result = this.write(this.tableFilePath(sql.table, file), data, sql);\r\n } else if (sql.type === 'delete') {\r\n const file = this.getFileNameFromWhere(sql.where);\r\n result = this.del(this.tableFilePath(sql.table, file), sql);\r\n } else if (sql.type === 're') {\r\n const file = this.getFileNameFromWhere(sql.where);\r\n result = this.re(this.tableFilePath(sql.table, file), sql);\r\n } else if (sql.type === 'update') {\r\n const file = this.getFileNameFromWhere(sql.where);\r\n const data = (sql.set as string[][])[0][1];\r\n result = this.write(this.tableFilePath(sql.table, file), data, sql);\r\n } else if (sql.type === 'select') {\r\n if (sql?.where?.length && sql?.as !== 2) {\r\n const file = this.getFileNameFromWhere(sql.where);\r\n const readRes = this.read(this.tableFilePath(sql.table, file), sql);\r\n const resObj: any = {};\r\n if (readRes?.[0]?.file && !readRes.error) {\r\n if (sql.as === 1) {\r\n try {\r\n const parsed = JSON.parse(readRes[0].data);\r\n if (sql.field?.length) {\r\n (sql.field as string[]).forEach((f) => {\r\n resObj[f] = parsed[f] ?? '';\r\n });\r\n } else {\r\n Object.assign(resObj, parsed);\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n } else {\r\n const fields = sql.field as string[];\r\n resObj[fields[0]] = readRes[0].file;\r\n if (fields[1]) {\r\n resObj[fields[1]] = readRes[0].data;\r\n }\r\n }\r\n }\r\n result = [resObj];\r\n } else {\r\n const listRes = this.list(tableDir, sql);\r\n if (listRes && !listRes.error) {\r\n if (sql?.list) {\r\n const mapEntry = (el: any) => {\r\n const fields = sql.field as string[];\r\n const item: any = { [fields[0]]: el.file };\r\n if (fields[1]) item[fields[1]] = el.data;\r\n return item;\r\n };\r\n if (listRes.open) listRes.open = listRes.open.map(mapEntry);\r\n if (listRes.delete) listRes.delete = listRes.delete.map(mapEntry);\r\n result = listRes;\r\n } else {\r\n if (sql?.as === 2) {\r\n let items = listRes;\r\n if (sql.where?.length) {\r\n const where = sql.where;\r\n const whereType = typeof where[0] === 'string' ? where[0] : 'and';\r\n items = items.filter((el: any) => {\r\n let match = whereType === 'and';\r\n for (let i = 0; i < where.length; i++) {\r\n if (typeof where[i] === 'string') continue;\r\n const cond = where[i];\r\n if (!cond) continue;\r\n const field = cond[0];\r\n const searchVal = String(cond[2]).replace(/%/g, '');\r\n let fieldVal = '';\r\n try {\r\n fieldVal = JSON.parse(el.data)[field] ?? '';\r\n } catch {\r\n /* ignore */\r\n }\r\n const condMatch = String(fieldVal).includes(searchVal);\r\n if (whereType === 'and') {\r\n match = match && condMatch;\r\n if (!match) break;\r\n } else {\r\n match = match || condMatch;\r\n if (match) break;\r\n }\r\n }\r\n return match;\r\n });\r\n }\r\n items = items.map((el: any) => {\r\n const obj: any = {};\r\n try {\r\n const parsed = JSON.parse(el.data);\r\n if (sql.field?.length) {\r\n (sql.field as string[]).forEach((f) => {\r\n obj[f] = parsed[f] ?? '';\r\n });\r\n } else {\r\n Object.assign(obj, parsed);\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n return obj;\r\n });\r\n if (sql.order?.length) {\r\n const orderField = sql.order[0];\r\n const orderFieldName = typeof orderField === 'string' ? orderField : orderField[0];\r\n const direction = typeof orderField === 'string' ? 'ASC' : String(orderField[1]).toUpperCase();\r\n items.sort((a: any, b: any) => {\r\n const valA = String(a[orderFieldName] ?? '');\r\n const valB = String(b[orderFieldName] ?? '');\r\n const cmp = valA.localeCompare(valB);\r\n return direction === 'DESC' ? -cmp : cmp;\r\n });\r\n }\r\n result = items;\r\n } else {\r\n const fields = sql.field as string[];\r\n result = listRes.map((el: any) => ({\r\n [fields[0]]: el.file,\r\n ...(fields[1] ? { [fields[1]]: el.data } : {}),\r\n }));\r\n }\r\n }\r\n } else {\r\n result = sql?.list ? { open: [], delete: [] } : [];\r\n }\r\n }\r\n }\r\n\r\n if (result !== undefined) {\r\n resolve(result);\r\n } else {\r\n reject('');\r\n }\r\n } catch (e) {\r\n reject(e);\r\n }\r\n });\r\n }\r\n}\r\n\r\nexport default DbFile;\r\n","import type Idb from \"./src/type\";\r\nimport type { DbInstance } from \"./src/common\";\r\nimport mysqlDb from \"./src/mysql/Index\";\r\nimport sqliteDb from \"./src/sqlite/Index\";\r\nimport fileDb from \"./src/file/Index\";\r\n\r\n/** 支持的数据库驱动类型 */\r\nexport type DbType = \"mysql\" | \"sqlite\" | \"file\";\r\n\r\ntype DbConstructor = new (config: Record<string, unknown>) => DbInstance;\r\n\r\nconst DRIVERS: Record<DbType, DbConstructor> = {\r\n mysql: mysqlDb,\r\n sqlite: sqliteDb,\r\n file: fileDb as unknown as DbConstructor,\r\n};\r\n\r\n/**\r\n * 数据库工厂函数\r\n * @param type 驱动类型,默认 file\r\n * @param config 传给对应驱动的配置\r\n */\r\nfunction initDb(\r\n type: DbType | string = \"file\",\r\n config: Record<string, unknown> = {},\r\n): DbInstance | Record<string, never> {\r\n const Driver = DRIVERS[type as DbType];\r\n if (Driver) {\r\n return new Driver(config);\r\n }\r\n return {};\r\n}\r\n\r\nexport default initDb;\r\nexport type { Idb };\r\n","import sysserverws from \"./ws/index\";\nimport sysserverapi from \"./api/index\";\nimport sysserverlib from \"./lib/index\";\nimport sysserverdb from \"./db/index\";\n\nexport default ($asai: any) => {\n if (!$asai.$lib) $asai.$lib = {};\n $asai.dataserver = sysserverdb;\n $asai.$lib = { ...sysserverlib, ...$asai.$lib };\n if (!$asai.asaifs) {\n $asai.asaifs = $asai.$lib.AsFs;\n }\n $asai.$lib.ErrorCode?.loadErrorCodes?.($asai);\n if (!$asai.$lib.api) $asai.$lib.api = {};\n $asai.$lib.api = { ...sysserverapi, ...$asai.$lib.api };\n if (!$asai.$lib.ws) $asai.$lib.ws = {};\n $asai.$lib.ws = { ...sysserverws, ...$asai.$lib.ws };\n};\n","/**\n * asaihost.json 启动校验(轻量 schema,fail-fast)\n */\nimport { normalizeHostSiteDefaults } from '../infra/host-limits';\n\n/** 启动前归一化 host 配置 */\nexport function normalizeHostConfig(cfg: Record<string, any>): Record<string, any> {\n\tif (!cfg || typeof cfg !== 'object') return {};\n\tnormalizeSecurityConfig(cfg);\n\tnormalizeUserStoreConfig(cfg);\n\tif (cfg.logger && typeof cfg.logger === 'object') {\n\t\tnormalizeLoggerStoreConfig(cfg.logger);\n\t}\n\tnormalizeDataStoresConfig(cfg);\n\tnormalizeHostsConfig(cfg);\n\treturn cfg;\n}\n\nfunction normalizeHostsConfig(cfg: Record<string, any>): void {\n\tif (!cfg.hosts || typeof cfg.hosts !== 'object') return;\n\tif (cfg.hosts.default && typeof cfg.hosts.default === 'object') {\n\t\tnormalizeHostSiteDefaults(cfg.hosts.default);\n\t}\n\tfor (const [name, host] of Object.entries(cfg.hosts)) {\n\t\tif (name === 'default' || !host || typeof host !== 'object') continue;\n\t\tnormalizeHostSiteDefaults(host as Record<string, unknown>);\n\t}\n}\n\n/** 启动时合并 security 默认值(向后兼容:未配置时等同旧行为) */\nexport function normalizeSecurityConfig(cfg: Record<string, any>): void {\n\tif (!cfg.security || typeof cfg.security !== 'object') {\n\t\tcfg.security = { requireAuth: 0, csp: 0, auditLog: 1 };\n\t\treturn;\n\t}\n\tconst sec = cfg.security;\n\tif (sec.requireAuth == null) sec.requireAuth = 0;\n\tif (sec.csp == null) sec.csp = 0;\n\tif (sec.auditLog == null) sec.auditLog = 1;\n\tif (!Array.isArray(sec.authSkipPaths)) {\n\t\tsec.authSkipPaths = [\n\t\t\t'/api/asailog/*',\n\t\t\t'/api/sys/errorcodes/*',\n\t\t\t'/api/user/login/auth/*',\n\t\t\t'/api/user/login/changepass/*',\n\t\t\t'/api/user/login/register/*',\n\t\t\t'/api/user/login/config/*',\n\t\t\t'/api/sys/health/metrics/*',\n\t\t\t'/sys/info/*',\n\t\t\t'/jsonp/*',\n\t\t];\n\t}\n\tif (!sec.quota || typeof sec.quota !== 'object') {\n\t\tsec.quota = { enabled: 0 };\n\t}\n\tif (sec.allowRegister == null) sec.allowRegister = 1;\n\tif (sec.lockoutMaxFails == null) sec.lockoutMaxFails = 5;\n\tif (sec.lockoutMinutes == null) sec.lockoutMinutes = 15;\n\tif (sec.sessionTtlHours == null) sec.sessionTtlHours = 24;\n\tif (sec.passwordMinLength == null) sec.passwordMinLength = 8;\n\tif (!sec.passwordPolicy || typeof sec.passwordPolicy !== 'object') {\n\t\tsec.passwordPolicy = {\n\t\t\tminLength: sec.passwordMinLength,\n\t\t\trequireLower: 1,\n\t\t\trequireDigit: 1,\n\t\t\trequireUpper: 0,\n\t\t\trequireSpecial: 0,\n\t\t\tmaxAgeDays: 0,\n\t\t\thistoryCount: 0,\n\t\t};\n\t}\n\tif (!sec.banner || typeof sec.banner !== 'object') {\n\t\tsec.banner = { enabled: 0, text: '' };\n\t}\n\tif (sec.sessionIdleMinutes == null) sec.sessionIdleMinutes = 0;\n\tif (!Array.isArray(sec.roles) || !sec.roles.length) {\n\t\tsec.roles = [\n\t\t\t{ name: 'viewer', minLv: 0, permissions: ['read'] },\n\t\t\t{ name: 'operator', minLv: 3, permissions: ['read', 'operate'] },\n\t\t\t{ name: 'engineer', minLv: 5, permissions: ['read', 'operate', 'audit'] },\n\t\t\t{ name: 'admin', minLv: 7, permissions: ['read', 'operate', 'audit', 'admin'] },\n\t\t\t{ name: 'developer', minLv: 9, permissions: ['read', 'operate', 'audit', 'admin', 'develop'] },\n\t\t\t{ name: 'superadmin', minLv: 99, permissions: ['read', 'operate', 'audit', 'admin', 'develop', 'super'] },\n\t\t];\n\t}\n\tif (sec.forceWss == null) sec.forceWss = 0;\n\tif (!Array.isArray(sec.userLevels) || !sec.userLevels.length) {\n\t\tsec.userLevels = [\n\t\t\t{ lv: 0, key: 'guest', name: '普通用户', nameEn: 'Guest' },\n\t\t\t{ lv: 3, key: 'operator', name: '操作员', nameEn: 'Operator' },\n\t\t\t{ lv: 5, key: 'engineer', name: '工程师', nameEn: 'Engineer' },\n\t\t\t{ lv: 7, key: 'admin', name: '管理员', nameEn: 'Administrator' },\n\t\t\t{ lv: 9, key: 'developer', name: '开发者', nameEn: 'Developer' },\n\t\t\t{ lv: 99, key: 'superadmin', name: '超级管理员', nameEn: 'Super Administrator' },\n\t\t];\n\t}\n\tif (!sec.permissionThresholds || typeof sec.permissionThresholds !== 'object') {\n\t\tsec.permissionThresholds = { logRead: 3, adminRead: 7, adminWrite: 9 };\n\t}\n}\n\n/** userStore 默认值(file / sqlite / mysql 可切换) */\nexport function normalizeUserStoreConfig(cfg: Record<string, any>): void {\n\tif (!cfg.userStore || typeof cfg.userStore !== 'object') {\n\t\tcfg.userStore = {\n\t\t\ttype: 'file',\n\t\t\topt: { dir: 'webdata/webdb/users/', ext: '.json', create: 1 },\n\t\t};\n\t\treturn;\n\t}\n\tconst store = cfg.userStore;\n\tif (!store.type) store.type = 'file';\n\tif (!store.opt || typeof store.opt !== 'object') store.opt = {};\n\tif (store.type === 'file') {\n\t\tif (!store.opt.dir) store.opt.dir = 'webdata/webdb/users/';\n\t\tif (!store.opt.ext) store.opt.ext = '.json';\n\t\tif (store.opt.create == null) store.opt.create = 1;\n\t} else if (store.type === 'sqlite') {\n\t\tif (!store.opt.database) store.opt.database = './webdata/webdb/users/users.db';\n\t\tif (store.opt.create == null) store.opt.create = 1;\n\t}\n}\n\n/** 统一日志存储(IEC 62443-4-2 + WEB 日志)— file / sqlite / mysql;默认 file 文件夹模式 */\nexport function normalizeLoggerStoreConfig(logger: Record<string, any>): void {\n\tif (!logger.store || typeof logger.store !== 'object') {\n\t\tlogger.store = { type: 'file', dir: 'webdata/webdb/log/store/', ext: '.json', create: 1 };\n\t\treturn;\n\t}\n\tconst store = logger.store;\n\tif (!store.type) store.type = 'file';\n\tif (store.type === 'file') {\n\t\tif (!store.dir) store.dir = 'webdata/webdb/log/store/';\n\t\tif (!store.ext) store.ext = '.json';\n\t} else if (store.type === 'sqlite') {\n\t\tif (!store.database) store.database = './webdata/webdb/log/asai-logs.db';\n\t} else if (store.type === 'mysql') {\n\t\tif (!store.host) store.host = '127.0.0.1';\n\t\tif (!store.user) store.user = 'root';\n\t\tif (store.password == null) store.password = '';\n\t\tif (!store.database) store.database = 'asai_logs';\n\t}\n\tif (store.create == null) store.create = 1;\n\tif (!logger.intervention) logger.intervention = {};\n\tif (!logger.intervention.archivePath) {\n\t\tlogger.intervention.archivePath = './webdata/webdb/log/intervention/archive/';\n\t}\n\tif (!logger.siem || typeof logger.siem !== 'object') {\n\t\tlogger.siem = { enabled: 0 };\n\t}\n\tif (logger.siem.enabled == null) logger.siem.enabled = 0;\n\tif (logger.diskAlertMb == null) logger.diskAlertMb = 512;\n\tif (logger.complianceIntervalHours == null) logger.complianceIntervalHours = 6;\n}\n\n/**\n * dataStores 统一注册表 — 合并 userStore / logger.store,全库经 getDataServer 切换后端\n */\nexport function normalizeDataStoresConfig(cfg: Record<string, any>): void {\n\tif (!cfg.dataStores || typeof cfg.dataStores !== 'object') {\n\t\tcfg.dataStores = {};\n\t}\n\tconst stores = cfg.dataStores;\n\n\tif (!stores.user && cfg.userStore) {\n\t\tstores.user = { type: cfg.userStore.type || 'file', opt: { ...(cfg.userStore.opt || {}) } };\n\t}\n\tif (!stores.log && cfg.logger?.store) {\n\t\tconst s = cfg.logger.store;\n\t\tstores.log = {\n\t\t\ttype: s.type || 'file',\n\t\t\topt: {\n\t\t\t\tdatabase: s.database,\n\t\t\t\tdir: s.dir,\n\t\t\t\text: s.ext,\n\t\t\t\thost: s.host,\n\t\t\t\tuser: s.user,\n\t\t\t\tpassword: s.password,\n\t\t\t\tcreate: s.create,\n\t\t\t},\n\t\t};\n\t}\n\tif (stores.log && typeof stores.log === 'object') {\n\t\tconst logStore = stores.log as Record<string, any>;\n\t\tconst logType = (logStore.type || 'file') as 'file' | 'sqlite' | 'mysql';\n\t\tif (!logStore.opt || typeof logStore.opt !== 'object') logStore.opt = {};\n\t\tif (logType === 'file') {\n\t\t\tif (!logStore.opt.dir) logStore.opt.dir = 'webdata/webdb/log/store/';\n\t\t\tif (!logStore.opt.ext) logStore.opt.ext = '.json';\n\t\t} else if (logType === 'sqlite') {\n\t\t\tif (!logStore.opt.database) logStore.opt.database = './webdata/webdb/log/asai-logs.db';\n\t\t}\n\t\tif (logStore.opt.create == null) logStore.opt.create = 1;\n\t}\n\tif (!stores.default) {\n\t\tstores.default = {\n\t\t\ttype: 'sqlite',\n\t\t\topt: { database: './webdata/webdb/sqlite/asaisqlite.db', create: 1 },\n\t\t};\n\t}\n\n\t// 反向同步 legacy 字段,保持旧配置可读\n\tif (stores.user) {\n\t\tcfg.userStore = { type: stores.user.type || 'file', opt: stores.user.opt || {} };\n\t\tnormalizeUserStoreConfig(cfg);\n\t}\n\tif (stores.log && cfg.logger) {\n\t\tconst lo = stores.log.opt || {};\n\t\tcfg.logger.store = {\n\t\t\ttype: stores.log.type || 'file',\n\t\t\tdatabase: lo.database,\n\t\t\tdir: lo.dir,\n\t\t\text: lo.ext,\n\t\t\thost: lo.host,\n\t\t\tuser: lo.user,\n\t\t\tpassword: lo.password,\n\t\t\tcreate: lo.create,\n\t\t};\n\t\tnormalizeLoggerStoreConfig(cfg.logger);\n\t}\n}\n\nexport function validateHostConfig(cfg: Record<string, any>): string[] {\n\tconst errors: string[] = [];\n\tif (!cfg || typeof cfg !== 'object') {\n\t\treturn ['hostconfig 必须为非空对象'];\n\t}\n\n\t// password / asaisn / aes.keybase64 / httpscert PEM 由 secrets 模块注入,禁止出现在 asaihost.json\n\tif (cfg.password != null) {\n\t\terrors.push('password 禁止写入 asaihost.json,请使用 ASAI_HOST_PASSWORD 或 asaihost.secrets.local.json');\n\t}\n\tif (cfg.asaisn != null) {\n\t\terrors.push('asaisn 禁止写入 asaihost.json,请使用 ASAI_ASAISN');\n\t}\n\tif (cfg.aes?.keybase64 != null) {\n\t\terrors.push('aes.keybase64 禁止写入 asaihost.json,请使用 ASAI_AES_KEYBASE64');\n\t}\n\tif (cfg.httpscert?.key != null || cfg.httpscert?.cert != null) {\n\t\terrors.push('httpscert.key/cert 禁止内联于 asaihost.json,请使用 keyPath/certPath 或环境变量');\n\t}\n\tif (cfg.security?.sessionSecret != null) {\n\t\terrors.push('security.sessionSecret 禁止写入 asaihost.json,请使用 ASAI_SESSION_SECRET');\n\t}\n\tif (Array.isArray(cfg.wssec) && typeof cfg.wssec[0] === 'string' && cfg.wssec[0].length > 0) {\n\t\terrors.push('wssec[0] 禁止写入 asaihost.json,请使用 ASAI_WSSEC_TOKEN');\n\t}\n\n\tnormalizeSecurityConfig(cfg);\n\tnormalizeUserStoreConfig(cfg);\n\n\tif (cfg.logger && typeof cfg.logger === 'object') {\n\t\tnormalizeLoggerStoreConfig(cfg.logger);\n\t}\n\tnormalizeDataStoresConfig(cfg);\n\n\tif (cfg.dataStores && typeof cfg.dataStores === 'object') {\n\t\tfor (const [name, store] of Object.entries(cfg.dataStores)) {\n\t\t\tconst s = store as Record<string, any>;\n\t\t\tif (!s.type || !['file', 'sqlite', 'mysql'].includes(s.type)) {\n\t\t\t\terrors.push(`dataStores.${name}.type 必须为 file|sqlite|mysql`);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (cfg.security && typeof cfg.security === 'object') {\n\t\tconst sec = cfg.security;\n\t\tif (sec.requireAuth != null && sec.requireAuth !== 0 && sec.requireAuth !== 1) {\n\t\t\terrors.push('security.requireAuth 必须为 0 或 1');\n\t\t}\n\t\tif (sec.csp != null && sec.csp !== 0 && sec.csp !== 1) {\n\t\t\terrors.push('security.csp 必须为 0 或 1');\n\t\t}\n\t\tif (sec.minUserLevel != null && (typeof sec.minUserLevel !== 'number' || sec.minUserLevel < 0)) {\n\t\t\terrors.push('security.minUserLevel 必须为非负整数');\n\t\t}\n\t}\n\n\tif (!cfg.hosts || typeof cfg.hosts !== 'object') {\n\t\terrors.push('hosts 必须为对象');\n\t} else {\n\t\tif (!cfg.hosts.default) {\n\t\t\terrors.push('hosts.default 缺失');\n\t\t} else {\n\t\t\tnormalizeHostSiteDefaults(cfg.hosts.default as Record<string, unknown>);\n\t\t}\n\t\tfor (const [name, host] of Object.entries(cfg.hosts)) {\n\t\t\tconst h = host as Record<string, any>;\n\t\t\tif (name === 'default') {\n\t\t\t\tvalidateHostSiteLimits(name, h, errors);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (h.port != null && (typeof h.port !== 'number' || h.port <= 0 || h.port > 65535)) {\n\t\t\t\terrors.push(`hosts.${name}.port 无效: ${h.port}`);\n\t\t\t}\n\t\t\tif (h.hostdirs != null && !Array.isArray(h.hostdirs)) {\n\t\t\t\terrors.push(`hosts.${name}.hostdirs 必须为数组`);\n\t\t\t}\n\t\t\tvalidateHostSiteLimits(name, h, errors);\n\t\t}\n\t}\n\n\tif (cfg.logger?.sample && typeof cfg.logger.sample !== 'object') {\n\t\terrors.push('logger.sample 必须为对象(如 { \"REQ_OTHER\": 0.1 })');\n\t}\n\tif (cfg.logger?.skip != null && !Array.isArray(cfg.logger.skip)) {\n\t\terrors.push('logger.skip 必须为字符串数组(如 [\"/sys/info/metrics\"])');\n\t}\n\n\tif (cfg.proxyhosts && typeof cfg.proxyhosts === 'object') {\n\t\tfor (const [name, proxy] of Object.entries(cfg.proxyhosts)) {\n\t\t\tconst p = proxy as Record<string, any>;\n\t\t\tif (p.url && p.proxyport != null && typeof p.proxyport !== 'number') {\n\t\t\t\terrors.push(`proxyhosts.${name}.proxyport 无效`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn errors;\n}\n\nfunction validateHostSiteLimits(name: string, h: Record<string, any>, errors: string[]): void {\n\tconst flags = ['close', 'ws', 'ckhttp', 'ckws', 'oncors'] as const;\n\tfor (const key of flags) {\n\t\tif (h[key] != null && h[key] !== 0 && h[key] !== 1) {\n\t\t\terrors.push(`hosts.${name}.${key} 必须为 0 或 1`);\n\t\t}\n\t}\n\tfor (const key of ['maxhttp', 'maxws', 'maxonline'] as const) {\n\t\tif (h[key] != null && (typeof h[key] !== 'number' || h[key] <= 0)) {\n\t\t\terrors.push(`hosts.${name}.${key} 必须为正整数`);\n\t\t}\n\t}\n\tif (h.cors != null && !Array.isArray(h.cors)) {\n\t\terrors.push(`hosts.${name}.cors 必须为字符串数组`);\n\t}\n}\n\n/** IEC 62443-4-2 — 生产环境强制安全配置(开发环境不校验) */\nexport function validateProductionSecurity(cfg: Record<string, any>): string[] {\n\tconst errors: string[] = [];\n\tif (process.env.NODE_ENV !== 'production') return errors;\n\n\tconst sec = cfg?.security;\n\tif (!sec || typeof sec !== 'object') {\n\t\terrors.push('生产环境必须配置 security 对象');\n\t\treturn errors;\n\t}\n\tif (sec.requireAuth !== 1) {\n\t\terrors.push('生产环境 security.requireAuth 必须为 1(CR 1.1 身份鉴别)');\n\t}\n\tif (sec.allowRegister === 1) {\n\t\terrors.push('生产环境 security.allowRegister 应为 0(CR 1.3 禁止开放注册)');\n\t}\n\tif (!sec.quota?.enabled) {\n\t\terrors.push('生产环境 security.quota.enabled 应为 1(CR 7.1 资源限制)');\n\t}\n\tif (sec.csp !== 1) {\n\t\terrors.push('生产环境 security.csp 应为 1(CR 7.6 内容安全策略)');\n\t}\n\tif (typeof sec.minUserLevel !== 'number' || sec.minUserLevel < 0) {\n\t\terrors.push('生产环境 security.minUserLevel 应显式配置');\n\t}\n\tif (sec.forceWss === 1 && !cfg?.httpscert?.keyPath && !cfg?.httpscert?.key) {\n\t\terrors.push('生产环境 security.forceWss=1 时需配置 HTTPS 证书');\n\t}\n\n\treturn errors;\n}\n","/**\r\n * syscom 通信配置 — tcp / grpc / rs485 统一读取、归一化与重连参数\r\n *\r\n * 配置结构(推荐):\r\n * hostconfig.syscom.{tcp|grpc|rs485}.default\r\n * 兼容旧版顶层 tcp/grpc/rs485/serial485/1tcp 等键名。\r\n */\r\n\r\nexport type TransportKind = 'tcp' | 'grpc' | 'rs485';\r\n\r\nexport interface ReconnectOptions {\r\n\tenabled?: boolean;\r\n\tmaxRetries?: number;\r\n\tinitialDelay?: number;\r\n\tmaxDelay?: number;\r\n\tfactor?: number;\r\n}\r\n\r\nconst LEGACY_TOP_LEVEL: Record<string, TransportKind> = {\r\n\t'1tcp': 'tcp',\r\n\t'1grpc': 'grpc',\r\n\t'1rs485': 'rs485',\r\n\tserial485: 'rs485',\r\n};\r\n\r\nconst DEFAULT_CONN_ID: Record<TransportKind, string> = {\r\n\ttcp: 'testtcp',\r\n\tgrpc: 'testgrpc',\r\n\trs485: 'testrs485',\r\n};\r\n\r\nconst DEFAULT_RECONNECT: Record<TransportKind, ReconnectOptions> = {\r\n\ttcp: { enabled: true, maxRetries: 60, initialDelay: 1000, maxDelay: 30000, factor: 2 },\r\n\tgrpc: { enabled: true, maxRetries: 60, initialDelay: 1000, maxDelay: 30000, factor: 2 },\r\n\trs485: { enabled: true, maxRetries: 60, initialDelay: 3000, maxDelay: 30000, factor: 2 },\r\n};\r\n\r\n/** 启动时归一化:syscom 优先,合并 legacy 键到 tcp/grpc/rs485 */\r\nexport function normalizeHostConfig(cfg: Record<string, any>): Record<string, any> {\r\n\tif (!cfg || typeof cfg !== 'object') return {};\r\n\r\n\tif (cfg.syscom && typeof cfg.syscom === 'object') {\r\n\t\tfor (const kind of Object.keys(DEFAULT_CONN_ID) as TransportKind[]) {\r\n\t\t\tif (cfg.syscom[kind]) {\r\n\t\t\t\tcfg[kind] = cfg.syscom[kind];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const [legacy, canonical] of Object.entries(LEGACY_TOP_LEVEL)) {\r\n\t\tif (cfg[legacy] && !cfg[canonical]) {\r\n\t\t\tcfg[canonical] = cfg[legacy];\r\n\t\t}\r\n\t}\r\n\r\n\treturn cfg;\r\n}\r\n\r\nexport function getTransportBlock(cfg: any, kind: TransportKind): Record<string, any> | null {\r\n\tconst block = cfg?.[kind];\r\n\treturn block && typeof block === 'object' ? block : null;\r\n}\r\n\r\nexport function getTransportDefault(cfg: any, kind: TransportKind): Record<string, any> | null {\r\n\tconst def = getTransportBlock(cfg, kind)?.default;\r\n\treturn def && typeof def === 'object' ? def : null;\r\n}\r\n\r\nexport function hasTransportDefault(cfg: any, kind: TransportKind): boolean {\r\n\treturn !!getTransportDefault(cfg, kind);\r\n}\r\n\r\n/** 默认连接 ID(来自配置 default.id,否则各传输内置默认值) */\r\nexport function getDefaultConnId(cfg: any, kind: TransportKind): string {\r\n\tconst def = getTransportDefault(cfg, kind);\r\n\tconst id = def?.id;\r\n\treturn typeof id === 'string' && id.length > 0 ? id : DEFAULT_CONN_ID[kind];\r\n}\r\n\r\n/** 是否在启动时自动 connect(default.autoConnect !== false 时为 true) */\r\nexport function shouldAutoConnect(def: Record<string, any> | null | undefined): boolean {\r\n\tif (!def) return false;\r\n\treturn def.autoConnect !== false;\r\n}\r\n\r\n/** 解析重连参数:default.reconnect > 传输默认值 > tm.maxtry */\r\nexport function resolveReconnectOptions(\r\n\tdef: Record<string, any> | null | undefined,\r\n\tkind: TransportKind,\r\n\tcfg?: Record<string, any>,\r\n): ReconnectOptions {\r\n\tconst base = DEFAULT_RECONNECT[kind];\r\n\tconst rc = def?.reconnect;\r\n\tconst tmMaxTry = cfg?.tm?.maxtry;\r\n\r\n\treturn {\r\n\t\tenabled: rc?.enabled !== false && base.enabled !== false,\r\n\t\tmaxRetries: rc?.maxRetries ?? tmMaxTry ?? base.maxRetries ?? 60,\r\n\t\tinitialDelay: rc?.initialDelay ?? base.initialDelay ?? 1000,\r\n\t\tmaxDelay: rc?.maxDelay ?? base.maxDelay ?? 30000,\r\n\t\tfactor: rc?.factor ?? base.factor ?? 2,\r\n\t};\r\n}\r\n","/**\r\n * TCP / gRPC / RS485 传输桥公共模板 — 连接管理、路由注册、数据 watch 广播\r\n */\r\nimport { registerApi, registerWs } from './registry';\r\nimport {\r\n\tgetTransportDefault,\r\n\tgetDefaultConnId,\r\n\tshouldAutoConnect,\r\n\ttype TransportKind,\r\n} from '../config/syscom';\r\n\r\nconst PENDING_CFG_KEY: Record<TransportKind, string> = {\r\n\ttcp: 'asaihosttcpPending',\r\n\tgrpc: 'asaihostgrpcPending',\r\n\trs485: 'asaihost485Pending',\r\n};\r\n\r\nexport interface TransportBridgeOptions {\r\n\t$asai: any;\r\n\tmanager: any;\r\n\tmanagerKey: string;\r\n\tserversKey: string;\r\n\ttransport: TransportKind;\r\n\tbuildDefaultConfig: (def: Record<string, any>) => Record<string, any>;\r\n\tapiRoute: string;\r\n\tapiHandler: any;\r\n\twsRoute: string;\r\n\twsHandler: any;\r\n}\r\n\r\n/** 初始化传输管理器:挂 $asai、可选默认连接、注册 API/WS 路由 */\r\nexport function initTransportBridge(opts: TransportBridgeOptions): any {\r\n\tconst { $asai, manager } = opts;\r\n\t$asai[opts.managerKey] = manager;\r\n\tif (!$asai[opts.serversKey]) {\r\n\t\t$asai[opts.serversKey] = {};\r\n\t}\r\n\r\n\tconst defaultCfg = getTransportDefault($asai.hostconfig, opts.transport);\r\n\tconst connId = getDefaultConnId($asai.hostconfig, opts.transport);\r\n\r\n\tif (defaultCfg) {\r\n\t\tconst built = opts.buildDefaultConfig(defaultCfg);\r\n\t\t$asai[PENDING_CFG_KEY[opts.transport]] = { connId, config: built };\r\n\t\tif (shouldAutoConnect(defaultCfg) && !$asai[opts.serversKey][connId]) {\r\n\t\t\t$asai[opts.serversKey][connId] = manager.connect(built);\r\n\t\t}\r\n\t}\r\n\r\n\tregisterApi($asai, opts.apiRoute, opts.apiHandler);\r\n\tregisterWs($asai, opts.wsRoute, opts.wsHandler);\r\n\treturn manager;\r\n}\r\n\r\n/** 首次 API/WS 调用时再建立默认连接(autoConnect: false 时) */\r\nexport function ensureDefaultConnection($asai: any, transport: TransportKind): string | null {\r\n\tconst pending = $asai[PENDING_CFG_KEY[transport]];\r\n\tif (!pending) return null;\r\n\r\n\tconst managerKey =\r\n\t\ttransport === 'tcp' ? 'asaihosttcp' : transport === 'grpc' ? 'asaihostgrpc' : 'asaihost485';\r\n\tconst serversKey =\r\n\t\ttransport === 'tcp'\r\n\t\t\t? 'asaihosttcpserver'\r\n\t\t\t: transport === 'grpc'\r\n\t\t\t\t? 'asaihostgrpcserver'\r\n\t\t\t\t: 'asaihost485server';\r\n\r\n\tconst manager = $asai[managerKey];\r\n\tif (!manager || !pending.connId) return null;\r\n\r\n\tif (!$asai[serversKey]) $asai[serversKey] = {};\r\n\tif (!$asai[serversKey][pending.connId]) {\r\n\t\t$asai[serversKey][pending.connId] = manager.connect(pending.config);\r\n\t}\r\n\treturn pending.connId;\r\n}\r\n\r\n/** 标准 DATA 事件:JSON 解析 + watch 匹配 / WS 广播 */\r\nexport function createTransportDataHandler($asai: any, manager: any) {\r\n\treturn (event: any) => {\r\n\t\tif (typeof event.data === 'string') {\r\n\t\t\ttry {\r\n\t\t\t\tevent.data = JSON.parse(event.data);\r\n\t\t\t} catch {\r\n\t\t\t\t// 非 JSON 保持原样\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (event.data?.id) {\r\n\t\t\tmanager.watch(event.id, event.data);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tconst wsKey = $asai?.command?.commandconfig?.config?.commandclient;\r\n\t\t\t$asai.serversws?.[wsKey]?.broadws?.(event.data);\r\n\t\t} catch {\r\n\t\t\t// 广播非必需\r\n\t\t}\r\n\t};\r\n}\r\n\r\n/** 连接状态日志(ERROR 由各 manager 内部输出,避免重复) */\r\nexport function wireTransportConnectionLogs(\r\n\tmanager: any,\r\n\tevents: { CONNECTED: string; DISCONNECTED: string; ERROR?: string },\r\n\tlogPrefix: string,\r\n): void {\r\n\tmanager.on(events.CONNECTED, (event: any) => {\r\n\t\tconsole.log(`${logPrefix} 连接上线`, event.id, event.label || '');\r\n\t});\r\n\tmanager.on(events.DISCONNECTED, (event: any) => {\r\n\t\tconsole.log(`${logPrefix} 连接离线`, event.id, event.label || '');\r\n\t});\r\n\t// manager 内部已 console.error;此处仅注册 listener,避免 ERR_UNHANDLED_ERROR\r\n\tif (events.ERROR) {\r\n\t\tmanager.on(events.ERROR, () => {});\r\n\t}\r\n}\r\n","/**\n * AsaiRuntime 类型定义 — 逐步替换 any,保持与现有 $asai 对象兼容\n */\nimport type { WsRouteIndex } from './ws/route-index';\n\nexport type RouteFactory = ($asai: AsaiRuntime) => Record<string, unknown>;\n\n/** IEC 62443-4-2 安全策略(默认全关,不影响现有行为) */\nexport interface SecurityConfig {\n\t/** 1=强制 HTTP Userinfo 鉴权;0=关闭(默认) */\n\trequireAuth?: number;\n\t/** 1=启用 Content-Security-Policy */\n\tcsp?: number;\n\t/** 自定义 CSP 策略字符串 */\n\tcspPolicy?: string;\n\t/** 1=记录安全审计事件(默认开启) */\n\tauditLog?: number;\n\t/** 鉴权白名单路径(支持 * 后缀前缀匹配) */\n\tauthSkipPaths?: string[];\n\t/** 最低用户等级(requireAuth=1 时生效) */\n\tminUserLevel?: number;\n\t/** 0=禁止开放注册(生产推荐) */\n\tallowRegister?: number;\n\tlockoutMaxFails?: number;\n\tlockoutMinutes?: number;\n\tsessionTtlHours?: number;\n\tpasswordMinLength?: number;\n\t/** CR 1.12 登录前系统使用通知 */\n\tbanner?: { enabled?: number; text?: string };\n\t/** CR 1.7 口令强度策略 */\n\tpasswordPolicy?: {\n\t\tminLength?: number;\n\t\trequireUpper?: number;\n\t\trequireLower?: number;\n\t\trequireDigit?: number;\n\t\trequireSpecial?: number;\n\t\tmaxAgeDays?: number;\n\t\thistoryCount?: number;\n\t};\n\t/** CR 2.5 会话空闲锁定(分钟,0=关闭) */\n\tsessionIdleMinutes?: number;\n\t/** CR 2.1 SL-2 角色定义 */\n\troles?: Array<{ name: string; minLv: number; permissions?: string[] }>;\n\t/** CR 3.1 SL-2 生产强制 WSS */\n\tforceWss?: number;\n\tquota?: {\n\t\tenabled?: number;\n\t\tmaxApiConcurrent?: number;\n\t\tmaxApiPerIp?: number;\n\t\tmaxApiPerIpPerMin?: number;\n\t\tmaxWsPerIp?: number;\n\t\tmaxLoginSessions?: number;\n\t\tmaxSessionsPerUser?: number;\n\t\tonUserSessionOverflow?: string;\n\t};\n}\n\nexport interface HostConfig {\n\twebsite?: { title?: string; ver?: string };\n\tpassword?: string;\n\tsecurity?: SecurityConfig;\n\tip?: string;\n\tindex?: string;\n\toncors?: number;\n\tasaiport?: number[];\n\tguardtm?: ReturnType<typeof setTimeout> | null;\n\thosts?: Record<string, HostSiteConfig>;\n\tproxyhosts?: Record<string, ProxySiteConfig>;\n\tlogger?: LoggerConfig;\n\tmimetypes?: Record<string, string>;\n\taes?: { lv?: number; keybase64?: string; aad?: string };\n\tpath?: { mock?: string; ip?: string };\n\ttm?: { c?: number; d?: number; maxtry?: number };\n\tpkg?: { type?: number };\n\t[key: string]: unknown;\n}\n\nexport interface HostSiteConfig {\n\tclose?: number;\n\tport?: number;\n\tws?: number;\n\tckhttp?: number;\n\tckws?: number;\n\tmaxhttp?: number;\n\tmaxws?: number;\n\tmaxonline?: number;\n\toncors?: number;\n\twstype?: string;\n\thttptype?: string;\n\thostdirs?: string[];\n\tweburls?: {\n\t\trewrite?: boolean;\n\t\twebdir?: string;\n\t\tkeys?: string[];\n\t};\n\tmimetypes?: Record<string, string>;\n\tcors?: string[];\n\t[key: string]: unknown;\n}\n\nexport interface ProxySiteConfig {\n\turl?: string;\n\tport?: number;\n\tproxyport?: number;\n\thttptype?: string;\n\tproxyhttptype?: string;\n\t[key: string]: unknown;\n}\n\nexport interface LoggerConfig {\n\tlv?: { view?: number; record?: number };\n\tpath?: { maxsize?: number; client?: string; server?: string };\n\t/** 采样率 0~1,如 { \"REQ_OTHER\": 0.05 } */\n\tsample?: Record<string, number>;\n\t/** 不写日志的请求路径(精确匹配;以 * 结尾为前缀匹配) */\n\tskip?: string[];\n\t/** IEC 62443-4-2 干预日志(CEF 格式,留存≥5年) */\n\tintervention?: {\n\t\tpath?: string;\n\t\tretentionYears?: number;\n\t\t/** 演示/自动化测试触发的干预动作专用存储目录,与生产留存数据完全隔离,不计入合规审计留存 */\n\t\ttestPath?: string;\n\t};\n}\n\nexport type WorkHandler = (req: unknown, res: unknown, hostdir: string) => void;\nexport type WsWorkHandler = (msg: unknown, ws: unknown, hostdir: string, req: unknown) => void;\n\nexport interface AsaiHostOptions {\n\tsysWork: WorkHandler;\n\tapiWork: WorkHandler;\n\twsWork: WsWorkHandler;\n\tjsonpWork: WorkHandler;\n}\n\n/** 运行时主对象(与 app.ts 中 $asai 结构一致) */\nexport interface AsaiRuntime {\n\t$lib: Record<string, unknown>;\n\thostconfig: HostConfig;\n\tasaizip?: unknown;\n\tdataserver?: unknown;\n\tasaihost?: Record<string, unknown>;\n\tasaimock?: Record<string, unknown>;\n\tconnectionshttp: Record<string, Set<unknown>>;\n\tconnectionsws: Record<string, Record<string, unknown>>;\n\ttaskshttp: Record<string, unknown>;\n\ttasksws: Record<string, unknown>;\n\tservershttp: Record<string, unknown>;\n\tserversws: Record<string, unknown>;\n\thostserverapi?: Record<string, RouteFactory>;\n\thostserverapis?: string[];\n\thostserverws?: Record<string, RouteFactory>;\n\thostserverwss?: string[];\n\thostserversys?: Record<string, RouteFactory>;\n\thostserversyss?: string[];\n\twsRouteIndex?: WsRouteIndex;\n\tregisterApi?: (key: string, factory: RouteFactory) => void;\n\tregisterWs?: (key: string, factory: RouteFactory) => void;\n\tsetAppend?: (src: string, logstr: string) => Promise<void>;\n\tgetHost?: (hostdir: string) => HostSiteConfig;\n\tgetHostIP?: (ip?: string | null) => string;\n\tstartHTTPServer?: (hostdir: string) => unknown;\n\t$log?: (...args: unknown[]) => void | Promise<void>;\n\tcommand?: Record<string, unknown>;\n\ttmpdata: Record<string, unknown>;\n\ttm: number;\n\t[key: string]: unknown;\n}\n\n/** 兼容旧代码的全局别名 */\nexport type AsaiGlobal = AsaiRuntime;\nexport type HostConfigLegacy = HostConfig;\nexport type ProxyHostConfig = ProxySiteConfig;\n\n/** npm 包标识(与 package.json name 一致) */\nexport const PLUGIN_NAME = 'asaihost-nodejs' as const;\n\n/** `fn($asai, opt)` 返回值:启动函数 + ws 模块引用 */\nexport interface HostBootResult {\n\tStartAsaiHost: () => void;\n\tasaiWs: typeof import('ws');\n}\n\n/** 宿主插件对外 API 形状(具体方法签名见默认导出推断类型 AsaiNodejsHostPlugin) */\nexport interface AsaiNodejsHostPlugin {\n\treadonly name: typeof PLUGIN_NAME;\n\tfn: (runtime: AsaiRuntime, options: AsaiHostOptions) => HostBootResult;\n\tsysserver: (runtime: AsaiRuntime) => void;\n\tAsaiCommon: Record<string, unknown>;\n\tAsaiUtils: Record<string, unknown>;\n\t[key: string]: unknown;\n}\n","/**\r\n * asaihost-nodejs — Node.js HTTP/WebSocket 服务器宿主\r\n *\r\n * 默认导出为宿主插件对象;配置校验、路由注册、安全工具等见命名导出。\r\n */\r\nimport hostMainMod from './src/index';\r\nimport * as AsaiUtils from './src/utils';\r\nimport AsaiCommon from './src/common/Index';\r\nimport sysserver from './src/sysserver/index';\r\nimport {\r\n\tnormalizeHostConfig,\r\n\tvalidateHostConfig,\r\n\tvalidateProductionSecurity,\r\n} from './src/config/validate';\r\nimport {\r\n\tgetHostAllowedRoots,\r\n\tinitHostserverApi,\r\n\tinitHostserverWs,\r\n\tregisterApi,\r\n\tregisterWs,\r\n\tresolvePathUnderRoots,\r\n\tsecureCompare,\r\n\tsyncApiRouteKeys,\r\n\tsyncWsRouteKeys,\r\n\tlogSecurityEvent,\r\n\tsanitizeString,\r\n\tvalidateHttpAuth,\r\n\tnormalizeSecurityConfig,\r\n\tstripForbiddenSecretsFromHostConfig,\r\n\tloadAsaiSecrets,\r\n\tloadDotEnvFile,\r\n\tapplySecretsToHostConfig,\r\n\tresolveHttpsCertFromPaths,\r\n\tvalidateAsaiSecrets,\r\n\tisDevDefaultPassword,\r\n\thasTransportDefault,\r\n\tgetTransportDefault,\r\n\tgetDefaultConnId,\r\n\tgetTransportBlock,\r\n\tresolveReconnectOptions,\r\n\tshouldAutoConnect,\r\n\tinitTransportBridge,\r\n\tensureDefaultConnection,\r\n\tcreateTransportDataHandler,\r\n\twireTransportConnectionLogs,\r\n} from './src/host-api';\r\nimport type {\r\n\tAsaiNodejsHostPlugin,\r\n\tAsaiRuntime,\r\n\tAsaiHostOptions,\r\n\tHostBootResult,\r\n\tHostConfig,\r\n} from './src/types';\r\nimport { PLUGIN_NAME as PLUGIN_NAME_CONST } from './src/types';\r\n\r\ndeclare const __ASAIHOST_NODEJS_VERSION__: string;\r\n\r\n/** 兼容 tsx / CJS default 互操作 */\r\nfunction hostDefault<T>(mod: T): T {\r\n\tif (mod && typeof mod === 'object' && 'default' in (mod as object)) {\r\n\t\tconst d = (mod as unknown as { default?: T }).default;\r\n\t\tif (d !== undefined) return d;\r\n\t}\r\n\treturn mod;\r\n}\r\n\r\nconst hostMain = hostDefault(hostMainMod);\r\n\r\nconst initAsaiHost: AsaiNodejsHostPlugin = {\r\n\tname: PLUGIN_NAME_CONST,\r\n\tfn: ($asai: AsaiRuntime, opt: AsaiHostOptions): HostBootResult =>\r\n\t\thostMain($asai, opt) as HostBootResult,\r\n\tsysserver,\r\n\tAsaiCommon,\r\n\tAsaiUtils,\r\n\tnormalizeHostConfig,\r\n\tvalidateHostConfig,\r\n\tvalidateProductionSecurity,\r\n\tregisterApi,\r\n\tregisterWs,\r\n\tinitHostserverApi,\r\n\tinitHostserverWs,\r\n\tsyncApiRouteKeys,\r\n\tsyncWsRouteKeys,\r\n\tsecureCompare,\r\n\tresolvePathUnderRoots,\r\n\tgetHostAllowedRoots,\r\n\tlogSecurityEvent,\r\n\tsanitizeString,\r\n\tvalidateHttpAuth,\r\n\tnormalizeSecurityConfig,\r\n\tstripForbiddenSecretsFromHostConfig,\r\n\tloadAsaiSecrets,\r\n\tloadDotEnvFile,\r\n\tapplySecretsToHostConfig,\r\n\tresolveHttpsCertFromPaths,\r\n\tvalidateAsaiSecrets,\r\n\tisDevDefaultPassword,\r\n\tgetTransportBlock,\r\n\tgetTransportDefault,\r\n\thasTransportDefault,\r\n\tgetDefaultConnId,\r\n\tresolveReconnectOptions,\r\n\tshouldAutoConnect,\r\n\tinitTransportBridge,\r\n\tensureDefaultConnection,\r\n\tcreateTransportDataHandler,\r\n\twireTransportConnectionLogs,\r\n};\r\n\r\nexport {\r\n\tPLUGIN_NAME_CONST as PLUGIN_NAME,\r\n\tinitAsaiHost,\r\n\tnormalizeHostConfig,\r\n\tvalidateHostConfig,\r\n\tvalidateProductionSecurity,\r\n\tregisterApi,\r\n\tregisterWs,\r\n\tinitHostserverApi,\r\n\tinitHostserverWs,\r\n\tsyncApiRouteKeys,\r\n\tsyncWsRouteKeys,\r\n\tsecureCompare,\r\n\tresolvePathUnderRoots,\r\n\tgetHostAllowedRoots,\r\n\tlogSecurityEvent,\r\n\tsanitizeString,\r\n\tvalidateHttpAuth,\r\n\tnormalizeSecurityConfig,\r\n\tstripForbiddenSecretsFromHostConfig,\r\n\tloadAsaiSecrets,\r\n\tloadDotEnvFile,\r\n\tapplySecretsToHostConfig,\r\n\tresolveHttpsCertFromPaths,\r\n\tvalidateAsaiSecrets,\r\n\tisDevDefaultPassword,\r\n\tgetTransportBlock,\r\n\tgetTransportDefault,\r\n\thasTransportDefault,\r\n\tgetDefaultConnId,\r\n\tresolveReconnectOptions,\r\n\tshouldAutoConnect,\r\n\tinitTransportBridge,\r\n\tensureDefaultConnection,\r\n\tcreateTransportDataHandler,\r\n\twireTransportConnectionLogs,\r\n\tAsaiCommon,\r\n\tAsaiUtils,\r\n\tsysserver,\r\n};\r\n\r\nexport type {\r\n\tAsaiNodejsHostPlugin,\r\n\tAsaiRuntime,\r\n\tAsaiHostOptions,\r\n\tHostBootResult,\r\n\tHostConfig,\r\n\tSecurityConfig,\r\n\tHostSiteConfig,\r\n\tProxySiteConfig,\r\n\tLoggerConfig,\r\n\tRouteFactory,\r\n\tWorkHandler,\r\n\tWsWorkHandler,\r\n} from './src/types';\r\n\r\nexport type { AsaiSecrets } from './src/config/secrets';\r\nexport type { TransportKind, ReconnectOptions } from './src/config/syscom';\r\nexport type { SecurityAuditEvent, SecurityEventType } from './src/infra/security-audit';\r\nexport type { AuthCheckResult } from './src/infra/access-control';\r\nexport type { StoreDomain } from './src/sysserver/db/data-store';\r\n\r\n/** 构建时注入的版本号(与 package.json version 同步) */\r\nexport const PLUGIN_VERSION =\r\n\ttypeof __ASAIHOST_NODEJS_VERSION__ !== 'undefined'\r\n\t\t? __ASAIHOST_NODEJS_VERSION__\r\n\t\t: '0.0.1';\r\n\r\nexport default initAsaiHost;\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,YAAY,QAAQ;;;ACLpB,YAAY,QAAQ;AAEb,SAAS,QAAgB;AAC/B,MAAI;AACH,UAAM,aAAgB,qBAAkB;AACxC,eAAW,QAAQ,OAAO,KAAK,UAAU,GAAG;AAC3C,YAAM,QAAQ,WAAW,IAAI;AAC7B,UAAI,CAAC,MAAO;AACZ,iBAAW,SAAS,OAAO;AAC1B,YAAI,MAAM,WAAW,UAAU,MAAM,YAAY,eAAe,CAAC,MAAM,UAAU;AAChF,iBAAO,MAAM;AAAA,QACd;AAAA,MACD;AAAA,IACD;AAAA,EACD,SAAS,KAAK;AACb,YAAQ,MAAM,yBAAyB,GAAG;AAAA,EAC3C;AACA,SAAO;AACR;AAhBgB;AAkBT,SAAS,UAAU,IAAoB,OAAqB;AAClE,MAAI,MAAM,OAAO,OAAO,SAAU,QAAO;AACzC,MAAI,OAAO,YAAY,OAAO,OAAQ,QAAO;AAC7C,SAAO,OAAO,YAAY,MAAM;AACjC;AAJgB;;;AClBhB,IAAM,eAAe,oBAAI,IAAiB;AAC1C,IAAM,oBAAoB,oBAAI,IAAiB;AAExC,SAAS,gBAAgB,SAA0B;AACzD,MAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,KAAK,QAAQ,SAAS,OAAO,YAAY,aAAa,YAAY,QAAQ;AAC/H,WAAO;AAAA,EACR;AACA,SAAO,mBAAmB,KAAK,OAAO;AACvC;AALgB;AAOhB,SAAS,YAAY,SAAiB,OAAiB;AACtD,MAAI,OAAO,aAAa,IAAI,OAAO;AACnC,MAAI,CAAC,MAAM;AACV,UAAM,aAAa,MAAM,WAAW,MAAM,WAAW,CAAC;AACtD,UAAM,UAAU,MAAM,WAAW,MAAM,OAAO,KAAK,CAAC;AACpD,WAAO,EAAE,GAAG,YAAY,GAAG,QAAQ;AACnC,iBAAa,IAAI,SAAS,IAAI;AAAA,EAC/B;AACA,SAAO;AACR;AATS;AAYF,SAAS,WAAW,SAAiB,OAAiB;AAC5D,SAAO,EAAE,GAAG,YAAY,SAAS,KAAK,EAAE;AACzC;AAFgB;AAIhB,SAAS,iBAAiB,cAAsB,OAAiB;AAChE,MAAI,OAAO,kBAAkB,IAAI,YAAY;AAC7C,MAAI,CAAC,MAAM;AACV,UAAM,aAAa,MAAM,WAAW,YAAY,WAAW,CAAC;AAC5D,UAAM,WAAW,MAAM,WAAW,aAAa,YAAY,KAAK,CAAC;AACjE,WAAO,EAAE,GAAG,YAAY,GAAG,SAAS;AACpC,QAAI,CAAC,KAAK,OAAO,KAAK,MAAM;AAC3B,WAAK,OAAO,KAAK,YAAY,aAAa,UAAU,KAAK,IAAI,KAAK,IAAI,MAAM,KAAK;AAAA,IAClF;AACA,sBAAkB,IAAI,cAAc,IAAI;AAAA,EACzC;AACA,SAAO;AACR;AAZS;AAcF,SAAS,gBAAgB,cAAsB,OAAiB;AACtE,SAAO,EAAE,GAAG,iBAAiB,cAAc,KAAK,EAAE;AACnD;AAFgB;;;ACpCT,SAAS,YAAY,OAAY,IAA0C;AAC9E,QAAM,eAAe,OAAO,YAAY,IAAI,UAAU;AACtD,QAAM,iBAAiB,OAAO,YAAY,IAAI,iBAAiB;AAC/D,QAAM,eAAyB,CAAC;AAGhC,MAAI,QAAQ,MAAM,OAAO,QAAQ,OAAO,cAAc,8BAA8B,SAAS;AACzF,YAAQ,GAAG,4BAA4B,CAAC,QAAe;AACnD,UAAI;AACA,cAAM,KAAK,SAAS,mBAAmB,KAAK,WAAW,GAAG,EAAE;AAAA,MAChE,QAAQ;AAAA,MAER;AAAA,IACJ,CAAC;AAAA,EACL;AAEA,UAAQ,GAAG,sBAAsB,CAAC,QAAiB,YAA8B;AAC7E,UAAM,aAAa,IAAI,MAAM,EAAE;AAC/B,QAAI,cAAc;AAClB,QAAI,WAAW,OAAO,YAAY,UAAU;AACxC,oBAAc,QAAQ,aAAa,QAAQ;AAC3C,YAAM,aAAa,YAAY,MAAM,IAAI,KAAK,CAAC;AAC/C,YAAM,gBAAgB,WAAW,MAAM,GAAG,CAAC,EAAE,KAAK,KAAK;AACvD,qBAAe,gBAAgB,aAAa;AAAA,IAChD;AAEA,QAAI,aAAa;AACjB,QAAI,kBAAkB,OAAO;AACzB,mBAAa;AAAA,EAAK,OAAO,IAAI,KAAK,OAAO,OAAO;AAChD,UAAI,OAAO,MAAO,eAAc;AAAA,mBAAY,OAAO,KAAK;AAAA,IAC5D,WAAW,OAAO,WAAW,YAAY,WAAW,MAAM;AACtD,UAAI;AACA,qBAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,UAAU,GAAG,GAAG;AAAA,MACjE,QAAQ;AACJ,qBAAa,OAAO,MAAM;AAAA,MAC9B;AAAA,IACJ,OAAO;AACH,mBAAa,OAAO,MAAM;AAAA,IAC9B;AAEA,UAAM,WAAW;AAAA,qBAA0C,UAAU;AAAA,qBAAc,WAAW;AAC9F,UAAM,KAAK,uBAAuB,QAAQ;AAAA,EAC9C,CAAC;AAED,UAAQ,GAAG,qBAAqB,CAAC,QAAe;AAC5C,UAAM,WAAW,uBAAuB,KAAK,UAAU,GAAG,CAAC;AAC3D,QAAI;AACA,YAAM,KAAK,uBAAuB,QAAQ;AAAA,IAC9C,QAAQ;AAAA,IAER;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,iBAAa,KAAK,GAAG;AACrB,WAAO,aAAa,SAAS,KAAK,aAAa,CAAC,IAAI,MAAM,gBAAgB;AACtE,mBAAa,MAAM;AAAA,IACvB;AAEA,QAAI,aAAa,SAAS,cAAc;AACpC,UAAI;AACA,cAAM,KAAK,cAAc,kFAAkF;AAC3G,aAAK,OAAO,qCAA4C,EAAE;AAAA,UAAK,CAAC,EAAE,qBAAqB,MACnF,qBAAqB,OAAO;AAAA,YACxB,QAAQ;AAAA,YACR,QAAQ,GAAG,aAAa,MAAM,eAAe,cAAc;AAAA,YAC3D,SAAS;AAAA,YACT,UAAU;AAAA,UACd,CAAC;AAAA,QACL,EAAE,MAAM,MAAM,MAAS;AAAA,MAC3B,QAAQ;AAAA,MAER;AACA,UAAI;AACA,cAAM,KAAK,YAAY,UAAU,KAAK,WAAW,GAAG;AAAA,MACxD,QAAQ;AAAA,MAER;AACA,uBAAiB,KAAK;AACtB;AAAA,IACJ;AAEA,QAAI,MAAM,OAAO,OAAO,YAAY;AAChC,UAAI;AACA,WAAG,GAAG;AAAA,MACV,SAAS,aAAa;AAClB,gBAAQ,MAAM,oCAAoC,WAAW;AAAA,MACjE;AAAA,IACJ;AAAA,EACJ,CAAC;AAED,UAAQ,GAAG,WAAW,MAAM;AACxB,QAAI;AACA,YAAM,KAAK,WAAW,yBAAoB;AAAA,IAC9C,QAAQ;AAAA,IAER;AACA,qBAAiB,KAAK;AAAA,EAC1B,CAAC;AAED,UAAQ,GAAG,UAAU,MAAM;AACvB,QAAI;AACA,YAAM,KAAK,UAAU,wBAAmB;AAAA,IAC5C,QAAQ;AAAA,IAER;AACA,qBAAiB,KAAK;AAAA,EAC1B,CAAC;AACL;AA3GgB;AA6GT,SAAS,iBAAiB,OAAkB;AAC/C,OAAK,OAAO,qCAA4C,EAAE;AAAA,IAAK,CAAC,EAAE,qBAAqB,MACnF,qBAAqB,OAAO;AAAA,MACxB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACb,CAAC;AAAA,EACL,EAAE,MAAM,MAAM,MAAS;AAEvB,QAAM,kBAAkB;AACxB,MAAI;AAEJ,QAAM,YAAY,KAAK,IAAI;AAC3B,kBAAgB,WAAW,MAAM;AAC7B,UAAM,KAAK,YAAY,0BAA0B,KAAK,IAAI,IAAI,SAAS,IAAI;AAC3E,YAAQ,KAAK,CAAC;AAAA,EAClB,GAAG,eAAe;AAElB,MAAI;AACA,WAAO,OAAO,MAAM,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAgB;AAC5D,UAAI,UAAU,OAAO,OAAO,UAAU,YAAY;AAC9C,eAAO,MAAM,CAAC,QAAgB;AAC1B,cAAI,IAAK,OAAM,KAAK,QAAQ,4BAA4B,GAAG;AAAA,QAC/D,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAED,WAAO,OAAO,MAAM,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAgB;AAC1D,UAAI,UAAU,OAAO,OAAO,UAAU,YAAY;AAC9C,eAAO,MAAM,CAAC,QAAgB;AAC1B,cAAI,IAAK,OAAM,KAAK,MAAM,0BAA0B,GAAG;AAAA,QAC3D,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAED,QAAI,MAAM,WAAW,SAAS;AAC1B,mBAAa,MAAM,WAAW,OAAO;AACrC,YAAM,WAAW,UAAU;AAAA,IAC/B;AAEA,WAAO,KAAK,MAAM,WAAW,CAAC,CAAC,EAAE,QAAQ,CAAC,YAAY;AAClD,UAAI,MAAM,QAAQ,OAAO,EAAE,aAAa;AACpC,sBAAc,MAAM,QAAQ,OAAO,EAAE,WAAW;AAChD,eAAO,MAAM,QAAQ,OAAO,EAAE;AAAA,MAClC;AAAA,IACJ,CAAC;AAED,eAAW,MAAM;AACb,mBAAa,aAAa;AAC1B,YAAM,KAAK,YAAY,sBAAsB,KAAK,IAAI,IAAI,SAAS,KAAK;AACxE,cAAQ,KAAK,CAAC;AAAA,IAClB,GAAG,GAAI;AAAA,EACX,SAAS,KAAK;AACV,UAAM,KAAK,YAAY,4BAA4B,GAAG;AACtD,iBAAa,aAAa;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAClB;AACJ;AAzDgB;;;AC1GhB,OAAO,QAAQ;AAYf,IAAM,aAAa,oBAAI,IAAuB;AAG9C,SAAS,qBAA2B;AAClC,aAAW,QAAQ,CAAC,WAAW;AAC7B,WAAO,WAAW;AAAA,EACpB,CAAC;AACH;AAJS;AAWT,IAAM,YAAN,MAAM,WAAU;AAAA,EASd,YACU,OACA,UACR;AAFQ;AACA;AAVV,SAAQ,SAAmB,CAAC;AAC5B,SAAQ,QAA8C;AACtD,SAAiB,gBAAgB;AACjC;AAAA,SAAiB,gBAAgB;AAU/B,QAAI,CAAC,WAAU,uBAAuB;AACpC,iBAAU,wBAAwB;AAClC,cAAQ,KAAK,cAAc,MAAM,mBAAmB,CAAC;AAAA,IACvD;AAAA,EACF;AAAA,EAtDF,OAoCgB;AAAA;AAAA;AAAA,EAOd;AAAA;AAAA;AAAA,SAAe,wBAAwB;AAAA;AAAA;AAAA,EAchC,IAAI,SAAuB;AAChC,SAAK,OAAO,KAAK,OAAO;AAExB,QAAI,KAAK,OAAO,UAAU,KAAK,eAAe;AAC5C,WAAK,MAAM;AAAA,IACb,WAAW,CAAC,KAAK,OAAO;AACtB,WAAK,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,aAAa;AAAA,IAChE;AAAA,EACF;AAAA;AAAA,EAGO,aAAmB;AACxB,SAAK,MAAM;AAAA,EACb;AAAA;AAAA,EAGQ,QAAc;AACpB,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AACA,QAAI,KAAK,OAAO,WAAW,EAAG;AAE9B,UAAM,aAAa,KAAK,OAAO,KAAK,EAAE;AACtC,SAAK,SAAS,CAAC;AACf,SAAK,KAAK,WAAW,UAAU;AAAA,EACjC;AAAA,EAEA,MAAc,WAAW,YAAmC;AAC1D,QAAI;AACF,YAAM,EAAE,YAAAA,YAAW,IAAI,KAAK,MAAM,KAAK;AACvC,YAAMA,YAAW,KAAK,QAAQ;AAC9B,YAAM,OAAO,MAAM,GAAG,KAAK,KAAK,QAAQ;AACxC,YAAM,UAAU,KAAK,MAAM,WAAW,QAAQ,MAAM,WAAW;AAC/D,UAAI,KAAK,QAAQ,SAAS;AACxB,cAAM,YAAY,KAAK,SAAS,YAAY,GAAG;AAC/C,cAAM,WAAW,KAAK,SAAS,UAAU,GAAG,SAAS;AACrD,cAAM,UAAU,KAAK,SAAS,UAAU,SAAS;AACjD,cAAM,GAAG;AAAA,UACP,KAAK;AAAA,UACL,GAAG,QAAQ,IAAI,WAAW,CAAC,CAAC,GAAG,OAAO;AAAA,QACxC;AAAA,MACF;AACA,YAAM,GAAG,WAAW,KAAK,UAAU,YAAY,MAAM;AACrD,YAAM,MAAM,KAAK,SAAS,SAAS,UAAU,KAAK,KAAK,SAAS,SAAS,YAAY,IAAI,WAAW;AACpG,YAAM,OAAO,WAAW,SAAS,aAAa,IAAI,QAAQ;AAC1D,WAAK,aAAa,KAAK,OAAO;AAAA,QAC5B,QAAQ,SAAS,QAAQ,QAAQ;AAAA,QACjC,SAAS;AAAA,MACX,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IAC1B,SAAS,KAAK;AACZ,cAAQ,MAAM,oBAAoB,GAAG;AAAA,IACvC;AAAA,EACF;AAAA;AAAA,EAGO,UAAgB;AACrB,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,MAAM;AAAA,EACb;AACF;AAMA,SAAS,QAAQ,OAAY,KAAa,QAA+B;AACvE,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,QAAI;AACF,YAAM,YAAY,GAAG,MAAM,MAAM,SAAS,IAAI,GAAG;AACjD,UAAI,YAAY,WAAW,IAAI,SAAS;AACxC,UAAI,CAAC,WAAW;AACd,oBAAY,IAAI,UAAU,OAAO,GAAG;AACpC,mBAAW,IAAI,WAAW,SAAS;AAAA,MACrC;AACA,gBAAU,IAAI,MAAM;AACpB,MAAAA,SAAQ;AAAA,IACV,SAAS,KAAK;AACZ,cAAQ,MAAM,GAAG;AACjB,aAAO,GAAG;AAAA,IACZ;AAAA,EACF,CAAC;AACH;AAhBS;AA8BT,IAAM,mBAAmB,oBAAI,IAAY;AAEzC,eAAe,gBAAgB,OAAY,UAAkB,SAA8B;AACzF,MAAI,iBAAiB,IAAI,QAAQ,EAAG;AACpC,MAAI;AACF,UAAM,OAAO,MAAM,GAAG,KAAK,QAAQ;AACnC,QAAI,KAAK,OAAO,GAAG;AACjB,uBAAiB,IAAI,QAAQ;AAC7B;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,QAAM,SAAS,gBAAgB;AAAA,IAC7B,UAAU,MAAM,WAAW,SAAS,SAAS;AAAA,IAC7C,SAAS,MAAM,WAAW,SAAS,OAAO;AAAA,IAC1C,QAAQ,CAAC,GAAG,iBAAiB;AAAA,IAC7B,MAAM;AAAA,EACR,CAAC;AACD,QAAM,GAAG,WAAW,UAAU,QAAQ,MAAM;AAC5C,mBAAiB,IAAI,QAAQ;AAC/B;AAnBe;AA+Bf,IAAM,cAAc,oBAAI,IAAyB;AAEjD,IAAM,wBAAwB;AAQ9B,eAAsB,UACpB,OACA,KACA,QACe;AACf,MAAI;AACF,UAAM,UAAU,MAAM,WAAW,QAAQ,MAAM,WAAW;AAC1D,QAAI,OAAO,YAAY,IAAI,GAAG;AAC9B,UAAM,MAAM,KAAK,IAAI;AAGrB,QACE,CAAC,QACD,CAAC,KAAK,WACN,MAAM,KAAK,cAAc,uBACzB;AACA,YAAM,EAAE,YAAAC,YAAW,IAAI,MAAM,KAAK;AAClC,YAAMA,YAAW,GAAG;AACpB,YAAM,OAAO,MAAM,GAAG,KAAK,GAAG;AAC9B,aAAO,EAAE,SAAS,MAAM,MAAM,KAAK,MAAM,YAAY,IAAI;AACzD,kBAAY,IAAI,KAAK,IAAI;AAAA,IAC3B;AAGA,QAAI,KAAK,QAAQ,SAAS;AACxB,YAAM,UAAe,oBAAI,KAAK;AAC9B,YAAM,YAAY,IAAI,YAAY,GAAG;AACrC,YAAM,WAAW,IAAI,UAAU,GAAG,SAAS;AAC3C,YAAM,UAAU,IAAI,UAAU,SAAS;AACvC,YAAM,GAAG,OAAO,KAAK,GAAG,QAAQ,IAAI,WAAW,GAAG,OAAO,CAAC,GAAG,OAAO,EAAE;AACtE,WAAK,UAAU;AACf,WAAK,OAAO;AAAA,IACd;AAGA,SAAK,QAAQ,OAAO,WAAW,MAAM;AACrC,UAAM,QAAQ,OAAO,KAAK,MAAM;AAAA,EAClC,SAAS,KAAK;AACZ,YAAQ,MAAM,GAAG;AAEjB,gBAAY,OAAO,GAAG;AAAA,EACxB;AACF;AA1CsB;AA6CtB,eAAsB,gBAAgB,OAAY,SAAiB,SAAgC;AACjG,QAAM,YAAY,MAAM,WAAW,QAAQ,MAAM;AACjD,MAAI,CAAC,UAAW;AAChB,QAAM,UAAU,oBAAI,KAAK;AACzB,QAAM,UAAU,WAAW,GAAG,OAAO;AACrC,QAAM,UAAU,GAAG,SAAS,cAAc,OAAO;AACjD,QAAM,UAAU,GAAG,SAAS,cAAc,OAAO;AAEjD,MAAI;AACF,UAAM,EAAE,YAAAA,YAAW,IAAI,MAAM,KAAK;AAClC,UAAMA,YAAW,OAAO;AACxB,UAAM,GAAG,WAAW,SAAS,SAAS,MAAM;AAC5C,UAAM,sBAAsB,OAAO,SAAS,OAAO;AACnD,UAAM,GAAG,WAAW,SAAS,SAAS,MAAM;AAC5C,UAAM,YAAY,SAAS,OAAO;AAClC,SAAK,gBAAgB,OAAO;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,MAAM,WAAW;AAAA,MACjB,QAAQ,WAAW;AAAA,MACnB,KAAK,WAAW;AAAA,MAChB,QAAQ,WAAW;AAAA,IACrB,CAAC,EAAE,MAAM,MAAM,MAAS;AACxB,SAAK,gBAAgB,OAAO;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,EAC1B,SAAS,KAAK;AACZ,YAAQ,MAAM,2BAA2B,GAAG;AAAA,EAC9C;AACF;AA9BsB;AAgCtB,IAAM,yBAAyB,oBAAI,IAAY;AAE/C,eAAe,sBAAsB,OAAY,UAAkB,SAA8B;AAC/F,MAAI,uBAAuB,IAAI,QAAQ,EAAG;AAC1C,MAAI;AACF,UAAM,OAAO,MAAM,GAAG,KAAK,QAAQ;AACnC,QAAI,KAAK,OAAO,GAAG;AACjB,6BAAuB,IAAI,QAAQ;AACnC;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,QAAM,SAAS,gBAAgB;AAAA,IAC7B,UAAU,MAAM,WAAW,SAAS,SAAS;AAAA,IAC7C,SAAS,MAAM,WAAW,SAAS,OAAO;AAAA,IAC1C,QAAQ,CAAC,GAAG,iBAAiB;AAAA,IAC7B,MAAM;AAAA,EACR,CAAC;AACD,QAAM,GAAG,WAAW,UAAU,QAAQ,MAAM;AAC5C,yBAAuB,IAAI,QAAQ;AACrC;AAnBe;AAwCR,SAAS,QAAQ,OAAkB;AAExC,WAAS,QAAQ,MAAmB;AAClC,QAAI,MAAM,WAAW,QAAQ,IAAI,MAAM;AACrC,cAAQ,IAAI,GAAG,IAAI;AAAA,IACrB;AAAA,EACF;AAJS;AAMT,WAAS,UAAU,MAAmB;AACpC,QAAI,gBAAgB,MAAO,QAAO,KAAK,WAAW,OAAO,IAAI;AAC7D,QAAI,OAAO,SAAS,UAAU;AAC5B,UAAI;AACF,eAAO,KAAK,UAAU,IAAI;AAAA,MAC5B,QAAQ;AACN,eAAO,OAAO,IAAI;AAAA,MACpB;AAAA,IACF;AACA,WAAO,OAAO,IAAI;AAAA,EACpB;AAVS;AAaT,WAAS,aAAa,MAAsB;AAC1C,UAAM,SAAS,MAAM,WAAW,QAAQ;AACxC,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,UAAM,UAAU,KAAK,KAAK,CAAC,MAAM,OAAO,MAAM,QAAQ;AACtD,QAAI,CAAC,WAAW,OAAO,OAAO,KAAK,KAAM,QAAO;AAChD,UAAM,OAAO,OAAO,OAAO,OAAO,CAAC;AACnC,QAAI,OAAO,MAAM,IAAI,KAAK,QAAQ,EAAG,QAAO;AAC5C,QAAI,QAAQ,EAAG,QAAO;AACtB,WAAO,KAAK,OAAO,IAAI;AAAA,EACzB;AATS;AAWT,WAAS,iBAAiB,SAAiB,QAA4B,KAAyB,SAAiB,SAAqB;AACpI,UAAM,WAAW,GAAG,MAAM,WAAW,OAAO,KAAK,MAAM,OAAO,WAAW,GAAG,OAAO,CAAC;AACpF,UAAM,SAAS,sBAAsB;AAAA,MACnC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,gBAAgB,OAAO,UAAU,OAAO;AAC9C,cAAM,QAAQ,OAAO,UAAU,MAAM;AAAA,MACvC,SAAS,KAAK;AACZ,gBAAQ,MAAM,sBAAsB,GAAG;AAAA,MACzC;AAAA,IACF,GAAG;AAAA,EACL;AAjBS;AAoBT,WAAS,QAAQ,MAAmB;AAClC,SAAK,GAAG,IAAI;AAAA,EACd;AAFS;AAKT,WAAS,QAAQ,MAAmB;AAClC,QAAI,CAAC,aAAa,IAAI,EAAG;AAEzB,UAAM,UAAU,oBAAI,KAAK;AACzB,UAAM,UAAU,KAAK,CAAC;AAEtB,QAAI,YAAY,GAAG;AACjB,UAAI,MAAM,WAAW,QAAQ,MAAM,QAAQ;AACzC,cAAM,SAAS,KAAK,MAAM,CAAC,EAAE,IAAI,SAAS,EAAE,KAAK,IAAI;AACrD,cAAM,SAAS,sBAAsB;AAAA,UACnC,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX,CAAC;AACD,aAAK,IAAI,WAAW,GAAG,OAAO,CAAC;AAAA,EAAM,MAAM;AAAA,CAAI;AAC/C,cAAM,WAAW,GAAG,MAAM,WAAW,OAAO,KAAK,MAAM,OAAO,WAAW,GAAG,OAAO,CAAC;AACpF,cAAM,YAAY;AAChB,cAAI;AACF,kBAAM,gBAAgB,OAAO,UAAU,OAAO;AAC9C,kBAAM,QAAQ,OAAO,UAAU,MAAM;AAAA,UACvC,SAAS,KAAK;AACZ,oBAAQ,MAAM,sBAAsB,GAAG;AAAA,UACzC;AAAA,QACF,GAAG;AAAA,MACL;AACA;AAAA,IACF;AAEA,UAAM,UAAU,OAAO,YAAY,WAAW,UAAU;AACxD,UAAM,WAAW,OAAO,YAAY,YAAY,UAAU,MAAM,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC;AAC5F,UAAM,UAAU,SAAS,IAAI,SAAS,EAAE,KAAK,IAAI,EAAE,QAAQ,WAAW,GAAG;AACzE,QAAI;AACJ,QAAI;AACJ,QAAI,OAAO,SAAS,CAAC,MAAM,YAAY,OAAO,SAAS,CAAC,MAAM,UAAU;AACtE,eAAS,SAAS,CAAC;AACnB,YAAM,SAAS,CAAC;AAAA,IAClB;AAEA,QAAI,OAAO,YAAY,YAAY,UAAU,KAAK;AAChD,UAAI,MAAM,WAAW,QAAQ,MAAM,QAAQ;AACzC,yBAAiB,SAAS,QAAQ,KAAK,SAAS,OAAO;AAAA,MACzD;AAAA,IACF,WAAW,MAAM,WAAW,QAAQ,MAAM,QAAQ;AAChD,YAAM,cAAc,IAAI,WAAW,GAAG,OAAO,CAAC,KAAK,OAAO;AAAA;AAC1D,WAAK,WAAW;AAChB,uBAAiB,SAAS,QAAQ,KAAK,SAAS,OAAO;AAAA,IACzD;AAAA,EACF;AA/CS;AAiDT,MACE,SACA,OAAO,UAAU,YACjB,MAAM,WAAW,QAAQ,IAAI,QAC7B;AACA,UAAM,OAAO;AAAA,EACf,OAAO;AACL,UAAM,OAAO;AAAA,EACf;AACF;AAnHgB;;;AC3ThB,IAAM,iBAAiB,oBAAI,IAAI,CAAC,UAAU,aAAa,CAAC;AAEjD,IAAM,eAAN,MAAmB;AAAA,EAAnB;AACN,SAAQ,SAAmB,CAAC;AAAA;AAAA,EAN7B,OAK0B;AAAA;AAAA;AAAA,EAGzB,QAAQ,MAAsB;AAC7B,SAAK,SAAS,KAAK,OAAO,CAAC,MAAM,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAAA,EACjG;AAAA,EAEA,QAAQ,IAA4C;AACnD,QAAI,CAAC,MAAM,OAAO,OAAO,SAAU,QAAO;AAC1C,eAAW,SAAS,KAAK,QAAQ;AAChC,UAAI,GAAG,WAAW,KAAK,EAAG,QAAO;AAAA,IAClC;AACA,WAAO;AAAA,EACR;AAAA,EAEA,YAAY,KAAiC;AAC5C,QAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,eAAW,SAAS,KAAK,QAAQ;AAChC,UAAI,IAAI,WAAW,KAAK,EAAG,QAAO;AAAA,IACnC;AACA,WAAO;AAAA,EACR;AACD;AAQO,SAAS,aAAa,KAAsB;AAClD,SAAO,CAAC,CAAC,OAAO,CAAC,eAAe,IAAI,GAAG;AACxC;AAFgB;;;AC5BT,SAAS,mBAAmB,OAA0B;AAC5D,MAAI,CAAC,MAAM,cAAc;AACxB,UAAM,eAAe,IAAI,aAAa;AAAA,EACvC;AACA,SAAO,MAAM;AACd;AALgB;AAOT,SAAS,iBAAiB,OAAkB;AAClD,QAAM,iBAAiB,OAAO,KAAK,MAAM,iBAAiB,CAAC,CAAC;AAC7D;AAFgB;AAIT,SAAS,gBAAgB,OAAkB;AACjD,QAAM,OAAO,OAAO,KAAK,MAAM,gBAAgB,CAAC,CAAC,EAAE,OAAO,YAAY;AACtE,QAAM,gBAAgB;AACtB,qBAAmB,KAAK,EAAE,QAAQ,IAAI;AACvC;AAJgB;AAOT,SAAS,YAAY,OAAY,KAAa,SAA6B;AACjF,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO,CAAC;AAC/B,MAAI,CAAC,MAAM,KAAK,IAAK,OAAM,KAAK,MAAM,CAAC;AACvC,QAAM,KAAK,IAAI,GAAG,IAAI;AACtB,MAAI,MAAM,eAAe;AACxB,UAAM,cAAc,GAAG,IAAI;AAC3B,qBAAiB,KAAK;AAAA,EACvB;AACD;AARgB;AAWT,SAAS,WAAW,OAAY,KAAa,SAA6B;AAChF,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO,CAAC;AAC/B,MAAI,CAAC,MAAM,KAAK,GAAI,OAAM,KAAK,KAAK,CAAC;AACrC,QAAM,KAAK,GAAG,GAAG,IAAI;AACrB,MAAI,MAAM,cAAc;AACvB,UAAM,aAAa,GAAG,IAAI;AAC1B,oBAAgB,KAAK;AAAA,EACtB;AACD;AARgB;AAWT,SAAS,kBAAkB,OAAY,QAAsC,CAAC,GAAS;AAC7F,QAAM,gBAAgB;AAAA,IACrB,GAAI,MAAM,MAAM,OAAO,CAAC;AAAA,IACxB,GAAG;AAAA,EACJ;AACA,mBAAiB,KAAK;AACvB;AANgB;AAST,SAAS,iBAAiB,OAAY,QAAsC,CAAC,GAAQ;AAC3F,QAAM,eAAe,MAAM,MAAM,WAAW,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC;AAC1E,QAAM,eAAe;AAAA,IACpB,GAAI,gBAAgB,CAAC;AAAA,IACrB,GAAI,MAAM,MAAM,MAAM,CAAC;AAAA,IACvB,GAAG;AAAA,EACJ;AACA,kBAAgB,KAAK;AACrB,SAAO;AACR;AATgB;AAYT,SAAS,eAAe,OAAkB;AAChD,QAAM,cAAc,CAAC,KAAa,YAA0B,YAAY,OAAO,KAAK,OAAO;AAC3F,QAAM,aAAa,CAAC,KAAa,YAA0B,WAAW,OAAO,KAAK,OAAO;AAC1F;AAHgB;;;AC9ChB,SAAS,eAAe,OAAqB;AAC5C,QAAM,MAAM,OAAO,YAAY;AAC/B,MAAI,OAAO,OAAO,IAAI,aAAa,SAAU,QAAO,IAAI,aAAa;AACrE,SAAO;AACR;AAJS;AAMF,SAAS,iBAAiB,OAAY,OAAiC;AAC7E,MAAI,CAAC,eAAe,KAAK,EAAG;AAC5B,QAAM,MAAK,oBAAI,KAAK,GAAE,YAAY;AAClC,QAAM,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM,UAAU;AAAA,IAChB,MAAM,QAAQ;AAAA,IACd,MAAM,OAAO,QAAQ,MAAM,IAAI,KAAK;AAAA,IACpC,MAAM,SAAS,OAAO,MAAM,MAAM,KAAK,KAAK;AAAA,IAC5C,MAAM,UAAU;AAAA,IAChB,MAAM,KAAK,MAAM,MAAM,EAAE,KAAK;AAAA,EAC/B,EAAE,OAAO,OAAO;AAChB,QAAM,OAAO,MAAM,KAAK,GAAG;AAC3B,GAAC,OAAO,QAAQ,QAAQ,MAAM,OAAO,IAAI;AAC1C;AAhBgB;AAkBT,SAAS,YAAY,KAAkB;AAC7C,QAAM,YAAY,KAAK,UAAU,iBAAiB;AAClD,MAAI,OAAO,cAAc,YAAY,UAAU,SAAS,GAAG;AAC1D,WAAO,UAAU,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK;AAAA,EACrC;AACA,SAAO,KAAK,QAAQ,iBAAiB;AACtC;AANgB;;;AC3CT,IAAM,sBAAsB,CAAC,eAAe,UAAU,UAAU,aAAa;AAE7E,SAAS,uBAAuB,OAAsB;AAC5D,QAAM,WAAqB,CAAC;AAC5B,QAAM,MAAM,OAAO,YAAY;AAC/B,QAAM,OAAO,OAAO,KAAK,aAAa,aAAa,EAAE,YAAY;AACjE,MAAI,CAAC,oBAAoB,SAAS,IAA4C,GAAG;AAChF,aAAS,KAAK,+CAAY,IAAI,oBAAU;AAAA,EACzC;AACA,MAAI,KAAK,aAAa,OAAO,IAAI,SAAS,IAAI,KAAK;AAClD,aAAS,KAAK,6CAAe,IAAI,SAAS,oCAAW;AAAA,EACtD;AACA,SAAO;AACR;AAXgB;;;ACFhB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAE1B,IAAM,gBAAgB,UAAU,QAAQ;AAExC,eAAsB,eAAe,cAAc,KAAmE;AACrH,MAAI,QAAQ,aAAa,SAAS;AACjC,QAAI;AACH,YAAM,EAAE,OAAO,IAAI,MAAM,cAAc,SAAS,CAAC,UAAU,SAAS,GAAG,EAAE,SAAS,IAAK,CAAC;AACxF,UAAI,sBAAsB,KAAK,MAAM,KAAK,UAAU,KAAK,MAAM,GAAG;AACjE,eAAO,EAAE,IAAI,MAAM,QAAQ,8BAA8B;AAAA,MAC1D;AACA,aAAO,EAAE,IAAI,OAAO,QAAQ,sCAAsC;AAAA,IACnE,QAAQ;AACP,aAAO,EAAE,IAAI,OAAO,QAAQ,oBAAoB;AAAA,IACjD;AAAA,EACD;AACA,MAAI;AACH,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,eAAe,CAAC,QAAQ,MAAM,mBAAmB,SAAS,GAAG,EAAE,SAAS,IAAK,CAAC;AACrH,QAAI,OAAO,KAAK,MAAM,MAAO,QAAO,EAAE,IAAI,MAAM,QAAQ,iCAAiC;AAAA,EAC1F,QAAQ;AAAA,EAER;AACA,MAAI;AACH,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,WAAW,CAAC,MAAM,cAAc,GAAG,EAAE,SAAS,IAAK,CAAC;AAC3F,UAAM,IAAI,OAAO,MAAM,4BAA4B;AACnD,QAAI,GAAG;AACN,YAAM,WAAW,KAAK,IAAI,WAAW,EAAE,CAAC,CAAC,IAAI,GAAI;AACjD,aAAO;AAAA,QACN,IAAI,YAAY;AAAA,QAChB;AAAA,QACA,QAAQ,kBAAkB,QAAQ;AAAA,MACnC;AAAA,IACD;AAAA,EACD,QAAQ;AAAA,EAER;AACA,SAAO,EAAE,IAAI,OAAO,QAAQ,6CAA6C;AAC1E;AAjCsB;;;ACLtB,SAAS,kBAAkB;AAC3B,OAAOC,SAAQ;AACf,OAAO,UAAU;AAEV,SAAS,kBAAkB,YAAmC;AACpE,MAAI;AACH,UAAM,MAAMC,IAAG,aAAa,UAAU;AACtC,WAAO,WAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK;AAAA,EACrD,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAPgB;AAST,SAAS,qBAAqB,YAAqD;AACzF,QAAM,aAAa,KAAK,KAAK,YAAY,0BAA0B;AACnE,QAAM,eAAe,KAAK,KAAK,YAAY,mCAAmC;AAC9E,MAAI,CAACA,IAAG,WAAW,YAAY,GAAG;AACjC,WAAO,EAAE,IAAI,MAAM,QAAQ,yBAAyB;AAAA,EACrD;AACA,MAAI;AACH,UAAM,WAAW,KAAK,MAAMA,IAAG,aAAa,cAAc,MAAM,CAAC;AACjE,UAAM,WAAW,OAAO,SAAS,UAAU,EAAE;AAC7C,UAAM,SAAS,kBAAkB,UAAU;AAC3C,QAAI,CAAC,OAAQ,QAAO,EAAE,IAAI,OAAO,QAAQ,yBAAyB;AAClE,QAAI,YAAY,aAAa,QAAQ;AACpC,aAAO,EAAE,IAAI,OAAO,QAAQ,8BAA8B;AAAA,IAC3D;AACA,WAAO,EAAE,IAAI,MAAM,QAAQ,oBAAoB;AAAA,EAChD,SAAS,GAAQ;AAChB,WAAO,EAAE,IAAI,OAAO,QAAQ,GAAG,WAAW,uBAAuB;AAAA,EAClE;AACD;AAlBgB;;;ACJT,SAAS,aAAa,OAAY,MAAiB;AACzD,MAAI,CAAC,MAAM,YAAY,IAAI;AAC1B,UAAM,WAAW,KAAK,MAAM;AAAA,EAC7B;AACA,QAAM,YAAY,CAAC,KAAa,WAAmB,UAAU,OAAO,KAAK,MAAM;AAC/E,QAAM,kBAAkB,CAAC,SAAiB,YAAoB,gBAAgB,OAAO,SAAS,OAAO;AACrG,QAAM,UAAU,CAAC,YAAoB,WAAW,SAAS,KAAK;AAC9D,QAAM,YAAY,CAAC,OAAuB,UAAU,IAAI,KAAK;AAC7D,QAAM,mBAAmB,MAAM,iBAAiB,KAAK;AACrD,iBAAe,KAAK;AAEpB,cAAY,KAAK;AACjB,UAAQ,KAAK;AAEb,QAAM,WAAW,WAAW,CAAC;AAC7B,QAAM,WAAW,UAAU;AAE3B,MAAI,MAAM,YAAY,KAAK,MAAM,CAAC,MAAM,MAAM,UAAU,OAAO,MAAM,MAAM,UAAU,YAAY;AAChG,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,KAAK,MAAM,KAAK;AACjD,UAAM,KAAK,SAAS;AAAA,MACnB,QAAQ,MAAM,WAAW,IAAI,KAAK;AAAA,MAClC;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,MAAI,qBAAqB,MAAM,YAAY,YAAY,EAAE,GAAG;AAC3D,qBAAiB,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,QAAQ;AAAA,IACT,CAAC;AACD,SAAK,OAAO,qCAA4C,EAAE;AAAA,MAAK,CAAC,EAAE,+BAAAC,+BAA8B,MAC/FA,+BAA8B,OAAO;AAAA,QACpC,SAAS;AAAA,QACT,QAAQ;AAAA,MACT,CAAC;AAAA,IACF,EAAE,MAAM,MAAM,MAAS;AAAA,EACxB;AAEA,6BAA2B,KAAK;AAEhC,aAAW,KAAK,uBAAuB,KAAK,GAAG;AAC9C,qBAAiB,OAAO,EAAE,MAAM,eAAe,QAAQ,EAAE,CAAC;AAAA,EAC3D;AACA,QAAM,OAAO,MAAM,cAAc,QAAQ,IAAI;AAC7C,QAAM,WAAW,qBAAqB,IAAI;AAC1C,MAAI,CAAC,SAAS,IAAI;AACjB,qBAAiB,OAAO,EAAE,MAAM,eAAe,QAAQ,qBAAqB,SAAS,MAAM,GAAG,CAAC;AAAA,EAChG;AACA,OAAK,eAAe,EAAE,KAAK,CAAC,QAAQ;AACnC,QAAI,CAAC,IAAI,GAAI,kBAAiB,OAAO,EAAE,MAAM,eAAe,QAAQ,QAAQ,IAAI,MAAM,GAAG,CAAC;AAAA,EAC3F,CAAC;AACF;AApDgB;AAuDhB,SAAS,2BAA2B,OAAkB;AACrD,QAAM,QAAQ,OAAO,OAAO,YAAY,QAAQ,uBAAuB,KAAK;AAC5E,MAAI,SAAS,EAAG;AAChB,QAAM,KAAK,QAAQ,OAAO;AAC1B,cAAY,MAAM;AACjB,SAAK,OAAO,2BAAkC,EAAE;AAAA,MAAK,CAAC,EAAE,qBAAAC,qBAAoB,MAC3EA,qBAAoB,OAAO,MAAM;AAAA,IAClC,EAAE,MAAM,MAAM,MAAS;AAAA,EACxB,GAAG,EAAE;AACN;AATS;;;AC1DT,YAAY,UAAU;AACtB,YAAY,WAAW;;;ACTvB,SAAS,uBAAkC;;;ACA3C,SAAS,iBAAiB;;;ACAnB,SAAS,mBAAmB,UAAuC,OAA6B;AACtG,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,GAAG;AACpD,WAAO;AAAA,EACR;AACA,MAAI,SAAS,CAAC,GAAG;AAChB,UAAM,KAAK,OAAO,YAAY;AAC9B,QAAI,CAAC,IAAI;AACR,YAAM,KAAK,QAAQ,oDAAoD;AACvE,aAAO;AAAA,IACR;AACA,QAAI;AACH,eAAS,CAAC,IAAI,MAAM,KAAK,OAAO,SAAS,SAAS,CAAC,GAAG,EAAE;AACxD,eAAS,CAAC,IAAI,MAAM,KAAK,OAAO,SAAS,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;AACjE,eAAS,CAAC,IAAI,MAAM,KAAK,OAAO,SAAS,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;AAAA,IAClE,SAAS,KAAK;AACb,YAAM,KAAK,QAAQ,2BAA2B,GAAG;AAAA,IAClD;AAAA,EACD;AACA,SAAO;AACR;AAnBgB;;;ADGT,SAAS,cAAc,KAAU,OAAiB;AACxD,MAAI;AACH,UAAM,MAAM,IAAI,UAAU,wBAAwB;AAClD,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,mBAAmB,IAAI,MAAM,IAAI,GAAG,KAAK;AAAA,EACjD,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AARgB;AAWT,SAAS,iBAAiB,OAAY,IAAY,SAA2B;AACnF,MAAI,CAAC,MAAM,OAAO,OAAQ,QAAO;AACjC,QAAM,MAAM,MAAM,iBAAiB,CAAC;AACpC,QAAM,OAAO,UAAU,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG;AAClD,aAAW,OAAO,MAAM;AACvB,QAAI,IAAI,GAAG,IAAI,EAAE,EAAG,QAAO;AAAA,EAC5B;AACA,SAAO;AACR;AARgB;AAWhB,SAAS,gBAAgBC,KAAkB;AAC1C,MAAI,CAACA,IAAI,QAAO;AAChB,QAAM,QAAQA,IAAG;AACjB,SAAO,UAAU,UAAU,cAAc,UAAU,UAAU;AAC9D;AAJS;AAOT,SAAS,iBAAiBA,KAAS,IAAmC;AACrE,QAAM,UAAU,KAAK,UAAU,EAAE,IAAI,eAAe,IAAI,EAAE,MAAM,GAAG,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;AACzF,MAAI;AACH,IAAAA,IAAG,KAAK,SAAS,MAAM;AACtB,UAAI;AACH,QAAAA,IAAG,MAAM;AAAA,MACV,QAAQ;AAAA,MAER;AAAA,IACD,CAAC;AAAA,EACF,QAAQ;AACP,QAAI;AACH,MAAAA,IAAG,MAAM;AAAA,IACV,QAAQ;AAAA,IAER;AAAA,EACD;AACD;AAjBS;AAmBF,SAAS,OAAO,OAAY,SAAiBA,KAAS,MAAW,SAAuB;AAC9F,QAAM,CAAC,IAAI,EAAE,EAAE,IAAIA,IAAG,YAAY,CAAC;AAEnC,MAAI,CAAC,IAAI;AACR,IAAAA,IAAG,MAAM;AACT,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,UAAU,MAAM,cAAc,OAAO,IAAI,EAAE,GAAG;AACxD,UAAM,aAAa,MAAM,cAAc,OAAO,EAAE,EAAE;AAClD,QAAI,YAAY,WAAW,CAAC,MAAM,IAAI;AAErC,UAAI,gBAAgB,UAAU,GAAG;AAChC,yBAAiBA,KAAI;AAAA,UACpB,MAAM;AAAA,UACN,QAAQ,GAAG,EAAE;AAAA,UACb,KAAK,GAAG,EAAE;AAAA,QACX,CAAC;AACD,eAAO;AAAA,MACR;AACA,UAAI;AACH,mBAAW,MAAM;AAAA,MAClB,QAAQ;AAAA,MAER;AACA,aAAO,MAAM,cAAc,OAAO,EAAE,EAAE;AACtC,aAAO;AAAA,IACR;AAEA,qBAAiBA,KAAI;AAAA,MACpB,MAAM;AAAA,MACN,QAAQ,GAAG,EAAE;AAAA,MACb,KAAK,GAAG,EAAE;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,QAAQ;AAClB,UAAM,cAAc,MAAM,cAAc,OAAO,KAAK,CAAC;AAErD,UAAM,WAAgB,OAAO,OAAO,WAAW,EAAE;AAAA,MAChD,CAAC,SAAc,KAAK,WAAW,CAAC,MAAM,MAAM,KAAK,WAAW,CAAC,MAAM;AAAA,IACpE;AACA,UAAM,YAAY,QAAQ,aAAa;AAEvC,QAAI,UAAU;AACb,uBAAiBA,KAAI;AAAA,QACpB,MAAM;AAAA,QACN,QAAQ,GAAG,EAAE,IAAI,SAAS,SAAS,CAAC,CAAC;AAAA,QACrC,KAAK,GAAG,EAAE,IAAI,SAAS,SAAS,CAAC,CAAC;AAAA,MACnC,CAAC;AACD,aAAO;AAAA,IACR;AACA,QAAI,OAAO,KAAK,WAAW,EAAE,UAAU,WAAW;AACjD,uBAAiBA,KAAI;AAAA,QACpB,MAAM;AAAA,QACN,QAAQ,GAAG,SAAS;AAAA,QACpB,KAAK,OAAO,SAAS;AAAA,MACtB,CAAC;AACD,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AAhEgB;AAkET,SAAS,QACf,OAAY,SAAiBA,KAAS,KAAU,SAChD,eAAqC,cAC9B;AACP,QAAM,CAAC,EAAE,IAAIA,IAAG,YAAY,CAAC;AAC7B,MAAI,QAAQ,QAAQ,IAAI;AACvB,QAAI,CAACA,IAAG,QAAS,CAAAA,IAAG,UAAU,CAAC;AAC/B,UAAM,cAAc,OAAO,EAAE,EAAE,IAAIA;AAAA,EACpC;AAEA,EAAAA,IAAG,GAAG,WAAW,CAAC,QAAgB;AACjC,QAAI,aAAc,OAAM,KAAK,MAAM,WAAW,IAAI,SAAS,CAAC;AAC5D,oBAAgB,KAAKA,KAAI,SAAS,GAAG;AAAA,EACtC,CAAC;AAED,EAAAA,IAAG,GAAG,SAAS,MAAM;AACpB,QAAI,QAAQ,MAAM;AACjB,UAAIA,IAAG,SAAS;AACf,eAAO,OAAOA,IAAG,OAAO,EAAE,QAAQ,CAAC,OAAY,MAAM,cAAc,EAAE,CAAC;AACtE,QAAAA,IAAG,UAAU;AAAA,MACd;AAGA,UAAI,MAAM,MAAM,cAAc,OAAO,IAAI,EAAE,MAAMA,IAAI,QAAO,MAAM,cAAc,OAAO,EAAE,EAAE;AAAA,IAC5F;AACA,QAAIA,IAAG,eAAe,UAAU,UAAUA,IAAG,eAAe,UAAU,QAAS,CAAAA,IAAG,MAAM;AAAA,EACzF,CAAC;AACF;AA3BgB;;;AErHhB,SAAS,aAAAC,kBAAiB;AAEnB,SAAS,mBAAmB,OAAY,SAAuB;AACrE,QAAM,QAAQ,MAAM,QAAQ,OAAO;AACnC,MAAI,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,OAAO,KAAK,EAAE,QAAQ,CAAC,OAAY;AACzC,UAAI,GAAI,eAAc,EAAoB;AAAA,IAC3C,CAAC;AACD,UAAM,QAAQ,OAAO,IAAI,CAAC;AAAA,EAC3B;AACD;AARgB;AAWT,SAAS,SAAS,KAAU,OAAiB;AACnD,MAAI,QAAQ,UAAU,QAAQ,OAAQ,QAAO;AAC7C,MAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM,QAAO;AACpD,OAAK,KAAK,OAAO,MAAM,KAAK,QAAQ,WAAW,KAAK,MAAM,MAAM,MAAM,QAAQ,QAAQ;AACrF,QAAI,KAAK,MAAM,KAAK,OAAO,OAAO,IAAI,EAAE;AAAA,EACzC;AACA,SAAO,KAAK,UAAU,GAAG;AAC1B;AAPgB;AAST,SAAS,iBAAiB,KAAU,OAAkB;AAC5D,MAAI,SAAS,CAAC,KAAU,MAAc,UAAe;AACpD,UAAM,OAAO,SAAS,KAAK,KAAK;AAChC,QAAI,MAAM;AACT,UAAI,QAAQ,QAAQ,CAAC,WAAgB;AACpC,aAAK,SAAS,KAAK,WAAW,UAAU,OAAO,eAAeC,WAAU,MAAM;AAC7E,iBAAO,KAAK,IAAI;AAAA,QACjB;AAAA,MACD,CAAC;AAAA,IACF,OAAO;AACN,YAAM,KAAK,IAAI;AAAA,IAChB;AAAA,EACD;AACA,MAAI,UAAU,CAAC,QAAa;AAC3B,UAAM,OAAO,SAAS,KAAK,KAAK;AAChC,QAAI,QAAQ,QAAQ,CAAC,WAAgB;AACpC,UAAI,QAAQ,eAAeA,WAAU,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5D,CAAC;AAAA,EACF;AACD;AAnBgB;;;ACnBhB,SAAS,aAAa,eAAe;AAMrC,IAAM,YAAY,oBAAI,IAAoB;AAC1C,IAAM,WAAW,oBAAI,IAAqB;AAC1C,IAAM,eAAe,oBAAI,IAAqB;AAC9C,IAAM,UAAU,oBAAI,IAAqB;AAEzC,SAAS,SAAS,OAAY;AAC7B,SAAO,OAAO,YAAY,UAAU,SAAS,CAAC;AAC/C;AAFS;AAIT,SAAS,UAAU,OAAqB;AACvC,QAAM,IAAI,SAAS,KAAK;AACxB,SAAO,EAAE,YAAY,KAAK,EAAE,YAAY;AACzC;AAHS;AAKT,SAAS,QAAQ,SAAyB;AACzC,SAAO,WAAW;AACnB;AAFS;AAIF,SAAS,eAAe,OAAY,SAAiB,IAA8D;AACzH,MAAI,CAAC,UAAU,KAAK,EAAG,QAAO,EAAE,IAAI,KAAK;AACzC,QAAM,IAAI,SAAS,KAAK;AACxB,QAAM,KAAK,QAAQ,OAAO;AAE1B,QAAM,YAAY,EAAE,oBAAoB;AACxC,QAAM,YAAY,UAAU,IAAI,EAAE,KAAK;AACvC,MAAI,aAAa,WAAW;AAC3B,qBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,QAAQ,QAAQ,oBAAoB,GAAG,CAAC;AAC5F,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,qBAAqB;AAAA,EAC9D;AAEA,QAAM,WAAW,EAAE,eAAe;AAClC,QAAM,QAAQ,SAAS,IAAI,EAAE,KAAK,oBAAI,IAAI;AAC1C,QAAM,QAAQ,MAAM,IAAI,EAAE,KAAK;AAC/B,MAAI,SAAS,UAAU;AACtB,qBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,QAAQ,QAAQ,eAAe,GAAG,CAAC;AACvF,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,oBAAoB;AAAA,EAC7D;AAEA,QAAM,YAAY,EAAE,qBAAqB;AACzC,QAAM,MAAM,KAAK,IAAI;AACrB,MAAI,WAAW,aAAa,IAAI,EAAE;AAClC,MAAI,CAAC,UAAU;AACd,eAAW,oBAAI,IAAI;AACnB,iBAAa,IAAI,IAAI,QAAQ;AAAA,EAC9B;AACA,MAAI,SAAS,SAAS,IAAI,EAAE;AAC5B,MAAI,CAAC,UAAU,OAAO,UAAU,KAAK;AACpC,aAAS,EAAE,OAAO,GAAG,SAAS,MAAM,IAAM;AAC1C,aAAS,IAAI,IAAI,MAAM;AAAA,EACxB;AACA,SAAO,SAAS;AAChB,MAAI,OAAO,QAAQ,WAAW;AAC7B,qBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,QAAQ,QAAQ,qBAAqB,GAAG,CAAC;AAC7F,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,sBAAsB;AAAA,EAC/D;AAEA,YAAU,IAAI,IAAI,YAAY,CAAC;AAC/B,QAAM,IAAI,IAAI,QAAQ,CAAC;AACvB,WAAS,IAAI,IAAI,KAAK;AACtB,SAAO,EAAE,IAAI,KAAK;AACnB;AA1CgB;AA4CT,SAAS,eAAe,SAAiB,IAAkB;AACjE,QAAM,KAAK,QAAQ,OAAO;AAC1B,QAAM,IAAI,UAAU,IAAI,EAAE,KAAK;AAC/B,MAAI,IAAI,EAAG,WAAU,IAAI,IAAI,IAAI,CAAC;AAClC,QAAM,QAAQ,SAAS,IAAI,EAAE;AAC7B,MAAI,OAAO;AACV,UAAM,IAAI,MAAM,IAAI,EAAE,KAAK;AAC3B,QAAI,IAAI,EAAG,OAAM,IAAI,IAAI,IAAI,CAAC;AAAA,EAC/B;AACD;AATgB;AAWT,SAAS,cAAc,OAAY,SAAiB,IAAqB;AAC/E,MAAI,CAAC,UAAU,KAAK,EAAG,QAAO;AAC9B,QAAM,WAAW,SAAS,KAAK,EAAE,cAAc;AAC/C,QAAM,KAAK,QAAQ,OAAO;AAC1B,QAAM,QAAQ,QAAQ,IAAI,EAAE,KAAK,oBAAI,IAAI;AACzC,QAAM,MAAM,MAAM,IAAI,EAAE,KAAK;AAC7B,MAAI,OAAO,UAAU;AACpB,qBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,OAAO,QAAQ,cAAc,GAAG,CAAC;AACrF,WAAO;AAAA,EACR;AACA,QAAM,IAAI,IAAI,MAAM,CAAC;AACrB,UAAQ,IAAI,IAAI,KAAK;AACrB,SAAO;AACR;AAbgB;AAeT,SAAS,cAAc,SAAiB,IAAkB;AAChE,QAAM,KAAK,QAAQ,OAAO;AAC1B,QAAM,QAAQ,QAAQ,IAAI,EAAE;AAC5B,MAAI,CAAC,MAAO;AACZ,QAAM,IAAI,MAAM,IAAI,EAAE,KAAK;AAC3B,MAAI,IAAI,EAAG,OAAM,IAAI,IAAI,IAAI,CAAC;AAC/B;AANgB;AAST,SAAS,qBAAqB,OAAY,SAAsB;AACtE,QAAM,IAAI,SAAS,KAAK;AACxB,QAAM,YAAY,OAAO,EAAE,iBAAiB;AAC5C,MAAI,YAAY,EAAG,QAAO;AAC1B,SAAO,OAAO,SAAS,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,IAAI;AAC7D;AALgB;AAUT,SAAS,yBACf,KACA,UACA,OACA,SACA,SACA,UACS;AACT,QAAM,CAAC,IAAI,EAAE,EAAE,IAAK,YAAY,CAAC;AACjC,MAAI,QAAQ;AACZ,aAAW,UAAU,IAAI,SAAS;AACjC,QAAI,WAAW,SAAU;AACzB,QAAI,OAAO,eAAe,QAAQ,UAAU,OAAO,eAAe,QAAQ,QAAS;AACnF,UAAM,QAAS,OAAgD;AAC/D,UAAM,MAAM,QAAQ,CAAC;AACrB,UAAM,MAAM,QAAQ,CAAC;AAErB,QAAI,MAAM,MAAM,QAAQ,MAAM,QAAQ,GAAI;AAC1C,QAAI,SAAS,QAAQ,MAAM,IAAI;AAC9B,YAAM,WAAW,OAAO,gBAAgB,OAAO,IAAI,EAAE;AACrD,UAAI,aAAa,UAAU,UAAU,WAAW,CAAC,MAAM,GAAI;AAAA,IAC5D;AACA,aAAS;AAAA,EACV;AACA,SAAO;AACR;AAzBgB;;;AJzGT,SAAS,aAAa,OAAY,SAAuB;AAC/D,QAAM,UAAU,WAAW,SAAS,KAAK;AACzC,QAAM,gBAAgB,eAAe,QAAQ;AAC7C,QAAM,eAAe,CAAC,CAAC,MAAM,WAAW,QAAQ,IAAI;AAEpD,MAAI;AACH,QAAI,MAAM,UAAU,OAAO,EAAG;AAE9B,QAAI,QAAQ,QAAQ,CAAC,MAAM,cAAc,OAAO,GAAG;AAClD,YAAM,cAAc,OAAO,IAAI,CAAC;AAAA,IACjC;AACA,QAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,OAAM,QAAQ,OAAO,IAAI,CAAC;AAEvD,UAAM,MAAM,IAAI,gBAAgB,EAAE,QAAQ,MAAM,YAAY,OAAO,GAAG,mBAAmB,MAAM,CAAC;AAChG,qBAAiB,KAAK,KAAK;AAE3B,QAAI,GAAG,SAAS,CAAC,QAAe;AAC/B,yBAAmB,OAAO,OAAO;AACjC,YAAM,KAAK,MAAM,uBAAuB,GAAG;AAC3C,UAAI,QAAQ,MAAM;AACjB,cAAM,KAAK,MAAM,qBAAqB;AACtC,eAAO,MAAM,UAAU,OAAO;AAAA,MAC/B,CAAC;AAAA,IACF,CAAC;AAED,QAAI,GAAG,SAAS,CAAC,MAAc,WAAmB;AACjD,UAAI;AACH,cAAM,KAAK,MAAM,4BAA4B,OAAO,WAAW,IAAI,aAAa,QAAQ,SAAS,CAAC,EAAE;AACpG,2BAAmB,OAAO,OAAO;AAAA,MAClC,SAAS,KAAK;AACb,cAAM,KAAK,MAAM,2BAA2B,GAAG;AAAA,MAChD;AAAA,IACD,CAAC;AAED,QAAI,GAAG,cAAc,CAACC,KAAS,QAAa;AAC3C,YAAM,WAAW,YAAY,GAAG;AAChC,UAAI,CAAC,cAAc,OAAO,SAAS,QAAQ,GAAG;AAC7C,cAAM,QAAQ,KAAK,UAAU;AAAA,UAC5B,IAAI;AAAA,UACJ,IAAI,EAAE,MAAM,GAAG,MAAM,OAAO,MAAM,SAAS,QAAQ,MAAM,KAAK,uBAAuB;AAAA,QACtF,CAAC;AACD,QAAAA,IAAG,KAAK,OAAO,MAAMA,IAAG,MAAM,MAAM,aAAa,CAAC;AAClD;AAAA,MACD;AACA,MAAAA,IAAG,KAAK,SAAS,MAAM,cAAc,SAAS,QAAQ,CAAC;AAEvD,UAAI,WAAW,cAAc,KAAK,KAAK,KAAK,CAAC;AAC7C,MAAAA,IAAG,WAAW,IAAI;AAElB,YAAM,QAAQ,qBAAqB,OAAO,OAAO;AACjD,YAAM,uBAAuB,yBAAyB,KAAKA,KAAI,OAAO,SAAS,SAAS,IAAI,QAAQ;AAEpG,UAAI,wBAAwB,OAAO;AAClC,cAAM,KAAK,MAAM,+BAA+B,oBAAoB,IAAI,KAAK,GAAG;AAChF,yBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,OAAO,QAAQ,qBAAqB,IAAI,SAAS,CAAC;AACtG,cAAM,QAAQ,KAAK,UAAU;AAAA,UAC5B,IAAI;AAAA,UACJ,IAAI,EAAE,MAAM,GAAG,MAAM,OAAO,MAAM,SAAS,QAAQ,GAAG,KAAK,IAAI,KAAK,oBAAoB,KAAK,YAAY;AAAA,QAC1G,CAAC;AACD,QAAAA,IAAG,KAAK,OAAO,MAAMA,IAAG,MAAM,MAAM,aAAa,CAAC;AAClD;AAAA,MACD;AAEA,YAAM,SAAS,CAAC,QAAQ,QAAQ,OAAO,OAAO,SAASA,KAAI,KAAK,OAAO;AACvE,UAAI,QAAQ;AACX,gBAAQ,OAAO,SAASA,KAAI,KAAK,SAAS,eAAe,YAAY;AAAA,MACtE,OAAO;AACN,QAAAA,IAAG,MAAM;AAAA,MACV;AAAA,IACD,CAAC;AAED,UAAM,UAAU,OAAO,IAAI;AAAA,EAC5B,SAAS,KAAK;AACb,UAAM,KAAK,MAAM,cAAc,KAAK,UAAU,GAAG,CAAC;AAAA,EACnD;AACD;AA3EgB;;;AKThB,YAAYC,SAAQ;AASb,IAAM,kBAAN,MAAsB;AAAA,EAG5B,YACkB,UAAU,KACV,gBAAgB,KAChC;AAFgB;AACA;AAJlB,SAAQ,QAAQ,oBAAI,IAAwB;AAAA,EAKzC;AAAA,EAlBJ,OAY6B;AAAA;AAAA;AAAA,EAQpB,MAAM,KAAa,OAAyB;AACnD,QAAI,KAAK,MAAM,IAAI,GAAG,EAAG,MAAK,MAAM,OAAO,GAAG;AAC9C,SAAK,MAAM,IAAI,KAAK,KAAK;AACzB,WAAO,KAAK,MAAM,OAAO,KAAK,SAAS;AACtC,YAAM,SAAS,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AACxC,UAAI,CAAC,OAAQ;AACb,WAAK,MAAM,OAAO,MAAM;AAAA,IACzB;AAAA,EACD;AAAA,EAEA,IAAI,KAAgC;AACnC,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,MAAM,SAAS,KAAK,IAAI,IAAI,MAAM,WAAW,KAAK,eAAe;AACpE,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACR;AACA,SAAK,MAAM,OAAO,GAAG;AACrB,SAAK,MAAM,IAAI,KAAK,KAAK;AACzB,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,KAAa,UAAkB,SAAuB;AAC5D,SAAK,MAAM,KAAK,EAAE,UAAU,SAAS,UAAU,KAAK,IAAI,EAAE,CAAC;AAAA,EAC5D;AAAA,EAEA,QAAQ,KAAmB;AAC1B,SAAK,MAAM,KAAK,EAAE,UAAU,IAAI,SAAS,GAAG,OAAO,MAAM,UAAU,KAAK,IAAI,EAAE,CAAC;AAAA,EAChF;AAAA,EAEA,OAAO,OAAoC;AAC1C,QAAI,MAAM,SAAS,CAAC,MAAM,SAAU,QAAO;AAC3C,QAAI;AACH,YAAM,OAAU,aAAS,MAAM,QAAQ;AACvC,UAAI,CAAC,KAAK,OAAO,KAAK,KAAK,YAAY,MAAM,QAAS,QAAO;AAC7D,aAAO;AAAA,IACR,QAAQ;AACP,aAAO;AAAA,IACR;AAAA,EACD;AACD;;;ACtDA,IAAM,cACL;AAEM,SAAS,qBAAqB,KAAU,UAAU,OAAO,YAAwB;AACvF,MAAI,UAAU,0BAA0B,SAAS;AACjD,MAAI,UAAU,mBAAmB,YAAY;AAC7C,MAAI,UAAU,mBAAmB,iCAAiC;AAClE,MAAI,UAAU,sBAAsB,0CAA0C;AAC9E,MAAI,UAAU,oBAAoB,GAAG;AACrC,MAAI,UAAU,8BAA8B,aAAa;AACzD,MAAI,UAAU,gCAAgC,aAAa;AAC3D,MAAI,SAAS;AACZ,QAAI,UAAU,6BAA6B,qCAAqC;AAAA,EACjF;AACA,QAAM,MAAM,YAAY;AACxB,MAAI,KAAK,KAAK;AACb,UAAM,MAAM,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,SAAS,IAAI,IAAI,YAAY;AAC5F,QAAI,UAAU,2BAA2B,GAAG;AAAA,EAC7C;AACD;AAhBgB;AAkBT,SAAS,gBAAgB,KAAU,OAAiB;AAC1D,MAAI;AACH,UAAM,WAAW,IAAI,UAAU,UAAU,GAAG,MAAM,IAAI;AACtD,WAAO,mBAAmB,UAAU,KAAK;AAAA,EAC1C,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAPgB;AAST,SAAS,gBAAgB,KAAU,OAAqB;AAC9D,MAAI,WAAW,gBAAgB,KAAK,KAAK;AACzC,SAAO;AACR;AAHgB;;;AC9BT,SAAS,gBAAgB,KAAsB;AACrD,SAAO,eAAe,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO,KAAK,OAAO,GAAG;AACzE;AAFgB;AAIT,SAAS,iBAAiB,QAAqC;AACrE,SAAO,WAAW;AACnB;AAFgB;AAIT,SAAS,qBAAqB,KAAiC;AACrE,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,IAAI,IAAI,QAAQ,GAAG;AACzB,QAAM,IAAI,IAAI,QAAQ,GAAG;AACzB,MAAI,MAAM,IAAI;AACd,MAAI,KAAK,EAAG,OAAM,KAAK,IAAI,KAAK,CAAC;AACjC,MAAI,KAAK,EAAG,OAAM,KAAK,IAAI,KAAK,CAAC;AACjC,SAAO,IAAI,MAAM,GAAG,GAAG;AACxB;AARgB;AAaT,SAAS,kBAAkB,OAAyB;AAC1D,QAAM,OAAO,MAAM,YAAY,QAAQ;AACvC,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,EAAG,QAAO,MAAM;AAE5D,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,WAAqB,CAAC;AAC5B,aAAW,QAAQ,MAAM;AACxB,QAAI,OAAO,SAAS,YAAY,CAAC,KAAM;AACvC,QAAI,KAAK,SAAS,GAAG,EAAG,UAAS,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,QAClD,OAAM,IAAI,IAAI;AAAA,EACpB;AACA,MAAI,MAAM,SAAS,KAAK,SAAS,WAAW,EAAG,QAAO,MAAM;AAE5D,SAAO,CAAC,QAA4B;AACnC,UAAMC,QAAO,qBAAqB,GAAG;AACrC,QAAI,CAACA,MAAM,QAAO;AAClB,QAAI,MAAM,IAAIA,KAAI,EAAG,QAAO;AAC5B,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACzC,UAAIA,MAAK,WAAW,SAAS,CAAC,CAAC,EAAG,QAAO;AAAA,IAC1C;AACA,WAAO;AAAA,EACR;AACD;AAtBgB;AAwBT,SAAS,QACf,OACA,MACA,QACA,KACA,aACA,KACA,KACO;AACP,MAAI,CAAC,iBAAiB,MAAM,KAAK,YAAY,GAAG,EAAG;AACnD,QAAM,KAAK,MAAM,QAAQ,GAAG;AAC5B,MAAI,OAAO,OAAO,OAAO,MAAM,oBAAoB,YAAY;AAC9D,oBAAgB,OAAO,KAAK,KAAK,IAAI;AAAA,EACtC;AACD;AAdgB;AAiBT,SAAS,gBAAgB,OAAY,KAAU,KAAU,SAAuB;AACtF,MAAI,IAAI,mBAAoB;AAC5B,MAAI,qBAAqB;AACzB,QAAM,WAAW,6BAAM;AACtB,QAAI;AACH,YAAM,QAAQ,iBAAiB,KAAK,KAAK,OAAO;AAChD,WAAK,MAAM,gBAAgB,UAAU,KAAK,GAAG,sBAAsB,KAAK,CAAC;AAAA,IAC1E,QAAQ;AAAA,IAER;AAAA,EACD,GAPiB;AAQjB,MAAI,IAAI,iBAAiB,IAAI,SAAU,UAAS;AAAA,MAC3C,KAAI,KAAK,UAAU,QAAQ;AACjC;AAbgB;;;ACjEhB,YAAYC,SAAQ;AACpB,YAAYC,eAAc;;;ACD1B,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AAEf,SAAS,sBAAsB,eAAuB,cAAgC;AAC5F,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACxD,UAAM,IAAI,MAAM,cAAc;AAAA,EAC/B;AACA,MAAI,cAAc,SAAS,IAAI,GAAG;AACjC,UAAM,IAAI,MAAM,cAAc;AAAA,EAC/B;AAEA,QAAM,UAAU,cAAc,QAAQ,OAAO,GAAG,EAAE,KAAK;AACvD,MAAI,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAW,IAAI,GAAG;AAC3D,UAAM,IAAI,MAAM,gCAAgC;AAAA,EACjD;AAEA,QAAM,aAAkB,gBAAU,QAAQ,QAAQ,QAAQ,EAAE,CAAC;AAE7D,aAAW,QAAQ,cAAc;AAChC,QAAI,CAAC,KAAM;AACX,UAAM,UAAe,cAAQ,IAAI;AACjC,UAAM,YAAiB,cAAQ,SAAS,UAAU;AAClD,UAAM,MAAW,eAAS,SAAS,SAAS;AAC5C,QAAI,QAAQ,MAAO,CAAC,IAAI,WAAW,IAAI,KAAK,CAAM,iBAAW,GAAG,GAAI;AACnE,aAAO;AAAA,IACR;AAAA,EACD;AAEA,QAAM,IAAI,MAAM,kBAAkB;AACnC;AA1BgB;AA6BT,SAAS,2BACf,eACA,cAC8C;AAC9C,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,YAAY,cAAc,SAAS,IAAI,GAAG;AACxF,WAAO;AAAA,EACR;AAEA,QAAM,UAAU,cAAc,QAAQ,OAAO,GAAG,EAAE,KAAK;AACvD,MAAI,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAW,IAAI,GAAG;AAC3D,WAAO;AAAA,EACR;AAEA,QAAM,aAAkB,gBAAU,QAAQ,QAAQ,QAAQ,EAAE,CAAC;AAE7D,aAAW,QAAQ,cAAc;AAChC,QAAI,CAAC,KAAM;AACX,QAAI;AACH,YAAM,UAAe,cAAQ,IAAI;AACjC,YAAM,YAAiB,cAAQ,SAAS,UAAU;AAClD,YAAM,MAAW,eAAS,SAAS,SAAS;AAC5C,UAAI,IAAI,WAAW,IAAI,KAAU,iBAAW,GAAG,EAAG;AAClD,YAAM,OAAU,aAAS,SAAS;AAClC,UAAI,KAAK,OAAO,GAAG;AAClB,eAAO,EAAE,UAAU,WAAW,KAAK;AAAA,MACpC;AAAA,IACD,QAAQ;AAAA,IAER;AAAA,EACD;AAEA,SAAO;AACR;AAhCgB;AAmCT,SAAS,oBAAoB,YAA2B;AAC9D,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,OAAO,wBAAC,QAAiB;AAC9B,QAAI,OAAO,QAAQ,YAAY,CAAC,IAAI,KAAK,EAAG;AAC5C,QAAI;AACH,YAAM,MAAW,cAAQ,OAAO,IAAI,QAAQ,OAAO,GAAG,CAAC;AACvD,UAAO,eAAW,GAAG,EAAG,OAAM,IAAI,GAAG;AAAA,IACtC,QAAQ;AAAA,IAER;AAAA,EACD,GARa;AASb,aAAW,OAAO,YAAY,YAAY,CAAC,EAAG,MAAK,GAAG;AACtD,OAAK,SAAS;AACd,OAAK,QAAQ;AACb,MAAI,YAAY,SAAS,OAAQ,MAAK,WAAW,QAAQ,MAAM;AAC/D,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAQ,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AACnC,SAAO;AACR;AAlBgB;;;AClEhB,YAAYC,SAAQ;AACpB,YAAY,cAAc;AAGnB,SAAS,kBAAkB,OAAsB;AACtD,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAM,wBAAC,MAA0B;AACrC,QAAI,CAAC,EAAG;AACR,UAAM,MAAe,iBAAQ,CAAC;AAC9B,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,WAAK,IAAI,GAAG;AACZ,YAAM,KAAK,GAAG;AAAA,IAChB;AAAA,EACF,GAPY;AASZ,MAAI,MAAM,QAAQ,MAAM,eAAe,GAAG;AACxC,eAAW,KAAK,MAAM,gBAAiB,KAAI,CAAC;AAAA,EAC9C;AACA,MAAI,MAAM,WAAY,KAAI,MAAM,UAAU;AAC1C,MAAI,MAAM,eAAgB,KAAI,MAAM,cAAc;AAElD,SAAO;AACT;AAnBgB;AAsBhB,SAAS,oBAAoB,OAAqB;AAChD,MAAI,MAAM,eAAgB,QAAO;AACjC,SAAO,MAAM,YAAY,KAAK,SAAS;AACzC;AAHS;AAKF,SAAS,sBAAsB,SAAc,OAAsB;AACxE,QAAM,QAAQ,kBAAkB,KAAK;AACrC,QAAM,UAAoB,CAAC;AAC3B,QAAM,OAAO,oBAAI,IAAY;AAE7B,QAAM,UAAU,wBAAC,QAAgB;AAC/B,QAAI,CAAC,OAAO,KAAK,IAAI,GAAG,EAAG;AAC3B,QAAI,oBAAoB,KAAK,GAAG;AAC9B,WAAK,IAAI,GAAG;AACZ,cAAQ,KAAK,GAAG;AAChB;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,YAAO,aAAkB,iBAAQ,MAAM,GAAG,CAAC,EAAE,YAAY,GAAG;AAC1D,eAAK,IAAI,GAAG;AACZ,kBAAQ,KAAK,GAAG;AAChB;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,GAlBgB;AAoBhB,aAAW,OAAO,QAAQ,YAAY,CAAC,EAAG,SAAQ,GAAG;AACrD,MAAI,QAAQ,SAAS,OAAQ,SAAQ,QAAQ,QAAQ,MAAM;AAC3D,SAAO;AACT;AA5BgB;AA8BT,SAAS,iBAAiB,MAAgB,OAAsB;AACrE,QAAM,QAAQ,kBAAkB,KAAK;AACrC,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,OAAO;AACxB,eAAW,KAAK,MAAM;AACpB,YAAM,MAAe,iBAAQ,MAAM,CAAC;AACpC,UAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,aAAK,IAAI,GAAG;AACZ,cAAM,KAAK,GAAG;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAdgB;;;AFvDhB,IAAM,kBAAkB,IAAI,OAAO;AAE5B,SAAS,aAAa,QAAwB;AACnD,MAAI;AACF,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,UAAU,OAAO,WAAW,MAAM,IAAI,SAAS,UAAU,MAAM;AACrE,WAAO,IAAI,IAAI,SAAS,kBAAkB,EAAE;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AARgB;AAUhB,IAAM,wBAAwB,CAAC,YAAY,cAAc,kBAAkB,gBAAgB;AAE3F,SAAS,kBAAkB,SAAiB,WAA4B;AACtE,QAAM,IAAI,aAAa,OAAO;AAC9B,QAAM,OAAO,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AACnC,MAAI,SAAS,UAAW,QAAO;AAE/B,MAAI,sBAAsB,KAAK,CAAC,WAAW,EAAE,WAAW,MAAM,CAAC,EAAG,QAAO;AACzE,SAAO,+EAA+E,KAAK,CAAC;AAC9F;AAPS;AAST,SAAS,iBAAiB,KAAU,KAAU,MAAc,UAAkB,SAAiB,OAAkB;AAC/G,QAAM,OAAO,IAAI,KAAK,MAAM,IAAI,OAAO;AACvC,MAAI,IAAI,QAAQ,eAAe,MAAM,MAAM;AACzC,QAAI,UAAU,GAAG;AACjB,QAAI,IAAI;AACR;AAAA,EACF;AACA,MAAI;AACF,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,kBAAkB,KAAK;AAAA,MACvB,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,iBAAiB,IAAI,KAAK,OAAO,EAAE,YAAY;AAAA,IACjD,CAAC;AACD,QAAI,IAAI,IAAI;AAAA,EACd,SAAS,KAAK;AACZ,UAAM,KAAK,QAAQ,+BAA+B,gBAAgB,GAAG,CAAC;AACtE,QAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAI,uBAAuB;AAAA,IACjC;AAAA,EACF;AACF;AAvBS;AAyBF,SAAS,gBAAgB,KAAU,KAAU,WAAmB,UAAkB,MAAgB,OAAkB;AACzH,MAAI,KAAK,QAAQ,iBAAiB;AAChC,IAAG,aAAS,WAAW,CAAC,KAAK,SAAS;AACpC,UAAI,KAAK;AACP,cAAM,KAAK,QAAQ,2BAA2B,gBAAgB,GAAG,CAAC;AAClE,YAAI,CAAC,IAAI,aAAa;AACpB,cAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,cAAI,IAAI,uBAAuB;AAAA,QACjC;AACA;AAAA,MACF;AACA,uBAAiB,KAAK,KAAK,MAAM,UAAU,KAAK,SAAS,KAAK;AAAA,IAChE,CAAC;AACD;AAAA,EACF;AAEA,QAAM,aAAgB,qBAAiB,SAAS;AAChD,QAAM,OAAO,IAAI,KAAK,IAAI,IAAI,KAAK,OAAO;AAC1C,MAAI,IAAI,QAAQ,eAAe,MAAM,MAAM;AACzC,eAAW,QAAQ;AACnB,QAAI,UAAU,GAAG;AACjB,QAAI,IAAI;AACR;AAAA,EACF;AAEA,aAAW,GAAG,SAAS,CAAC,QAAQ;AAC9B,UAAM,KAAK,UAAU,iBAAiB,gBAAgB,GAAG,CAAC;AAC1D,QAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAI,uBAAuB;AAAA,IACjC,WAAW,CAAC,IAAI,cAAe,KAAI,QAAQ;AAAA,EAC7C,CAAC;AAED,MAAI,GAAG,WAAW,MAAM;AACtB,QAAI,CAAC,WAAW,UAAW,YAAW,QAAQ;AAAA,EAChD,CAAC;AAED,MAAI;AACF,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,iBAAiB,KAAK,MAAM,YAAY;AAAA,IAC1C,CAAC;AACD,eAAW,KAAK,GAAG;AAAA,EACrB,SAAS,KAAK;AACZ,UAAM,KAAK,QAAQ,+BAA+B,gBAAgB,GAAG,CAAC;AACtE,QAAI,CAAC,WAAW,UAAW,YAAW,QAAQ;AAC9C,QAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAI,uBAAuB;AAAA,IACjC;AAAA,EACF;AACF;AArDgB;AA+DT,SAAS,oBAAoB,KAAoE;AACtG,QAAM,EAAE,SAAS,SAAS,WAAW,OAAO,gBAAgB,IAAI;AAChE,QAAM,aAAa,CAAC,EAAE,QAAQ,SAAS,WAAW,QAAQ,SAAS,UAAU,QAAQ,SAAS,MAAM;AACpG,QAAM,cAAwB,aAAa,QAAQ,SAAS,QAAQ,CAAC,IAAI,CAAC;AAE1E,QAAM,eAAe,wBAAC,SAA0B;AAC9C,QAAI,CAAC,cAAc,CAAC,KAAM,QAAO;AACjC,aAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAI,KAAK,WAAW,YAAY,CAAC,CAAC,EAAG,QAAO;AAAA,IAC9C;AACA,WAAO;AAAA,EACT,GANqB;AAQrB,QAAM,eAAe,wBACnB,KACA,KACA,WACA,MACA,aACA,MAAc,MACL;AACT,UAAM,WAAW,aAAa,IAAI;AAClC,UAAM,eAAe,SAAS,SAAS,GAAG,IAAI,WAAW,YAAY;AACrE,UAAM,WAAW,GAAG,OAAO,IAAI,UAAU,KAAK,GAAG,CAAC,IAAI,YAAY;AAClE,UAAM,QAAQ,UAAU,KAAK,GAAG,MAAM,YAAY,KAAK,GAAG,IACtD,iBAAiB,aAAa,KAAK,IACnC,iBAAiB,WAAW,KAAK;AAErC,UAAM,gBAAgB,wBAAC,YAAiE;AACtF,YAAM,MAAM,gBAAgB,IAAI,QAAQ;AACxC,UAAI,KAAK,MAAO,QAAO;AACvB,UAAI,OAAO,CAAC,IAAI,OAAO;AACrB,cAAM,WAAW,gBAAgB,OAAO,GAAG;AAC3C,YAAI,SAAU,QAAO,EAAE,UAAU,IAAI,UAAU,MAAM,SAAS;AAAA,MAChE;AAEA,YAAM,MAAM,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AACzD,YAAM,UAAU,2BAA2B,KAAK,KAAK;AACrD,UAAI,SAAS;AACX,wBAAgB,OAAO,UAAU,QAAQ,UAAU,QAAQ,KAAK,OAAO;AACvE,eAAO;AAAA,MACT;AAEA,sBAAgB,QAAQ,QAAQ;AAChC,aAAO;AAAA,IACT,GAjBsB;AAmBtB,UAAM,QAAQ,cAAc,YAAY;AACxC,QAAI,CAAC,OAAO;AACV,UAAI,MAAM,KAAK,CAAC,cAAc,kBAAkB,cAAc,SAAS,GAAG;AACxE,YAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,YAAI,IAAI,iBAAiB;AACzB;AAAA,MACF;AACA,mBAAa,KAAK,KAAK,CAAC,QAAQ,QAAS,MAAO,GAAG,MAAM,WAAW,aAAa,MAAM,CAAC;AACxF;AAAA,IACF;AAEA,UAAM,WAAW,QAAQ,YAAqB,kBAAQ,MAAM,QAAQ,CAAC,KAAK;AAC1E,oBAAgB,KAAK,KAAK,MAAM,UAAU,UAAU,MAAM,MAAM,KAAK;AAAA,EACvE,GA/CqB;AAiDrB,SAAO,CAAC,KAAU,KAAU,QAAgB;AAC1C,QAAI,UAAU,gCAAgC,cAAc;AAC5D,QAAI,UAAU,8BAA8B,cAAc;AAE1D,UAAM,UAAU,sBAAsB,SAAS,KAAK;AACpD,QAAI,CAAC,QAAQ,QAAQ;AACnB,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAI,4BAA4B;AACpC;AAAA,IACF;AAEA,QAAI,aAAa,GAAG,GAAG;AACrB,mBAAa,KAAK,KAAK,CAAC,QAAQ,QAAS,MAAO,GAAG,MAAM,WAAW,OAAO;AAAA,IAC7E,OAAO;AACL,mBAAa,KAAK,KAAK,SAAS,KAAK,OAAO;AAAA,IAC9C;AAAA,EACF;AACF;AA/EgB;;;AGpHT,SAAS,2BAA2B,OAAY,SAAiB,QAAa,SAAoB;AACxG,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,kBAAkB,YAAY,MAAM;AACzC,UAAM,YAAY,MAAM,gBAAgB,OAAO,GAAG,QAAQ;AAC1D,QAAI,YAAY,UAAU,KAAK;AAC9B,YAAM,KAAK,QAAQ,yBAAyB,SAAS,IAAI,OAAO,GAAG;AAAA,IACpE;AACA,QAAI,YAAY,UAAU,MAAM;AAC/B,YAAM,KAAK,QAAQ,2CAA2C;AAC9D,UAAI,MAAM,gBAAgB,OAAO,GAAG;AACnC,cAAM,gBAAgB,OAAO,EAAE,QAAQ,CAAC,SAAc;AACrD,cAAI,KAAK,aAAa,KAAK,IAAI,IAAI,KAAK,YAAY,KAAQ;AAC3D,iBAAK,QAAQ;AAAA,UACd;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD,GAAG,GAAM;AAET,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,OAAM,QAAQ,OAAO,IAAI,CAAC;AACvD,QAAM,QAAQ,OAAO,EAAE,cAAc;AAErC,SAAO,GAAG,cAAc,CAAC,eAAoB;AAC5C,QAAI,CAAC,MAAM,gBAAgB,OAAO,GAAG;AACpC,YAAM,gBAAgB,OAAO,IAAI,oBAAI,IAAI;AAAA,IAC1C;AACA,UAAM,YAAY,MAAM,gBAAgB,OAAO,EAAE;AACjD,QAAI,aAAa,SAAS;AACzB,UAAI;AACH,cAAM,KAAK,QAAQ,iCAAiC,SAAS,IAAI,OAAO,GAAG;AAC3E,mBAAW,QAAQ;AAAA,MACpB,SAAS,KAAK;AACb,cAAM,KAAK,QAAQ,2BAA2B,GAAG;AAAA,MAClD;AACA;AAAA,IACD;AACA,UAAM,gBAAgB,OAAO,EAAE,IAAI,UAAU;AAC7C,eAAW,GAAG,SAAS,MAAM;AAC5B,YAAM,gBAAgB,OAAO,EAAE,OAAO,UAAU;AAAA,IACjD,CAAC;AACD,eAAW,WAAW,GAAM;AAAA,EAC7B,CAAC;AACF;AA1CgB;;;ACFhB,SAAS,gBAAgB;AACzB,OAAOC,cAAa;AAGpB,IAAM,UAAUC,SAAQ;AAExB,SAAS,QAAQ,IAAkB;AAClC,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAAA,EAE9B;AACD;AALS;AAQF,SAAS,kBAAkB,MAAwB;AACzD,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,MAAO,QAAO,CAAC;AACjE,MAAI;AACH,QAAIA,SAAQ,aAAa,SAAS;AACjC,YAAM,MAAM,SAAS,kCAAkC,IAAI,MAAM;AAAA,QAChE,UAAU;AAAA,QACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ;AAAA,MACjC,CAAC;AACD,YAAM,OAAO,oBAAI,IAAY;AAC7B,iBAAW,QAAQ,IAAI,MAAM,OAAO,GAAG;AACtC,cAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,KAAK;AACrC,YAAI,MAAM,SAAS,KAAK,MAAM,CAAC,MAAM,YAAa;AAClD,cAAM,YAAY,MAAM,CAAC,KAAK;AAC9B,cAAM,YAAY,UAAU,MAAM,SAAS;AAC3C,cAAM,MAAM,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AACjD,YAAI,aAAa,SAAS,UAAU,CAAC,GAAI,EAAE,MAAM,QAAQ,MAAM,GAAG;AACjE,eAAK,IAAI,GAAG;AAAA,QACb;AAAA,MACD;AACA,aAAO,CAAC,GAAG,IAAI;AAAA,IAChB;AACA,QAAI;AACH,YAAM,MAAM,SAAS,kBAAkB,IAAI,oBAAoB;AAAA,QAC9D,UAAU;AAAA,QACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ;AAAA,MACjC,CAAC;AACD,aAAO,IACL,MAAM,OAAO,EACb,IAAI,CAAC,MAAM,SAAS,EAAE,KAAK,GAAG,EAAE,CAAC,EACjC,OAAO,CAAC,MAAM,IAAI,CAAC;AAAA,IACtB,QAAQ;AACP,aAAO,CAAC;AAAA,IACT;AAAA,EACD,QAAQ;AACP,WAAO,CAAC;AAAA,EACT;AACD;AApCgB;AAsChB,SAAS,QAAQ,KAAsB;AACtC,MAAI,CAAC,OAAO,QAAQ,WAAW,OAAO,EAAG,QAAO;AAChD,MAAI;AACH,QAAIA,SAAQ,aAAa,SAAS;AACjC,eAAS,iBAAiB,GAAG,OAAO,EAAE,OAAO,SAAS,CAAC;AAAA,IACxD,OAAO;AACN,eAAS,WAAW,GAAG,IAAI,EAAE,OAAO,SAAS,CAAC;AAAA,IAC/C;AACA,WAAO;AAAA,EACR,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAZS;AAeF,SAAS,YACf,MACA,MACU;AACV,QAAM,UAAU,MAAM,cAAc;AACpC,QAAM,YAAY,kBAAkB,IAAI,EAAE,OAAO,CAAC,MAAM,MAAM,WAAW,MAAM,OAAO;AACtF,MAAI,CAAC,UAAU,OAAQ,QAAO;AAE9B,QAAM,QAAQ,MAAM,QAAQ,IAAI,KAAK,KAAK,OAAO;AACjD,UAAQ,KAAK,cAAc,KAAK,gBAAM,IAAI,kEAAgB,UAAU,KAAK,IAAI,CAAC,EAAE;AAChF,aAAW,OAAO,WAAW;AAC5B,YAAQ,GAAG;AAAA,EACZ;AACA,UAAQ,GAAG;AAEX,QAAM,YAAY,kBAAkB,IAAI,EAAE,OAAO,CAAC,MAAM,MAAM,WAAW,MAAM,OAAO;AACtF,SAAO,UAAU,WAAW;AAC7B;AAjBgB;AAoBT,SAAS,oBAAoB,OAAsB;AACzD,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,QAAQ,MAAM,YAAY;AAChC,MAAI,OAAO;AACV,eAAW,MAAM,OAAO,KAAK,KAAK,GAAG;AACpC,UAAI,OAAO,UAAW;AACtB,UAAI,OAAO,UAAU,CAAC,gBAAgB,EAAE,EAAG;AAC3C,YAAM,MAAM,WAAW,IAAI,KAAK;AAChC,UAAI,KAAK,MAAO;AAChB,UAAI,KAAK,KAAM,OAAM,IAAI,OAAO,IAAI,IAAI,CAAC;AAAA,IAC1C;AAAA,EAED;AACA,QAAM,aAAa,MAAM,YAAY;AACrC,MAAI,YAAY;AACf,eAAW,MAAM,OAAO,KAAK,UAAU,GAAG;AACzC,UAAI,OAAO,UAAW;AACtB,UAAI,CAAC,gBAAgB,EAAE,EAAG;AAC1B,YAAM,MAAM,gBAAgB,IAAI,KAAK;AACrC,UAAI,KAAK,UAAW,OAAM,IAAI,OAAO,IAAI,SAAS,CAAC;AAAA,IACpD;AAAA,EACD;AACA,SAAO,CAAC,GAAG,KAAK;AACjB;AAvBgB;AA0BT,SAAS,uBAAuB,OAAkB;AACxD,aAAW,QAAQ,oBAAoB,KAAK,GAAG;AAC9C,gBAAY,MAAM,EAAE,YAAYA,SAAQ,IAAI,CAAC;AAAA,EAC9C;AACD;AAJgB;;;Ab7FhB,SAAS,kBAAkB,OAAY,SAAuB;AAC7D,MAAI,MAAM,WAAW,SAAS;AAC7B,iBAAa,MAAM,WAAW,OAAO;AACrC,UAAM,WAAW,UAAU;AAAA,EAC5B;AACA,QAAM,WAAW,UAAU,WAAW,MAAM;AAC3C,oBAAgB,OAAO,OAAO;AAC9B,QAAI,MAAM,WAAW,SAAS;AAC7B,mBAAa,MAAM,WAAW,OAAO;AACrC,YAAM,WAAW,UAAU;AAAA,IAC5B;AAAA,EACD,GAAG,MAAM,WAAW,IAAI,KAAK,GAAI;AAClC;AAZS;AAcT,SAAS,oBAAoB,OAAY,SAAiBC,KAAoB;AAC7E,SAAO,MAAM,YAAY,OAAO;AAChC,MAAIA,IAAI,QAAO,MAAM,UAAU,OAAO;AACvC;AAHS;AAKF,SAAS,cAAc,WAAmB,IAAI,KAAU,OAAiB;AAC/E,MAAI;AACH,QAAI,SAAS,WAAW,OAAO,GAAG;AAEjC,aAAO;AAAA,QACN,gBAAgB,wBAAC,aAAkB;AAClC,iBAAa,mBAAa,KAAK,aAAa,MAAM,WAAW,WAAW,QAAQ;AAAA,QACjF,GAFgB;AAAA,QAGhB,OAAa;AAAA,QACb,SAAe;AAAA,MAChB;AAAA,IACD,OAAO;AACN,aAAO;AAAA,QACN,gBAAqB;AAAA,QACrB,OAAY;AAAA,QACZ,SAAc;AAAA,MACf;AAAA,IACD;AAAA,EACD,SAAS,KAAK;AACb,UAAM,KAAK,QAAQ,sBAAsB,eAAe,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO;AAAA,EAAK,IAAI,KAAK,KAAK,KAAK,UAAU,GAAG,CAAC;AACjI,WAAO;AAAA,MACN,gBAAqB;AAAA,MACrB,OAAY;AAAA,MACZ,SAAc;AAAA,IACf;AAAA,EACD;AACD;AA1BgB;AA4BT,SAAS,gBAAgB,OAAY,SAAsB;AACjE,QAAM,UAAU,WAAW,SAAS,KAAK;AACzC,MAAI,CAAC,WAAW,QAAQ,MAAO;AAE/B,MAAI;AACH,QAAI,CAAC,MAAM,YAAY,OAAO,GAAG;AAChC,UAAI,QAAQ,cAAc,QAAW;AACpC,gBAAQ,YAAY,EAAE,GAAI,MAAM,WAAW,aAAa,CAAC,GAAI,GAAI,QAAQ,aAAa,CAAC,EAAG;AAAA,MAC3F,OAAO;AACN,gBAAQ,YAAY,EAAE,GAAI,MAAM,WAAW,aAAa,CAAC,EAAG;AAAA,MAC7D;AAEA,YAAM,UAAU,cAAc,QAAQ,UAAU,SAAS,KAAK;AAC9D,YAAM,YAAY,MAAM,WAAW,SAAS;AAC5C,YAAM,kBAAkB,IAAI,gBAAgB,KAAM,GAAM;AACxD,YAAM,cAAc,kBAAkB,KAAK;AAC3C,YAAM,WAAW,QAAQ,YAAY,IAAI,WAAW,OAAO;AAE3D,YAAM,cAAc,eAAe,aAAa;AAChD,YAAM,UAAU,eAAe,SAAS;AACxC,YAAM,UAAU,eAAe,SAAS;AACxC,YAAM,YAAY,eAAe,WAAW;AAC5C,YAAM,eAAe,oBAAoB,EAAE,SAAS,SAAS,WAAW,OAAO,gBAAgB,CAAC;AAEhG,YAAM,SAAU,QAAgB,eAAe,CAAC,KAAU,QAAa;AACtE,YAAI;AACH,cAAI,CAAC,gBAAgB,KAAK,KAAK,GAAG;AACjC,oBAAQ,OAAO,QAAQ,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AACjE,gBAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,gBAAI,IAAI,KAAK;AACb;AAAA,UACD;AACA,+BAAqB,KAAK,SAAS,MAAM,UAAU;AAEnD,cAAI,IAAI,KAAK,WAAW,MAAM,KAAK,SAAS;AAC3C,oBAAQ,OAAO,OAAO,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AAChE,oBAAQ,KAAK,KAAK,OAAO;AAAA,UAC1B,WAAW,IAAI,KAAK,WAAW,MAAM,KAAK,SAAS;AAClD,oBAAQ,OAAO,OAAO,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AAChE,oBAAQ,KAAK,KAAK,OAAO;AAAA,UAC1B,WAAW,IAAI,KAAK,WAAW,QAAQ,KAAK,WAAW;AACtD,oBAAQ,OAAO,SAAS,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AAClE,sBAAU,KAAK,KAAK,OAAO;AAAA,UAC5B,WAAW,cAAc;AACxB,oBAAQ,OAAO,aAAa,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AACtE,yBAAa,KAAK,KAAK,IAAI,GAAI;AAAA,UAChC,OAAO;AACN,kBAAM,KAAK,QAAQ,IAAI,QAAQ,IAAI,GAAG;AACtC,gBAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,gBAAI,IAAI,KAAK;AAAA,UACd;AAAA,QACD,SAAS,KAAK;AACb,gBAAM,KAAK,QAAQ,uBAAuB,gBAAgB,GAAG,CAAC;AAC9D,cAAI,CAAC,IAAI,aAAa;AACrB,gBAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,gBAAI,IAAI,uBAAuB;AAAA,UAChC,WAAW,CAAC,IAAI,eAAe;AAC9B,gBAAI,IAAI;AAAA,UACT;AAAA,QACD;AAAA,MACD,CAAC;AAED,YAAM,YAAY,OAAO,IAAI;AAE7B,UAAI,QAAQ,IAAI;AACf,qBAAa,OAAO,OAAO;AAAA,MAC5B;AAEA,aAAO,GAAG,SAAS,CAAC,QAAa;AAChC,YAAI,IAAI,SAAS,cAAc;AAC9B,gBAAM,WAAW,SAAS,KAAK,QAAQ,IAAI;AAC3C,gBAAM,KAAK,QAAQ,gBAAgB,QAAQ,IAAI,2BAA2B;AAC1E,8BAAoB,OAAO,SAAS,QAAQ,EAAE;AAC9C,oBAAU,OAAO,OAAO;AAAA,QACzB,OAAO;AACN,gBAAM,KAAK,QAAQ,iBAAiB,eAAe,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO;AAAA,EAAK,IAAI,KAAK,KAAK,GAAG;AAAA,QAC7G;AAAA,MACD,CAAC;AAED,kBAAY,QAAQ,MAAM,EAAE,YAAY,QAAQ,KAAK,OAAO,QAAQ,CAAC;AAErE,UAAI,MAAM,WAAW,OAAO,UAAW,CAAC,QAAQ,MAAM,CAAC,MAAM,WAAW,IAAK;AAC5E,eAAO,OAAO,QAAQ,MAAM,MAAM;AACjC,kBAAQ,IAAI,IAAI,OAAO,cAAc,WAAW,CAAC,GAAG;AACpD,cAAI,QAAQ,IAAI;AACf,oBAAQ,IAAI,0BAA0B,QAAQ,UAAU,OAAO,aAAa,QAAQ,IAAI,SAAS;AAAA,UAClG;AACA,kBAAQ,IAAI,0BAA0B,QAAQ,QAAQ,aAAa,QAAQ,IAAI,SAAS;AACxF,kBAAQ,IAAI,kDAAkD;AAAA,QAC/D,CAAC;AAAA,MACF,OAAO;AACN,cAAM,QAAgB,UAAU,QAAQ,IAAI,KAAK;AACjD,eAAO,OAAO,QAAQ,MAAM,OAAO,MAAM;AACxC,kBAAQ,IAAI,IAAI,OAAO,cAAc,WAAW,CAAC,GAAG;AACpD,cAAI,QAAQ,IAAI;AACf,oBAAQ,IAAI,0BAA0B,QAAQ,UAAU,OAAO,GAAG,KAAK,IAAI,QAAQ,IAAI,SAAS;AAAA,UACjG;AACA,kBAAQ,IAAI,0BAA0B,QAAQ,QAAQ,GAAG,KAAK,IAAI,QAAQ,IAAI,SAAS;AACvF,kBAAQ,IAAI,kDAAkD;AAAA,QAC/D,CAAC;AAAA,MACF;AAEA,UAAI,QAAQ,QAAQ;AACnB,mCAA2B,OAAO,SAAS,QAAQ,OAAO;AAAA,MAC3D;AAAA,IACD;AAAA,EACD,SAAS,KAAK;AACb,UAAM,KAAK,QAAQ,sBAAsB,eAAe,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO;AAAA,EAAK,IAAI,KAAK,KAAK,KAAK,UAAU,GAAG,CAAC;AAAA,EAClI;AAEA,SAAO,MAAM,YAAY,OAAO;AACjC;AA/GgB;AAiHhB,SAAS,yBAAyB,OAAY,MAAc,gBAAuC;AAClG,aAAW,WAAW,OAAO,KAAK,MAAM,eAAe,CAAC,CAAC,GAAG;AAC3D,QAAI,YAAY,eAAgB;AAChC,UAAM,MAAM,WAAW,SAAS,KAAK;AACrC,QAAI,KAAK,SAAS,KAAM,QAAO;AAAA,EAChC;AACA,SAAO;AACR;AAPS;AASF,SAAS,UAAU,OAAY,gBAAwB,QAAc;AAC3E,QAAM,gBAA0B,MAAM,WAAW,YAAY,CAAC;AAC9D,QAAM,UAAU,WAAW,eAAe,KAAK;AAC/C,QAAM,OAAO,SAAS;AACtB,MAAI,CAAC,QAAQ,CAAC,cAAc,SAAS,IAAI,GAAG;AAC3C,sBAAkB,OAAO,aAAa;AACtC;AAAA,EACD;AAEA,QAAM,mBAAmB,yBAAyB,OAAO,MAAM,aAAa;AAC5E,MAAI,kBAAkB;AACrB,YAAQ;AAAA,MACP,2BAAiB,IAAI,gDAAa,gBAAgB,wBAAS,aAAa;AAAA,IACzE;AACA;AAAA,EACD;AAEA,QAAM,WAAW,YAAY,MAAM,EAAE,YAAY,QAAQ,KAAK,OAAO,cAAc,CAAC;AACpF,QAAM,WAAW,WAAW,cAAc,OAAO,CAAC,MAAc,MAAM,IAAI;AAC1E,MAAI,UAAU;AACb,YAAQ,KAAK,2BAAiB,IAAI,kEAAgB,aAAa,GAAG;AAClE,sBAAkB,OAAO,aAAa;AACtC;AAAA,EACD;AAEA,UAAQ,MAAM,2BAAiB,IAAI,wFAAsC,IAAI,QAAG;AAChF,UAAQ,KAAK,CAAC;AACf;AA3BgB;;;AcrLhB,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EAAqB;AAAA,EAAc;AAAA,EACnC;AAAA,EAAsB;AAAA,EAAuB;AAAA,EAAM;AAAA,EAAY;AACjE,CAAC;AAEM,SAAS,iBAAiB,OAAY,cAA4B;AACvE,QAAM,WAAW,gBAAgB,cAAc,KAAK;AACpD,MAAI,CAAC,SAAS,IAAK;AACnB,MAAI,MAAM,eAAe,YAAY,EAAG;AAExC,MAAI;AACF,UAAM,aAAa,cAAc,SAAS,eAAe,UAAU,KAAK;AACxE,UAAM,aAAa,cAAc,SAAS,KAAM,UAAU,KAAK;AAE/D,UAAM,gBAAgB,IAAI,IAAI,SAAS,GAAI;AAC3C,UAAM,gBAAgB,cAAc,aAAa;AACjD,UAAM,oBAAoB,gBAAgB,MAAM;AAGhD,UAAM,cAAc,IAAI,WAAW,MAAM;AAAA,MACvC,WAAW,SAAS,aAAa;AAAA,MACjC,SAAS,SAAS,WAAW;AAAA,MAC7B,gBAAgB,SAAS,kBAAkB;AAAA,MAC3C,YAAY,SAAS,cAAc;AAAA,MACnC,gBAAgB,SAAS,kBAAkB;AAAA,MAC3C,oBAAoB,SAAS,sBAAsB;AAAA,MACnD,gBAAgB,SAAS,kBAAkB;AAAA,IAC7C,CAAC;AAED,UAAM,cAAe,WAAmB,eAAe,CAAC,KAAU,QAAa;AAC7E,UAAI,SAAS,UAAU;AACrB,YAAI,UAAU,KAAK;AAAA,UACjB,UAAU,SAAS,MAAM,IAAI;AAAA,UAC7B,6BAA6B;AAAA,QAC/B,CAAC;AACD,YAAI,IAAI;AACR;AAAA,MACF;AAEA,YAAM,YAAY,IAAI,IAAI,IAAI,OAAO,KAAK,aAAa;AAIvD,YAAM,iBAAsC,CAAC;AAC7C,iBAAW,OAAO,OAAO,KAAK,IAAI,OAAO,GAAG;AAC1C,YAAI,CAAC,mBAAmB,IAAI,IAAI,YAAY,CAAC,GAAG;AAC9C,yBAAe,GAAG,IAAI,IAAI,QAAQ,GAAG;AAAA,QACvC;AAAA,MACF;AAEA,YAAM,YAAiB;AAAA,QACrB,OAAO;AAAA,QACP,QAAQ,IAAI;AAAA,QACZ,UAAU,UAAU;AAAA,QACpB,MAAM,UAAU,QAAQ;AAAA,QACxB,MAAM,UAAU,WAAW,UAAU;AAAA,QACrC,SAAS;AAAA,MACX;AACA,UAAI,eAAe;AACjB,kBAAU,aAAa,UAAU;AAAA,MACnC;AAGA,YAAM,eAAe,SAAS,gBAAgB;AAE9C,YAAM,iBAAiB,WAAW,QAAQ,WAAW,CAAC,eAAoB;AACxE,eAAO,KAAK,WAAW,OAAO,EAAE,QAAQ,CAAC,QAAQ;AAC/C,cAAI,CAAC,mBAAmB,IAAI,IAAI,YAAY,CAAC,GAAG;AAC9C,gBAAI,UAAU,KAAK,WAAW,QAAQ,GAAG,CAAE;AAAA,UAC7C;AAAA,QACF,CAAC;AACD,YAAI,aAAa,WAAW;AAC5B,YAAI,cAAc;AAChB,gBAAM,WAAW,gBAAgB,KAAK,KAAK;AAC3C,cAAI,SAAU,KAAI,UAAU,YAAY,MAAM,QAAQ,QAAQ,IAAI,SAAS,KAAK,IAAI,IAAI,QAAQ;AAAA,QAClG;AACA,mBAAW,KAAK,KAAK,EAAE,KAAK,KAAK,CAAC;AAAA,MACpC,CAAC;AAED,UAAI,KAAK,gBAAgB,EAAE,KAAK,KAAK,CAAC;AAEtC,UAAI,GAAG,SAAS,CAAC,QAAa;AAC5B,cAAM,KAAK,SAAS,yBAAyB,GAAG;AAChD,uBAAe,QAAQ;AAAA,MACzB,CAAC;AAED,qBAAe,GAAG,SAAS,CAAC,QAAe;AACzC,cAAM,KAAK,SAAS,0BAA0B,GAAG;AACjD,cAAM,KAAK,SAAS,WAAW,UAAU,IAAI,YAAY,aAAa,EAAE;AACxE,YAAI,CAAC,IAAI,aAAa;AACpB,cAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAAA,QACpE;AACA,YAAI,IAAI,kBAAkB,IAAI,OAAO;AAAA,MACvC,CAAC;AAED,qBAAe,WAAW,MAAQ,MAAM;AACtC,cAAM,KAAK,SAAS,yBAAyB;AAC7C,uBAAe,QAAQ;AACvB,YAAI,CAAC,IAAI,aAAa;AACpB,cAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAAA,QACpE;AACA,YAAI,IAAI,iBAAiB;AAAA,MAC3B,CAAC;AAAA,IACH,CAAC;AAED,gBAAY,GAAG,SAAS,CAAC,QAAa;AACpC,UAAI,IAAI,SAAS,cAAc;AAC7B,cAAM,KAAK,SAAS,gBAAgB,SAAS,SAAS,2BAA2B;AACjF,eAAO,MAAM,eAAe,YAAY;AACxC,cAAM,WAAW,YAAY,SAAS,WAAW;AAAA,UAC/C,YAAY,QAAQ;AAAA,UACpB,OAAO;AAAA,QACT,CAAC;AACD,YAAI,UAAU;AACZ,kBAAQ,KAAK,uCAAmB,SAAS,SAAS,kEAAgB,YAAY,GAAG;AACjF,qBAAW,MAAM,iBAAiB,OAAO,YAAY,GAAG,MAAM,WAAW,IAAI,KAAK,GAAI;AAAA,QACxF;AAAA,MACF,OAAO;AACL,cAAM,KAAK,SAAS,uBAAuB,GAAG;AAAA,MAChD;AAAA,IACF,CAAC;AAED,QAAI,CAAC,MAAM,aAAc,OAAM,eAAe,CAAC;AAC/C,UAAM,aAAa,YAAY,IAAI;AAEnC,gBAAY,SAAS,WAAW,EAAE,YAAY,QAAQ,KAAK,OAAO,aAAa,CAAC;AAEhF,UAAM,WAAW,UAAU,SAAS,SAAS,KAAK;AAClD,UAAM,iBAAiB,6BAAM;AAC3B,cAAQ,IAAI,IAAI,YAAY,cAAc,WAAW,CAAC,GAAG;AACzD,cAAQ,IAAI,4BAA4B,SAAS,aAAa,GAAG,YAAY,WAAW,IAAI,SAAS,SAAS,SAAS;AACvH,cAAQ,IAAI,4BAA4B,SAAS,GAAG,SAAS;AAC7D,cAAQ,IAAI,kDAAkD;AAAA,IAChE,GALuB;AAOvB,QAAI,UAAU;AACZ,kBAAY,OAAO,SAAS,WAAW,UAAU,cAAc;AAAA,IACjE,OAAO;AACL,kBAAY,OAAO,SAAS,WAAW,cAAc;AAAA,IACvD;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,KAAK,SAAS,uBAAuB,KAAK,UAAU,GAAG,CAAC;AAAA,EAChE;AACF;AA1IgB;;;A1BHhB,IAAM,eAAe,oBAAI,IAAsB;AACxC,SAAS,eAAe,MAAoC;AACjE,SAAO,aAAa,IAAI,IAAI;AAC9B;AAFgB;AAID,SAAR,YAAkB,OAAY,KAAU;AAE7C,eAAa,IAAI,WAAW,IAAI,OAAO;AACvC,eAAa,IAAI,WAAW,IAAI,OAAO;AACvC,eAAa,IAAI,UAAU,IAAI,MAAM;AACrC,eAAa,IAAI,aAAa,IAAI,SAAS;AAE3C,WAAS,gBAAsB;AAC7B,iBAAa,OAAO,GAAG;AAEvB,YAAQ,IAAI,kSAAkD;AAE9D,2BAAuB,KAAK;AAE5B,QAAI,MAAM,YAAY,OAAO;AAC3B,YAAM,kBAAkB,CAAC,YACvB,gBAAgB,OAAO,OAAO;AAChC,aAAO,KAAK,MAAM,WAAW,KAAK,EAAE,QAAQ,CAAC,OAAe;AAC1D,YAAI,gBAAgB,EAAE,GAAG;AACvB,0BAAgB,OAAO,EAAE;AAAA,QAC3B;AAAA,MACF,CAAC;AAED,UAAI,MAAM,WAAW,MAAM,MAAM;AAC/B,wBAAgB,OAAO,MAAM;AAAA,MAC/B;AAAA,IACF;AAEA,QAAI,MAAM,YAAY,YAAY;AAChC,aAAO,KAAK,MAAM,WAAW,UAAU,EAAE,QAAQ,CAAC,OAAe;AAC/D,YAAI,gBAAgB,EAAE,GAAG;AACvB,2BAAiB,OAAO,EAAE;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AA5BS;AA8BT,SAAO,EAAE,eAAe,QAAQ,GAAG;AACrC;AAtCO;;;A2BlBP;AAAA;AAAA;AAAA;AAAA;;;ACCO,SAAS,OAAO,OAAY;AAClC,WAAS,aAAa,SAAc,SAAkB;AACrD,WAAO,cAAc,WAAW,MAAM,OAAO,SAAS,MAAM,SAAS,KAAK,MAAM,SAAS;AAAA,EAC1F;AAFS;AAIT,WAAS,UAAU,SAAc;AAChC,UAAM,EAAE,SAAS,SAAS,IAAI;AAC9B,UAAM,OAAO,UAAU,KAAK,MAAM,SAAS,KAAK,SAAS,EAAE,IAAI;AAC/D,QAAI,KAAM,QAAO,KAAK,EAAE,SAAS,OAAO,UAAU,SAAS,GAAG,CAAC;AAC/D,WAAO,EAAE,GAAG,SAAS,GAAI,YAAY,CAAC,EAAG;AAAA,EAC1C;AALS;AAOT,WAAS,UAAU,SAAc;AAChC,UAAM,UAAU,QAAQ,OAAO,GAAG,SAAS,QAAQ,eAAe,UAAU,OAAO,IAAI,QAAQ,SAAS,GAAG,QAAQ,EAAE;AAAA,EACtH;AAFS;AAIT,WAAS,aAAa,SAAc,QAAa;AAChD,QAAI,QAAQ,SAAS,KAAK;AACzB,UAAI,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,GAAG;AAC3C,sBAAc,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,CAAC;AACpD,cAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,IAAI;AAAA,MAC1C;AACA;AAAA,IACD;AACA,QAAI,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,EAAG;AAE5C,UAAM,cAAc,UAAU,OAAO;AACrC,UAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,IAAI,YAAY,MAAM;AAC1D,YAAM,UAAU,EAAE,GAAG,UAAU,OAAO,GAAG,IAAI,KAAK,IAAI,EAAE;AACxD,YAAM,UAAU,QAAQ,OAAO,EAAE,OAAO,SAAS,QAAQ,MAAM,GAAG,QAAQ,EAAE;AAC5E,UAAI,CAAC,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,GAAG;AAC5C,sBAAc,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,CAAC;AAAA,MACrD;AAAA,IACD,GAAG,aAAa,MAAM,GAAI;AAE1B,YAAQ,IAAI,OAAO,SAAS,MAAM;AACjC,UAAI,MAAM,QAAQ,QAAQ,OAAO,IAAI,MAAM,GAAG;AAC7C,sBAAc,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,CAAC;AACpD,eAAO,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM;AAAA,MAC7C;AAAA,IACD,CAAC;AAAA,EACF;AAzBS;AA2BT,WAAS,WAAW,SAAc;AACjC,YAAQ,WAAY,QAAQ,gBAAgB,MAAM,UAAU,KAAK,QAAQ,OAAO,IAAI,QAAQ,SAAS,EAAE,KAAM,CAAC;AAC9G,QAAI,QAAQ,UAAU,IAAI;AACzB,mBAAa,SAAS,aAAa,QAAQ,SAAS,QAAQ,OAAO,CAAC;AAAA,IACrE,OAAO;AACN,gBAAU,OAAO;AAAA,IAClB;AAAA,EACD;AAPS;AAST,SAAO,EAAE,cAAc,WAAW,YAAY,cAAc,UAAU;AACvE;AArDgB;;;ACShB,eAAsB,sBAAsB,KAAU,OAA2B;AAChF,QAAM,WAAW,KAAK;AACtB,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,SAAS,CAAC,EAAG;AAC9C,QAAM,KAAK,OAAO,SAAS,CAAC,CAAC;AAC7B,MAAI;AACH,UAAM,EAAE,iBAAAC,iBAAgB,IAAI,MAAM,OAAO,6BAAyC;AAClF,UAAM,OAAO,MAAMA,iBAAgB,KAAK,EAAE,eAAe,EAAE;AAC3D,QAAI,QAAQ,KAAK,WAAW,UAAU;AACrC,UAAI,cAAc,EAAE,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,QAAQ,KAAK,OAAO;AAClE,UAAI,SAAS,CAAC,IAAI,OAAO,KAAK,EAAE;AAAA,IACjC,OAAO;AACN,UAAI,cAAc;AAAA,IACnB;AAAA,EACD,QAAQ;AACP,QAAI,cAAc;AAAA,EACnB;AACD;AAhBsB;AAkBf,SAAS,oBAAoB,KAAkB;AACrD,MAAI,KAAK,aAAa,MAAM,KAAM,QAAO,OAAO,IAAI,YAAY,EAAE;AAClE,QAAM,IAAI,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AACzC,SAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AACjC;AAJgB;AAMT,SAAS,mBAAmB,KAA8B;AAChE,MAAI,KAAK,aAAa,GAAI,QAAO,OAAO,IAAI,YAAY,EAAE;AAC1D,QAAM,KAAK,KAAK,WAAW,CAAC;AAC5B,SAAO,KAAK,OAAO,EAAE,IAAI;AAC1B;AAJgB;;;ACrBhB,SAAS,kBAAkB,OAAqC;AAC/D,SAAQ,OAAO,YAAY,YAAwC,CAAC;AACrE;AAFS;AAIT,SAAS,mBAAmBC,OAAc,SAA0B;AACnE,MAAI,QAAQ,SAAS,GAAG,GAAG;AAC1B,WAAOA,MAAK,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC;AAAA,EAC5C;AACA,SAAOA,UAAS;AACjB;AALS;AAQF,SAAS,cAAc,OAAY,UAA2B;AACpE,QAAM,MAAM,kBAAkB,KAAK;AACnC,QAAM,YAAa,IAAI,iBAA8B;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACA,SAAO,UAAU,KAAK,CAAC,MAAM,mBAAmB,UAAU,CAAC,CAAC;AAC7D;AAXgB;AAaT,SAAS,eAAe,OAAY,UAA2B;AACrE,QAAM,MAAM,kBAAkB,KAAK;AACnC,MAAI,CAAC,IAAI,YAAa,QAAO;AAC7B,MAAI,cAAc,OAAO,QAAQ,EAAG,QAAO;AAC3C,SAAO;AACR;AALgB;AAaT,SAAS,iBAAiB,KAAU,OAAY,UAAmC;AACzF,MAAI,CAAC,eAAe,OAAO,QAAQ,GAAG;AACrC,WAAO,EAAE,IAAI,KAAK;AAAA,EACnB;AAEA,QAAM,WAAW,KAAK;AACtB,QAAM,KAAK,YAAY,GAAG;AAE1B,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,KAAK,CAAC,SAAS,CAAC,GAAG;AACpE,qBAAiB,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,QAAQ;AAAA,IACT,CAAC;AACD,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,0BAA0B;AAAA,EACnE;AAEA,QAAM,CAAC,EAAE,IAAI;AACb,QAAM,MAAM,kBAAkB,KAAK;AACnC,QAAM,WAAW,OAAO,IAAI,iBAAiB,WAAW,IAAI,eAAe;AAC3E,QAAM,YAAY,oBAAoB,GAAG;AAEzC,MAAI,YAAY,UAAU;AACzB,qBAAiB,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ,KAAK;AAAA,MACb,MAAM,OAAO,EAAE;AAAA,MACf,OAAO;AAAA,MACP;AAAA,MACA,QAAQ,YAAY,QAAQ;AAAA,IAC7B,CAAC;AACD,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,0BAA0B;AAAA,EACnE;AAEA,SAAO,EAAE,IAAI,KAAK;AACnB;AAtCgB;AAyChB,eAAsB,sBAAsB,KAAU,OAAY,UAA4C;AAC7G,MAAI,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,SAAS,CAAC,GAAG;AACpD,UAAM,sBAAsB,KAAK,KAAK;AACtC,QAAI,CAAC,IAAI,eAAe,eAAe,OAAO,QAAQ,GAAG;AACxD,uBAAiB,OAAO;AAAA,QACvB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,MAAM,OAAO,IAAI,SAAS,CAAC,CAAC;AAAA,QAC5B,IAAI,YAAY,GAAG;AAAA,QACnB,QAAQ;AAAA,MACT,CAAC;AACD,aAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,uBAAuB;AAAA,IAChE;AAAA,EACD;AACA,SAAO,iBAAiB,KAAK,OAAO,QAAQ;AAC7C;AAhBsB;AAkBf,SAAS,cAAc,KAAU,QAA+B;AACtE,MAAI,UAAU,OAAO,QAAQ,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACvF,MAAI,IAAI,KAAK,UAAU,EAAE,OAAO,OAAO,WAAW,eAAe,CAAC,CAAC;AACpE;AAHgB;;;AC9FT,SAAS,OAAO,OAAyB;AAC/C,SAAO,UAAU,KAAK,UAAU;AACjC;AAFgB;AAKT,SAAS,sBAAsB,SAAqE;AAC1G,QAAM,MAAM,WAAW,CAAC;AACxB,SAAO;AAAA,IACN,OAAO,OAAO,IAAI,KAAK;AAAA,IACvB,IAAI,OAAO,IAAI,EAAE;AAAA,IACjB,QAAQ,OAAO,IAAI,MAAM;AAAA,IACzB,MAAM,OAAO,IAAI,IAAI;AAAA,IACrB,QAAQ,OAAO,IAAI,MAAM;AAAA,IACzB,SAAS,YAAY,IAAI,SAAS,GAAI;AAAA,IACtC,OAAO,YAAY,IAAI,OAAO,GAAI;AAAA,IAClC,WAAW,YAAY,IAAI,WAAW,GAAG;AAAA,EAC1C;AACD;AAZgB;AAchB,SAAS,YAAY,OAAgB,UAA0B;AAC9D,QAAM,IAAI,OAAO,KAAK;AACtB,SAAO,OAAO,UAAU,CAAC,KAAK,IAAI,IAAI,IAAI;AAC3C;AAHS;AAMF,SAAS,0BAA0B,MAAqC;AAC9E,MAAI,KAAK,SAAS,KAAM,MAAK,QAAQ;AACrC,MAAI,KAAK,MAAM,KAAM,MAAK,KAAK;AAC/B,MAAI,KAAK,UAAU,KAAM,MAAK,SAAS;AACvC,MAAI,KAAK,QAAQ,KAAM,MAAK,OAAO;AACnC,MAAI,KAAK,UAAU,KAAM,MAAK,SAAS;AACvC,MAAI,KAAK,WAAW,KAAM,MAAK,UAAU;AACzC,MAAI,KAAK,SAAS,KAAM,MAAK,QAAQ;AACrC,MAAI,KAAK,aAAa,KAAM,MAAK,YAAY;AAC7C,MAAI,CAAC,MAAM,QAAQ,KAAK,IAAI,EAAG,MAAK,OAAO,CAAC;AAC7C;AAVgB;AAaT,SAAS,qBACf,KACA,SACA,WACgB;AAChB,QAAM,SAAS,sBAAsB,OAAO;AAC5C,MAAI,CAAC,OAAO,OAAQ,QAAO;AAE3B,MAAI,SAAS,UAAU,KAAK,QAAQ;AACpC,MAAI,CAAC,QAAQ;AACZ,UAAM,UAAU,UAAU,KAAK,SAAS;AACxC,QAAI,SAAS;AACZ,UAAI;AACH,iBAAS,IAAI,IAAI,OAAO,EAAE;AAAA,MAC3B,QAAQ;AACP,cAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,YAAI,MAAM,UAAU,EAAG,UAAS,GAAG,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;AAAA,MACzD;AAAA,IACD;AAAA,EACD;AACA,SAAO,UAAU;AAClB;AArBgB;AAuBT,SAAS,iBACf,QACA,SACA,YACU;AACV,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,WAAW,IAAK,QAAO;AAC3B,QAAM,WAAW,SAAS;AAC1B,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,SAAS,OAAQ,QAAO;AACzD,MAAI,SAAS,SAAS,MAAM,EAAG,QAAO;AACtC,MAAI,cAAc,OAAO,SAAS,UAAU,EAAG,QAAO;AACtD,SAAO;AACR;AAZgB;;;ACpEhB,IAAO,cAAQ,wBAAC,OAAY,MAAW,CAAC,MAAM;AAC5C,OAAK,KAAK,KAAK;AAGf,WAAS,UAAU,KAAU,KAAqB;AAChD,WAAO,IAAI,QAAQ,IAAI,YAAY,CAAC,KAAK;AAAA,EAC3C;AAFS;AAIT,MAAI,gBAAwD;AAC5D,MAAI,mBAAmB;AAEvB,WAAS,eAAeC,QAAY,UAAkB;AACpD,UAAM,OAAOA,OAAM;AACnB,QAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,QAAI,CAAC,iBAAiB,qBAAqB,KAAK,QAAQ;AACtD,sBAAgB,KAAK,IAAI,CAAC,SAAiB,EAAE,KAAK,KAAK,MAAM,QAAQ,GAAG,GAAG,EAAE;AAC7E,yBAAmB,KAAK;AAAA,IAC1B;AACA,QAAI,CAAC,cAAe,QAAO;AAC3B,aAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC7C,YAAM,QAAQ,cAAc,CAAC;AAC7B,UAAI,aAAa,MAAM,QAAQ,SAAS,WAAW,MAAM,IAAI,GAAG;AAC9D,eAAO,MAAM;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAfS;AAiBT,WAAS,UAAU,KAAU,MAAc,SAAiB;AAC1D,QAAI,UAAU,MAAM;AAAA,MAClB,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC5C;AALS;AAMT,WAAS,QAAQ,KAAU,KAAU,SAAiB;AACpD,UAAM,UAAe,MAAM,QAAQ,OAAO;AAC1C,UAAM,SAAS,qBAAqB,KAAK,SAAS,SAAS;AAC3D,UAAM,OAAY,UAAU,KAAK,MAAM;AACvC,QAAI,iBAAiB,QAAQ,SAAS,IAAI,GAAG;AAC3C,UAAI,UAAU,+BAA+B,WAAW,MAAM,MAAM,MAAO;AAC3E,UAAI,UAAU,gCAAgC,oBAAoB;AAClE,UAAI,UAAU,gCAAgC,iDAAiD;AAG/F,UAAI,IAAI,WAAW,WAAW;AAC5B,YAAI,aAAa;AACjB,eAAO,IAAI,IAAI;AAAA,MACjB;AACA,UAAI,KAAa;AACjB,UAAI,QAAiB;AACrB,UAAI,UAAe,UAAkB;AAMrC,iBAAW,IAAI,IAAI,IAAI,KAAK,UAAU,UAAU,KAAK,MAAM,CAAC,EAAE;AAC9D,iBAAW,SAAS;AACpB,UAAI,MAAM,KAAK,UAAU,SAAS,OAAO,WAAW,OAAO,GAAG;AAC5D,gBAAQ;AACR,iBAAS,SAAS,MAAM,KAAK,OAAO,OAAO,EAAE,MAAM,KAAK,MAAM,mBAAmB,SAAS,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;AAAA,MACnH;AACA,UAAI,SAAS,OAAO,WAAW,MAAM,GAAG;AACtC,gBAAQ;AAAA,UACN,IAAI,mBAAmB,SAAS,OAAO,UAAU,CAAC,CAAC;AAAA,QACrD;AACA,YAAI,IAAI,IAAI,QAAQ,QAAQ,MAAM,IAAI;AAEpC,cAAI,KAAK,YAAY,KAAK,SAAS,CAAC,KAAK,OAAO,IAAI;AAClD,iBAAK,IAAI,SAAS,CAAC;AAEnB,oBAAQ,MAAM,KAAK,OAAO,SAAS,OAAO,IAAI,EAAE;AAChD,oBAAQ,OAAO,YAAY,IAAI,gBAAgB,MAAM,KAAK,EAAE,QAAQ,CAAC;AAAA,UACvE;AAAA,QACF;AAAA,MACF,OAAO;AACL,gBAAQ,OAAO,YAAY,IAAI,gBAAgB,SAAS,MAAM,EAAE,QAAQ,CAAC;AAAA,MAC3E;AAIA,YAAM,gBAAgB,eAAe,OAAO,QAAQ;AACpD,UAAI,CAAC,eAAe;AAClB,eAAO,UAAU,KAAK,KAAK,WAAW;AAAA,MACxC;AACA,YAAM,WAAW,YAAY,GAAG;AAChC,YAAM,UAAU,eAAe,OAAO,SAAS,QAAQ;AACvD,UAAI,CAAC,QAAQ,IAAI;AACf,eAAO,UAAU,KAAK,QAAQ,QAAQ,KAAK,QAAQ,WAAW,gBAAgB;AAAA,MAChF;AACA,YAAM,cAAc,6BAAM,eAAe,SAAS,QAAQ,GAAtC;AACpB,UAAI,KAAK,UAAU,WAAW;AAC9B,UAAI,KAAK,SAAS,WAAW;AAC7B,YAAM,YAAY;AAChB,cAAM,aAAa,MAAM,sBAAsB,KAAK,OAAO,QAAQ;AACnE,YAAI,CAAC,WAAW,IAAI;AAClB,sBAAY;AACZ,iBAAO,cAAc,KAAK,UAAU;AAAA,QACtC;AAEF,YAAI,QAAa,MAAM,cAAc,aAAa,IAAI,OAAO,KAAK;AAClE,YAAI,CAAC,OAAO;AACV,iBAAO,UAAU,KAAK,KAAK,iBAAiB;AAAA,QAC9C;AAEA,YAAI,UAAU,gBAAgB,iCAAiC;AAE/D,cAAM,KAAK,OAAO,IAAI,QAAQ,SAAS,UAAU,KAAK;AAEtD,YAAI;AACJ,YAAI;AACJ,YAAI,IAAI,IAAI,QAAQ,QAAQ,MAAM,IAAI;AACpC,qBAAW;AACX,mBAAS;AACT,cAAI,IAAI,WAAW,QAAQ;AAEzB,kBAAM,SAAmB,CAAC;AAE1B,kBAAM,UAAU,MAAM,YAAY,WAAW,MAAM,OAAO;AAC1D,gBAAI,WAAW;AACf,gBAAI,UAAU;AACd,gBAAI,GAAG,QAAQ,CAAC,UAAkB;AAChC,kBAAI,QAAS;AACb,0BAAY,MAAM;AAClB,kBAAI,WAAW,SAAS;AACtB,0BAAU;AACV,0BAAU,KAAK,KAAK,mBAAmB;AACvC,oBAAI,QAAQ;AACZ;AAAA,cACF;AACA,qBAAO,KAAK,KAAK;AAAA,YACnB,CAAC;AACD,gBAAI,GAAG,OAAO,MAAM;AAClB,kBAAI,QAAS;AACb,yBAAW,OAAO,OAAO,MAAM,EAAE,SAAS;AAE1C,sBAAQ,MAAM,KAAK,UAAU,UAAU,aAAa,SAAS;AAC7D,kBAAI,OAAO;AACT,sBAAM,UAAe,KAAK,MAAM,QAAQ;AACxC,2BAAW,MAAM,KAAK,OAAO,OAAO,EAAE,MAAM,QAAQ,CAAC;AACrD,oBAAI,SAAS,QAAQ,GAAG;AACtB,sBAAI;AACF,+BAAW,KAAK,MAAM,QAAQ;AAAA,kBAChC,SAAS,KAAK;AAAA,kBAAC;AAAA,gBACjB;AAAA,cACF;AAEA,kBAAI,KAAK,YAAY,KAAK,SAAS,CAAC,GAAG;AACrC,qBAAK,IAAI,SAAS,CAAC;AAEnB,2BAAW,MAAM,KAAK,OAAO,SAAS,UAAU,EAAE;AAAA,cACpD;AAEA,kBAAI,OAAO,QAAQ,OAAO,OAAO,SAAS,YAAY;AACpD,sBAAM,SAAc,EAAE,QAAQ,MAAM,UAAU,GAAG;AAEjD,oBAAI,SAAS,MAAM,KAAK,QAAQ,QAAQ;AACtC,yBAAO,SAAS,MAAM,KAAK,QAAQ;AAAA,gBACrC;AAEA,sBAAM,KAAK,KAAK,KAAK,SAAS,MAAM;AAAA,cACtC,OAAO;AACL,oBAAI,IAAI,QAAQ;AAAA,cAClB;AAAA,YACF,CAAC;AAAA,UACH,WAAW,IAAI,WAAW,OAAO;AAE/B,gBAAI,OAAO,OAAO,OAAO,OAAO,QAAQ,YAAY;AAElD,oBAAM,SAAc,EAAE,QAAQ,MAAM,QAAQ,GAAG;AAE/C,kBAAI,SAAS,MAAM,KAAK,QAAQ,QAAQ;AACtC,uBAAO,SAAS,MAAM,KAAK,QAAQ;AAAA,cACrC;AAEA,oBAAM,IAAI,KAAK,KAAK,SAAS,MAAM;AAAA,YACrC,OAAO;AACL,kBAAI,IAAI,KAAK,UAAU,MAAM,CAAC;AAAA,YAChC;AAAA,UACF;AAAA,QACF,OAAO;AAEL,cAAI,OAAO,KAAK,KAAK,GAAG,QAAQ;AAC9B,qBAAS;AAAA,UACX;AACA,cAAI,IAAI,WAAW,QAAQ;AACzB,kBAAM,KAAK,WAAW,SAAS,GAAG,EAC/B,KAAK,CAACC,cAAkB;AAEvB,kBAAI,OAAO,QAAQ,OAAO,OAAO,SAAS,YAAY;AACpD,sBAAM,KAAK,KAAK,KAAK,SAAS;AAAA,kBAC5B;AAAA,kBACA,MAAMA;AAAA,gBACR,CAAC;AAAA,cACH,OAAO;AACL,oBAAI,IAAIA,SAAQ;AAAA,cAClB;AAAA,YACF,CAAC,EACA,MAAM,CAAC,QAAa;AACnB,qBAAO,UAAU,KAAK,KAAK,sBAAsB;AAAA,YACnD,CAAC;AAAA,UACL;AAAA,QACF;AAAA,MACA,GAAG;AAAA,IACL,OAAO;AACL,YAAM,KAAK,OAAO,IAAI,QAAQ,IAAI,GAAG;AAAA,IACvC;AAAA,EACF;AA7KS;AA+KT,SAAO,EAAE,QAAQ;AACnB,GAlNe;;;ACHf,IAAO,aAAQ,wBAAC,OAAY,MAAW,CAAC,MAAM;AAC5C,OAAK,KAAK,KAAK;AAGf,QAAM,iBAAiB,oBAAI,IAAiB;AAC5C,QAAM,aAAa,mBAAmB,KAAK;AAE3C,WAAS,aAAa,YAAoB;AACxC,QAAI,CAAC,eAAe,IAAI,UAAU,GAAG;AACnC,qBAAe,IAAI,YAAY,MAAM,aAAa,UAAU,IAAI,KAAK,CAAC;AAAA,IACxE;AACA,WAAO,eAAe,IAAI,UAAU;AAAA,EACtC;AALS;AAQT,WAAS,aAAa,KAAU;AAC9B,QAAI,OAAO,SAAS,GAAG,GAAG;AACxB,YAAM,IAAI,SAAS;AAAA,IACrB;AACA,QAAI,QAAQ,QAAQ;AAAA,IACpB,WAAW,OAAO,QAAQ,UAAU;AAClC,UAAI;AACF,cAAM,KAAK,MAAM,GAAG;AAAA,MACtB,SAAS,KAAK;AAAA,MAAC;AAAA,IACjB;AACA,WAAO,YAAY,GAAG;AAAA,EACxB;AAXS;AAcT,WAAS,OAAO,KAAUC,KAAS,SAAiB,KAAU;AAC5D,QAAI;AACF,UAAI,UAAU,aAAa,GAAG;AAE9B,UAAI;AACJ,UAAI,YAAY,QAAQ;AAEtB,QAAAA,IAAG,OAAO,MAAM;AAChB;AAAA,MACF,OAAO;AACL,cAAM,eAAwB,OAAO,YAAY,YAAY,YAAY;AACzE,qBAAa,eACT,WAAW,QAAQ,SAAS,EAAE,IAC9B,WAAW,YAAY,OAAO;AAElC,YAAI,CAAC,cAAc,MAAM,eAAe,QAAQ;AAC9C,uBAAa,MAAM,cAAc,KAAK,CAAC,QAAgB;AACrD,gBAAI,cAAc;AAChB,qBAAO,SAAS,IAAI,WAAW,GAAG;AAAA,YACpC;AACA,mBAAO,OAAO,YAAY,YAAY,QAAQ,WAAW,GAAG;AAAA,UAC9D,CAAC;AAAA,QACH;AAEA,YAAI,CAAC,YAAY;AACf,gBAAM,UAAU,WAAW;AAAA,YACzB;AAAA,YACA,IAAAA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,WAAY;AACjB,mBAAa,UAAU,GAAG,OAAO,SAASA,KAAI,SAAS,GAAG;AAAA,IAC5D,SAAS,KAAK;AACZ,OAAC,MAAM,QAAQ,QAAQ,SAAS,MAAM,iBAAiB,eAAe,QAAQ,IAAI,UAAU,GAAG;AAAA,IACjG;AAAA,EACF;AAzCS;AA0CT,WAAS,YAAY,KAAU;AAC7B,QAAI,KAAK,IAAI,OAAO,MAAM,MAAM,QAAQ,QAAQ;AAC9C,UAAI,KAAK,MAAM,KAAK,OAAO,OAAO,EAAE,MAAM,IAAI,GAAG,CAAC;AAAA,IACpD;AACA,WAAO;AAAA,EACT;AALS;AAQT,WAAS,YAAYC,QAAY;AAE/B,QAAI,CAACA,OAAM,SAAS;AAClB,MAAAA,OAAM,UAAU;AAAA,QACd,eAAe;AAAA,UACb,UAAU,CAAC;AAAA,QACb;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,aAAa,6BAAM;AAEjB,cAAM,MAAMA,OAAM,QAAQ,QAAQ;AAClC,YAAI,MAAM,0BAA0B;AAAA,MACtC,GAJa;AAAA,IAKf;AAAA,EACF;AAhBS;AAkBT,SAAO,EAAE,QAAQ,YAAY;AAC/B,GAlGe;;;ACDf,IAAO,cAAQ,wBAAC,OAAY,MAAW,CAAC,MAAM;AAC1C,OAAK,KAAK,KAAK;AAEf,MAAI,gBAAyD;AAC7D,MAAI,mBAAmB;AAEvB,WAAS,kBAAkB,KAAe;AACtC,UAAM,SAAS,MAAM;AACrB,QAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,QAAI,CAAC,iBAAiB,qBAAqB,OAAO,QAAQ;AACtD,sBAAgB,OAAO,IAAI,CAAC,SAAiB,EAAE,KAAK,KAAK,OAAO,IAAI,GAAG,GAAG,EAAE;AAC5E,yBAAmB,OAAO;AAAA,IAC9B;AACA,QAAI,CAAC,cAAe,QAAO;AAC3B,UAAM,MAAM,IAAI,OAAO;AACvB,aAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC3C,YAAM,OAAO,cAAc,CAAC;AAC5B,UAAI,IAAI,WAAW,KAAK,KAAK,KAAK,MAAM,cAAc,KAAK,GAAG,GAAG;AAC7D,eAAO,KAAK;AAAA,MAChB;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAhBS;AAmBT,QAAM,YAAY,wBAAC,KAAU,MAAc,YAAoB;AAC3D,QAAI,UAAU,MAAM;AAAA,MAChB,gBAAgB;AAAA,IACpB,CAAC;AACD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9C,GALkB;AAMlB,WAAS,QAAQ,KAAU,KAAU,SAAiB;AAElD,UAAM,aAAa,kBAAkB,GAAG;AAExC,QAAI,CAAC,YAAY;AACb,aAAO,UAAU,KAAK,KAAK,WAAW;AAAA,IAC1C;AAEA,UAAM,WAAW,IAAI,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AAC5C,UAAM,YAAY;AAClB,YAAM,aAAa,MAAM,sBAAsB,KAAK,OAAO,OAAO;AAClE,UAAI,CAAC,WAAW,IAAI;AAChB,eAAO,cAAc,KAAK,UAAU;AAAA,MACxC;AAGA,YAAM,UAAU,MAAM,cAAc,UAAU,IAAI,KAAK;AACvD,UAAI,CAAC,SAAS;AACV,eAAO,UAAU,KAAK,KAAK,+BAA+B;AAAA,MAC9D;AAEA,UAAI,SAAS,QAAQ,OAAO,SAAS,SAAS,YAAY;AACtD,gBAAQ,KAAK,KAAK,KAAK,OAAO;AAAA,MAClC,OAAO;AACH,YAAI,IAAI,UAAU;AAAA,MACtB;AACA,UAAI,CAAC,SAAS;AACV,YAAI,UAAU,KAAK;AAAA,UACf,gBAAgB;AAAA,QACpB,CAAC;AACD,YAAI,IAAI,IAAI,GAAG;AAAA,MACnB,OAAO;AAAA,MAEP;AAAA,IACA,GAAG;AAAA,EACP;AAnCS;AAqCT,SAAO,EAAE,QAAQ;AACrB,GArEe;;;ACLf,IAAO,mBAAQ,wBAAC,OAAY,WAAmB;AAC3C,MAAI,CAAC,OAAO,UAAU;AAClB,UAAM,WAAW,CAAC;AAAA,EACtB;AACA,MAAI,CAAC,MAAM,SAAS,MAAM,GAAG;AACzB,UAAM,SAAS,MAAM,IAAI,EAAE,OAAO,oBAAI,IAAI,EAAE;AAAA,EAChD;AACA,WAAS,aAAa,SAAsB;AACxC,WAAO,SAAS,MAAM,SAAS;AAAA,EACnC;AAFS;AAGT,WAAS,eAAe;AACpB,WAAO,IAAI,QAAQ,CAACC,UAAc,WAAgB;AAC9C,YAAM,SAAS,MAAM,EAAE,SAAS,IAAI,MAAM;AAAA,QACtC,MAAM,QAAQ,cAAc,SAAS,MAAM;AAAA,MAC/C;AAEA,YAAM,SAAS,MAAM,EAAE,OAAO,YAAY,CAAC,UAAe;AACtD,0BAAkB,MAAM,IAAI;AAAA,MAChC;AAEA,YAAM,SAAS,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,QAAa;AACpD,cAAM,SAAS,MAAM,EAAE,OAAO;AAC9B,cAAM,WAAW,QAAQ,IAAI,QACzB,QAAQ;AAAA,UACJ;AAAA,UACA,GAAG,MAAM,IAAI,MAAM,QAAQ,cAAc,SAAS,MAAM,CAAC;AAAA,UACzD;AAAA,QACJ;AACJ,eAAO;AAAA,MACX,CAAC;AAED,YAAM,SAAS,MAAM,EAAE,OAAO,GAAG,SAAS,MAAM;AAC5C,cAAM,SAAS,MAAM,EAAE,OAAO;AAC9B,cAAM,WAAW,QAAQ,IAAI,QACzB,QAAQ;AAAA,UACJ;AAAA,UACA,GAAG,MAAM,IAAI,MAAM,QAAQ,cAAc,SAAS,MAAM,CAAC;AAAA,QAC7D;AACJ,eAAO;AAAA,MACX,CAAC;AAED,YAAM,SAAS,MAAM,EAAE,OAAO,SAAS,MAAM;AACzC,cAAM,WAAW,QAAQ,IAAI,QACzB,QAAQ;AAAA,UACJ;AAAA,UACA,GAAG,MAAM,IAAI,MAAM,QAAQ,cAAc,SAAS,MAAM,CAAC;AAAA,QAC7D;AACJ,cAAM,SAAS,MAAM,EAAE,OAAO;AAC9B,QAAAA,SAAQ;AAAA,MACZ;AAAA,IACJ,CAAC;AAAA,EACL;AAzCS;AA2CT,WAAS,aAAa,SAAiB;AACnC,QAAI,MAAM,SAAS,MAAM,EAAE,MAAM;AAC7B,YAAM,SAAS,MAAM,EAAE,OAAO,KAAK,OAAO;AAAA,IAC9C;AAAA,EACJ;AAJS;AAKT,WAAS,kBAAkB,SAAiB;AACxC,QAAI,MAAM,SAAS,MAAM,EAAE,MAAM;AAC7B,UAAI;AACA,cAAM,cAAmB,KAAK,MAAM,OAAO;AAC3C,cAAM,MAAc,aAAa,WAAW;AAC5C,cAAM,OAAO,MAAM,SAAS,MAAM,EAAE,MAAM,IAAI,GAAG;AACjD,YAAI,MAAM;AACN,gBAAM,SAAS,WAAW;AAC1B,cAAI,YAAY,MAAM,CAAC,YAAY,IAAI;AAAA,UAEvC,OAAO;AACH,kBAAM,SAAS,MAAM,EAAE,MAAM,OAAO,GAAG;AAAA,UAC3C;AAAA,QACJ;AAAA,MACJ,SAAS,GAAG;AAAA,MAAC;AAAA,IACjB;AAAA,EACJ;AAhBS;AAiBT,WAAS,YAAY,aAAkB;AACnC,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACpC,UAAI,MAAM,SAAS,MAAM,EAAE,MAAM;AAC7B,YAAI;AACA,gBAAM,UAAe,CAAC;AACtB,kBAAQ,YAAY,KAAK,IAAI;AAC7B,cAAI,CAAC,YAAY,IAAI;AACjB,wBAAY,KAAK,MAAM,KAAK,GAAG,KAAK,IAAI;AAAA,UAC5C;AACA,gBAAM,SAAS,MAAM,EAAE,MAAM;AAAA,YACzB,aAAa,WAAW;AAAA,YACxB;AAAA,cACI,UAAU,wBAAC,QAAa;AACpB,gBAAAA,SAAQ,GAAG;AAAA,cACf,GAFU;AAAA,cAGV,GAAG;AAAA,cACH,GAAG;AAAA,YACP;AAAA,UACJ;AACA,uBAAa,KAAK,UAAU,WAAW,CAAC;AAAA,QAC5C,SAAS,KAAK;AACV,iBAAO,GAAG;AAAA,QACd;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAzBS;AA0BT,WAAS,cAAc,aAAkB,IAAS;AAC9C,QAAI,MAAM,SAAS,MAAM,EAAE,MAAM;AAC7B,UAAI;AACA,cAAM,SAAS,MAAM,EAAE,MAAM,IAAI,aAAa,WAAW,GAAG;AAAA,UACxD,UAAU,wBAAC,QAAa;AACpB,eAAG,GAAG;AAAA,UACV,GAFU;AAAA,UAGV,GAAG;AAAA,QACP,CAAC;AACD,qBAAa,KAAK,UAAU,WAAW,CAAC;AAAA,MAC5C,SAAS,KAAK;AAAA,MAAC;AAAA,IACnB;AAAA,EACJ;AAZS;AAaT,WAAS,iBAAiB,aAAkB;AACxC,QAAI,aAAa,OAAO,SAAS;AAC7B,YAAM,SAAS,MAAM,EAAE,QAAQ,oBAAI,IAAI;AAAA,IAE3C,OAAO;AACH,YAAM,MAAc,aAAa,WAAW;AAC5C,YAAM,OAAO,MAAM,SAAS,MAAM,EAAE,MAAM,IAAI,GAAG;AACjD,UAAI,MAAM;AACN,cAAM,SAAS,MAAM,EAAE,MAAM,OAAO,GAAG;AAAA,MAC3C;AAAA,IACJ;AAAA,EACJ;AAXS;AAaT,SAAO;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AACJ,GAtIe;;;ACKf,IAAO,gBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACVA,IAAO,eAAQ,wBAAC,UAAe;AAC3B,WAAS,KAAK,SAAcC,KAAS,SAAiB,KAAU;AAC5D,UAAM,UAAU,OAAO,EAAE,OAAO,QAAQ,GAAGA,GAAE;AAAA,EACjD;AAFS;AAGT,SAAO,EAAE,KAAK;AAClB,GALe;;;ACAf,IAAO,cAAQ,wBAAC,UAAe;AAE3B,WAAS,UAAU,SAAcC,KAAS,SAAiB,KAAU;AACjE,QAAI;AACJ,QAAI,QAAQ,IAAI,QAAQ,OAAO,QAAQ,GAAG,SAAS,UAAU;AACzD,aAAO,QAAQ,GAAG;AAClB,aAAO,QAAQ,GAAG;AAAA,IACtB,OAAO;AACH,aAAO;AAAA,IACX;AACA,QAAI,CAAC,MAAM,IAAI,KAAK,MAAM,IAAI,GAAG;AAC7B,YAAM,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,MAAM,IAAI,KAAK,IAAI;AAAA,IAC/D;AACA,UAAM,IAAI,KAAK,MAAM,IAAI,EAAE,GAAG,KAAK,QAAQ,EAAE;AAC7C,UAAM,KAAK,GAAG,SAAS,MAAM;AACzB,cAAQ,KAAK,QAAQ,GAAG,MAAM,GAAG,EAAE,IAAI;AACvC,cAAQ,KAAK,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AACxC,aAAO,QAAQ;AACf,YAAM,KAAK,SAAS,aAAa,OAAO;AACxC,YAAM,UAAU,OAAO,EAAE,OAAO,SAAS,GAAGA,GAAE;AAC9C,YAAM,IAAI,KAAK,MAAM,IAAI,EAAE,KAAK,CAAC;AAAA,IACrC,GAAG,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE,EAAE;AAAA,EACpC;AApBS;AAqBT,WAAS,KAAK,SAAcA,KAAS,SAAiB,KAAU;AAC5D,QAAI,QAAQ,GAAG,SAAS,MAAM,GAAG;AAE7B,gBAAU,SAASA,KAAI,SAAS,GAAG;AAEnC,YAAM,UAAU,OAAO,EAAE;AAAA,QACrB,EAAE,IAAI,QAAQ,IAAI,IAAI,EAAE;AAAA,QACxB;AAAA,QACAA;AAAA,MACJ;AAAA,IACJ;AACA,UAAM,KAAK,QAAQ,YAAY,OAAO;AAAA,EAC1C;AAZS;AAaT,SAAO,EAAE,KAAK;AAClB,GArCe;;;ACGf,IAAO,aAAQ;AAAA,EACb;AAAA,EACA,YAAY;AACd;;;ACNA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAWjB,eAAe,SAAS,KAAU,OAAY,KAA+B;AAC3E,QAAM,sBAAsB,KAAK,KAAK;AACtC,SAAO,oBAAoB,GAAG,KAAK;AACrC;AAHe;AAKf,IAAO,oBAAQ,wBAAC,UAAe;AAC7B,QAAM;AAAA,IACJ,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,sBAAAC;AAAA,EACF,IAAI,MAAM,KAAK;AACf,QAAM,EAAE,aAAa,UAAU,MAAM,IAAI,MAAM,MAAM,UAAU,KAAK;AAEpE,WAAS,SAAS,KAAU;AAC1B,UAAM,OAAO,GAAG,GAAG;AAAA,EACrB;AAFS;AAOT,WAAS,OAAO,KAAkB;AAChC,QAAI,SAAiB,IAAI,QAAQ,OAAO,IAAI,MAAM;AAClD,QAAI,QAAQ;AACV,eAAS,mBAAmB,MAAM;AAAA,IACpC,OAAO;AACL,eAAS,IAAI,QAAQ,MAAM,IAAI,MAAM;AACrC,UAAI,QAAQ;AACV,iBAAS,mBAAmB,MAAM;AAClC,YAAI,WAAW,gBAAgB,WAAW,cAAc;AACtD,mBAAS,MAAM,WAAW,QAAQ,MAAM,UAAU;AAAA,QACpD,OAAO;AACL,mBAAS,MAAM,WAAW,QAAQ,OAAO,MAAM,KAAK;AAAA,QACtD;AAAA,MACF,OAAO;AACL,iBAAS,MAAM,WAAW,QAAQ,MAAM,UAAU;AAAA,MACpD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAlBS;AAuBT,iBAAe,KAAK,KAAU,KAAU,SAAiB,KAAU;AACjE,UAAM,MAAM,IAAI;AAEhB,QAAI,IAAI,WAAW,gCAAgC,GAAG;AACpD,UAAI;AACF,cAAM,MAAM,KAAK,GAAG,IAAI,IAAI;AAC5B,oBAAY,KAAK,MAAM,GAAG;AAAA,MAC5B,SAAS,KAAK;AACZ,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC9C,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAClH,UAAI;AACF,cAAM,OAAO,WAAW,IAAI,IAAI;AAChC,cAAM,MAAM,KAAK,OAAO,OAAO,IAAI,IAAI;AACvC,oBAAY,KAAK,MAAM,GAAG;AAAA,MAC5B,SAAS,KAAK;AACZ,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AACjD,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC3E,UAAI;AACF,cAAM,UAAU,OAAO,GAAG;AAC1B,cAAM,UAAU,mBAAmB,IAAI,QAAQ,QAAQ,IAAI,MAAM,IAAI;AACrE,cAAM,WAAWA,sBAAqB,SAAS,OAAO;AACtD,cAAMJ,YAAW,QAAQ;AACzB,cAAM,UAAU,QAAQ;AACxB,cAAM,UACJ,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,OAAO,IAAI,QAAQ,EAAE;AACjE,cAAMK,IAAG,UAAU,UAAU,SAAS,MAAM;AAC5C,cAAM,UAAU,QAAQ;AACxB,oBAAY,KAAK,UAAU,GAAG;AAAA,MAChC,SAAS,KAAK;AACZ,cAAM,SAAS,UAAU,GAAG;AAC5B,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAAA,EACF;AA9Ce;AAmDf,iBAAe,IAAI,KAAU,KAAU,SAAiB,KAAU;AAChE,UAAM,MAAM,IAAI;AAGhB,QAAI,IAAI,WAAW,iCAAiC,GAAG;AACrD,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAClH,UAAI;AACF,cAAM,KAAK,mBAAmB,IAAI,QAAQ,MAAM,IAAI,MAAM,MAAM,QAAQ;AACxE,YAAI,CAAC,qBAAqB,KAAK,KAAK,kBAAkB,KAAK,MAAM,OAAO,YAAY,OAAO,YAAY,OAAO,QAAQ;AACpH,gBAAM,OAAO,OAAO,QAAQ,QAAQ;AACpC,gBAAM,SAAS,MAAM,kBAAkB,OAAO,EAAE,MAAmB,QAAQ,OAAO,QAAQ,QAAQ,GAAG,CAAC;AACtG,gBAAM,WAAW,uBAAuB,MAAM;AAC9C,cAAI,SAAS,QAAQ;AACnB,kBAAM,QAAQ,SAAS,EAAE,IAAI,SAAS,MAAM;AAC5C,mBAAO,YAAY,KAAK,EAAE,UAAU,WAAW,KAAK,GAAG,GAAG;AAAA,UAC5D;AAAA,QACF;AACA,cAAM,MAAMC,MAAK,QAAQ,OAAO,GAAG,CAAC;AACpC,YAAI,CAAC,KAAK;AACR,gBAAM,QAAQ,oBAAoB;AAClC,iBAAO,SAAS,KAAK,aAAa,GAAG;AAAA,QACvC;AACA,cAAM,QAAQ,GAAG;AACjB,cAAM,QAAQ,MAAMJ,YAAW,GAAG;AAClC,cAAM,QAAQ,GAAG,MAAM,SAAS,MAAM,QAAQ;AAC9C,oBAAY,KAAK,OAAO,GAAG;AAAA,MAC7B,SAAS,KAAK;AACZ,cAAM,SAAS,cAAc,GAAG;AAChC,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AACjD,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAClH,UAAI;AACF,cAAM,KAAK,mBAAmB,IAAI,QAAQ,MAAM,IAAI,MAAM,MAAM,QAAQ;AACxE,cAAM,UAAU,mBAAmB,IAAI,QAAQ,QAAQ,IAAI,MAAM,IAAI;AACrE,YAAI,CAAC,qBAAqB,KAAK,KAAK,kBAAkB,KAAK,MAAM,OAAO,YAAY,OAAO,YAAY,OAAO,QAAQ;AACpH,gBAAMK,QAAO,MAAM,oBAAoB,OAAO,IAAI,OAAO;AACzD,cAAIA,OAAM;AACR,kBAAM,QAAQ,SAAS,EAAE,IAAI,OAAO,EAAE;AACtC,mBAAO,YAAY,KAAKA,OAAM,GAAG;AAAA,UACnC;AAAA,QACF;AACA,cAAM,UAAU,OAAO,GAAG;AAC1B,cAAM,WAAWH,sBAAqB,SAAS,OAAO;AACtD,cAAM,SAAS,MAAMH,YAAW,QAAQ;AACxC,YAAI,CAAC,QAAQ;AACX,gBAAM,QAAQ,QAAQ;AACtB,iBAAO,SAAS,KAAK,aAAa,GAAG;AAAA,QACvC;AACA,cAAM,QAAQ,QAAQ;AACtB,cAAM,OAAO,MAAMI,IAAG,SAAS,UAAU,MAAM;AAC/C,oBAAY,KAAK,MAAM,GAAG;AAAA,MAC5B,SAAS,KAAK;AACZ,cAAM,SAAS,UAAU,GAAG;AAC5B,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AACjD,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC3E,UAAI;AACF,cAAM,UAAU,OAAO,GAAG;AAC1B,cAAM,UAAU,mBAAmB,IAAI,QAAQ,QAAQ,IAAI,MAAM,IAAI;AACrE,cAAM,WAAW,QAAQ,MAAM,OAAO,EAAE,IAAI,KAAK;AACjD,YAAI,kBAAkB,KAAK,GAAG;AAC5B,gBAAM,yBAAyB,OAAO,QAAQ,EAAE,MAAM,MAAM,MAAS;AAAA,QACvE;AACA,cAAM,WAAWD,sBAAqB,SAAS,OAAO;AACtD,cAAM,UAAU,QAAQ;AACxB,cAAMD,YAAW,QAAQ;AACzB,cAAM,UAAU,YAAY;AAC5B,oBAAY,KAAK,UAAU,GAAG;AAAA,MAChC,SAAS,KAAK;AACZ,cAAM,SAAS,UAAU,GAAG;AAC5B,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAAA,EACF;AApFe;AAsFf,SAAO,EAAE,MAAM,IAAI;AACrB,GAlLe;;;ACZR,SAAS,cAAc,OAAqB;AAClD,QAAM,MAAM,OAAO,YAAY,QAAQ;AACvC,SAAO,CAAC,EAAE,KAAK,WAAW,aAAa,KAAK;AAC7C;AAHgB;AAKT,SAAS,aAAa,OAAoB;AAChD,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,EAAG,QAAO,QAAQ,KAAK;AACvE,QAAM,UAAU,OAAO,YAAY,QAAQ,MAAM;AACjD,SAAO,OAAO,YAAY,WAAW,QAAQ,KAAK,IAAI;AACvD;AALgB;AAOT,SAAS,iBAAiB,OAAY,KAAmB;AAC/D,MAAI,CAAC,cAAc,KAAK,EAAG,QAAO;AAClC,QAAM,WAAW,aAAa,KAAK;AACnC,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,SAAS,KAAK,UAAU,cAAc,KAAK,KAAK,UAAU,WAAW;AAC3E,MAAI,OAAO,WAAW,YAAY,WAAW,SAAU,QAAO;AAC9D,QAAM,IAAI,KAAK,SAAS,CAAC;AACzB,QAAM,SAAS,EAAE,cAAc,EAAE;AACjC,SAAO,OAAO,WAAW,YAAY,WAAW;AACjD;AATgB;AAchB,eAAsB,oBAAoB,KAAU,OAAY,QAAQ,GAA2B;AAClG,MAAI,iBAAiB,OAAO,GAAG,EAAG,QAAO;AACzC,QAAM,sBAAsB,KAAK,KAAK;AACtC,SAAO,oBAAoB,GAAG,KAAK,QAAQ,SAAS;AACrD;AAJsB;AAMtB,eAAsB,qBAAqB,KAAU,OAAY,OAAiC;AACjG,MAAI,iBAAiB,OAAO,GAAG,EAAG,QAAO;AACzC,QAAM,sBAAsB,KAAK,KAAK;AACtC,SAAO,oBAAoB,GAAG,KAAK;AACpC;AAJsB;;;ACtBtB,SAAS,MAAM,KAA2B;AACxC,SAAO,QAAQ,SAAS,SAAS;AACnC;AAFS;AAIT,eAAe,iBAAiB,KAAU,OAA2B;AACnE,MAAI,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,SAAS,CAAC,GAAG;AACnD,UAAM,sBAAsB,KAAK,KAAK;AAAA,EACxC;AACF;AAJe;AAMf,IAAO,0BAAQ,wBAAC,UAAe;AAC7B,QAAM,EAAE,aAAa,SAAS,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AACnE,QAAM,KAAK,MAAM,KAAK;AAEtB,iBAAe,IAAI,KAAU,KAAU,SAAiB,KAAU;AAChE,UAAM,MAAM,IAAI,OAAO;AAEvB,QAAI,IAAI,WAAW,uCAAuC,GAAG;AAC3D,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACF,cAAM,KAAK,MAAM,IAAI,QAAQ,MAAM,IAAI,MAAM,EAAE;AAC/C,YAAI,OAAO,MAAM,GAAG,sBAAsB,OAAO,EAAE;AACnD,YAAI,kBAAkB,KAAK,KAAK,CAAC,qBAAqB,KAAK,GAAG;AAC5D,gBAAM,SAAS,MAAM,kBAAkB,OAAO,EAAE,MAAM,gBAAgB,GAAG,CAAC;AAC1E,gBAAM,YAAY,0BAA0B,QAAQ,EAAE;AACtD,gBAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,MAAW,EAAE,IAAI,CAAC;AAClD,qBAAW,KAAK,WAAW;AACzB,gBAAI,CAAC,MAAM,IAAI,EAAE,IAAI,EAAG,MAAK,KAAK,CAAC;AAAA,UACrC;AAAA,QACF;AACA,eAAO,YAAY,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG,GAAG;AAAA,MAClD,SAAS,KAAU;AACjB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC/C;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,mCAAmC,GAAG;AACvD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACF,cAAM,OAAO,mBAAmB,IAAI,QAAQ,QAAQ,IAAI,MAAM,QAAQ,EAAE;AACxE,cAAM,KAAK,MAAM,IAAI,QAAQ,MAAM,IAAI,MAAM,EAAE;AAC/C,YAAI,CAAC,KAAM,QAAO,SAAS,KAAK,iBAAiB,GAAG;AACpD,cAAM,UAAU,MAAM,GAAG,qBAAqB,OAAO,MAAM,EAAE;AAC7D,eAAO,YAAY,KAAK,EAAE,IAAI,GAAG,QAAQ,GAAG,GAAG;AAAA,MACjD,SAAS,KAAU;AACjB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC/C;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,kCAAkC,GAAG;AACtD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACF,eAAO,YAAY,KAAK,GAAG,wBAAwB,KAAK,GAAG,GAAG;AAAA,MAChE,SAAS,KAAU;AACjB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AA3Ce;AA6Cf,iBAAe,KAAK,KAAU,KAAU,SAAiB,KAAU;AACjE,UAAM,MAAM,IAAI,OAAO;AAEvB,QAAI,IAAI,WAAW,mCAAmC,GAAG;AACvD,UAAI,CAAE,MAAM,qBAAqB,KAAK,OAAO,uBAAuB,OAAO,YAAY,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AACjI,YAAM,iBAAiB,KAAK,KAAK;AACjC,YAAM,KAAK,oBAAoB,GAAG;AAClC,YAAM,KAAK,mBAAmB,GAAG;AACjC,UAAI;AACF,cAAM,OAAO,OAAO,IAAI,SAAS,WAAW,KAAK,MAAM,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,CAAC;AACxF,cAAM,OAAO,OAAO,KAAK,QAAQ,EAAE;AACnC,cAAM,KAAK,MAAM,KAAK,EAAE;AACxB,YAAI,CAAC,KAAM,QAAO,SAAS,KAAK,iBAAiB,GAAG;AACpD,cAAM,SAAS,MAAM,GAAG;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA,YACE,IAAI,KAAK,OAAO,EAAE,IAAI;AAAA,YACtB;AAAA,YACA,QAAQ,KAAK,SAAS,OAAO,KAAK,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI;AAAA,YAC1D,OAAO,CAAC,CAAC,KAAK;AAAA,UAChB;AAAA,UACA;AAAA,QACF;AACA,eAAO,YAAY,KAAK,EAAE,IAAI,GAAG,OAAO,GAAG,GAAG;AAAA,MAChD,SAAS,KAAU;AACjB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AA7Be;AA+Bf,SAAO,EAAE,KAAK,KAAK;AACrB,GAjFe;;;ACHf,SAAS,WAAW,KAAkC;AACrD,QAAM,IAAI,IAAI,UAAU,IAAI,QAAQ,CAAC;AACrC,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,CAAC,GAAG;AACvC,QAAI,KAAK,QAAQ,MAAM,GAAI,KAAI,CAAC,IAAI,OAAO,CAAC;AAAA,EAC7C;AACA,SAAO;AACR;AAPS;AAST,SAAS,UAAU,KAAmC;AACrD,MAAI,CAAC,KAAK,KAAM,QAAO,CAAC;AACxB,MAAI,OAAO,IAAI,SAAS,UAAU;AACjC,QAAI;AAAE,aAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IAAG,QAAQ;AAAE,aAAO,CAAC;AAAA,IAAG;AAAA,EACzD;AACA,SAAO,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,CAAC;AACnD;AANS;AAQT,IAAO,qBAAQ,wBAAC,UAAe;AAC9B,QAAM,EAAE,aAAa,SAAS,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AACnE,QAAM,KAAK,MAAM,KAAK;AAEtB,iBAAe,IAAI,KAAU,KAAU,SAAiB,KAAU;AACjE,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,IAAI,WAAW,GAAG;AAExB,QAAI,IAAI,WAAW,4BAA4B,GAAG;AACjD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,eAAO,YAAY,KAAK,gBAAgB,KAAK,GAAG,GAAG;AAAA,MACpD,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,2BAA2B,GAAG;AAChD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI,CAAC,kBAAkB,KAAK,GAAG;AAC9B,eAAO,YAAY,KAAK,EAAE,OAAO,YAAY,SAAS,+BAA+B,QAAQ,gBAAgB,KAAK,EAAE,GAAG,GAAG;AAAA,MAC3H;AACA,UAAI;AACH,cAAM,YAAY,sBAAsB,KAAK;AAC7C,cAAM,QAAQ,MAAM,gBAAgB,KAAK;AACzC,eAAO,YAAY,KAAK,EAAE,OAAO,WAAW,OAAO,QAAQ,gBAAgB,KAAK,EAAE,GAAG,GAAG;AAAA,MACzF,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,gCAAgC,GAAG;AACrD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,cAAM,KAAK,EAAE,OAAO,SAAS,SAAS;AACtC,cAAM,SAAS,MAAM,oBAAoB,OAAO,EAAE;AAClD,eAAO,YAAY,KAAK,QAAQ,GAAG;AAAA,MACpC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,4BAA4B,GAAG;AACjD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI,CAAC,kBAAkB,KAAK,EAAG,QAAO,SAAS,KAAK,yBAAyB,GAAG;AAChF,UAAI;AACH,cAAM,SAAS,MAAM,kBAAkB,OAAO;AAAA,UAC7C,MAAM,EAAE,OAAQ,EAAE,OAAmB;AAAA,UACrC,IAAI,EAAE,KAAM,EAAE,KAA8B;AAAA,UAC5C,QAAQ,EAAE,UAAU,EAAE,MAAM;AAAA,UAC5B,SAAS,EAAE,WAAW,EAAE,KAAK;AAAA,UAC7B,YAAY,EAAE,cAAc;AAAA,UAC5B,cAAc,EAAE,gBAAgB,OAAO,OAAO,EAAE,YAAY,IAAI;AAAA,UAChE,WAAW,EAAE,aAAa;AAAA,UAC1B,SAAS,EAAE,WAAW;AAAA,UACtB,SAAS,EAAE,WAAW;AAAA,UACtB,OAAO,EAAE,SAAS,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,UAC3C,QAAQ,EAAE,UAAU,OAAO,OAAO,EAAE,MAAM,IAAI;AAAA,QAC/C,CAAC;AACD,eAAO,YAAY,KAAK,QAAQ,GAAG;AAAA,MACpC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,4BAA4B,GAAG;AACjD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,cAAM,OAAQ,EAAE,QAAQ;AACxB,cAAM,SAAU,EAAE,UAAU;AAC5B,cAAM,WAAW,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,EAAE;AAC1D,cAAM,KAAK,EAAE,OAAO,SAAS,SAAS;AACtC,cAAM,SAAS,EAAE,UAAU,EAAE,MAAM;AACnC,YAAI,CAAC,YAAY,SAAS,eAAgB,QAAO,SAAS,KAAK,iBAAiB,GAAG;AACnF,cAAM,UAAU,MAAM,iBAAiB,OAAO;AAAA,UAC7C;AAAA,UACA,IAAI,SAAS,iBAAiB,KAAK;AAAA,UACnC,UAAU,YAAY;AAAA,UACtB;AAAA,UACA;AAAA,QACD,CAAC;AACD,eAAO,YAAY,KAAK,SAAS,GAAG;AAAA,MACrC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,8BAA8B,GAAG;AACnD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,eAAO,YAAY,KAAK,GAAG,wBAAwB,KAAK,GAAG,GAAG;AAAA,MAC/D,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AAClD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,cAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,8BAA8B;AAC5E,eAAO,YAAY,KAAK,qBAAqB,KAAK,GAAG,GAAG;AAAA,MACzD,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,gCAAgC,GAAG;AACrD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI,CAAC,kBAAkB,KAAK,EAAG,QAAO,SAAS,KAAK,yBAAyB,GAAG;AAChF,UAAI;AACH,cAAM,OAAO,EAAE,OAAO,OAAO,EAAE,IAAI,IAAI;AACvC,cAAM,KAAK,EAAE,KAAK,OAAO,EAAE,EAAE,IAAI;AACjC,cAAM,SAAS,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI;AAC7D,cAAM,SAAS,MAAM,kBAAkB,OAAO,EAAE,MAAmB,IAAI,OAAO,CAAC;AAC/E,YAAI,SAAS,kBAAkB,IAAI;AAClC,iBAAO,YAAY,KAAK,EAAE,OAAO,0BAA0B,QAAQ,MAAM,MAAM,GAAG,IAAI,MAAM,OAAO,GAAG,GAAG;AAAA,QAC1G;AACA,YAAI,SAAS,SAAS,SAAS,SAAS,SAAS,YAAY,QAAQ;AACpE,gBAAM,WAAW,SAAS,WACvB,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,IAAI,CAAC,OAAO;AAAA,YACvD,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,YAAY,EAAE;AAAA,YACd,QAAQ,EAAE;AAAA,YACV,WAAW;AAAA,UACZ,EAAE,IACA,uBAAuB,MAAM;AAChC,iBAAO,YAAY,KAAK,EAAE,UAAU,OAAO,GAAG,GAAG;AAAA,QAClD;AACA,eAAO,YAAY,KAAK,EAAE,OAAO,GAAG,GAAG;AAAA,MACxC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,4BAA4B,GAAG;AACjD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI,CAAC,kBAAkB,KAAK,EAAG,QAAO,SAAS,KAAK,yBAAyB,GAAG;AAChF,UAAI;AACH,cAAM,KAAK,EAAE;AACb,YAAI,MAAM,MAAM;AACf,gBAAM,MAAM,MAAM,gBAAgB,OAAO,EAAE;AAC3C,cAAI,CAAC,IAAK,QAAO,SAAS,KAAK,aAAa,GAAG;AAC/C,iBAAO,YAAY,KAAK,EAAE,OAAO,IAAI,GAAG,GAAG;AAAA,QAC5C;AACA,cAAM,OAAO,OAAO,EAAE,QAAQ,EAAE;AAChC,cAAM,WAAW,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,EAAE;AAC1D,cAAM,KAAK,EAAE,KAAK,OAAO,EAAE,EAAE,IAAI;AACjC,cAAM,SAAS,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI;AAE7D,YAAI,SAAS,SAAS,SAAS,SAAU,CAAC,QAAQ,SAAS,WAAW,MAAM,GAAI;AAC/E,gBAAM,UAAU,MAAM,oBAAoB,OAAO,QAAQ,QAAQ;AACjE,iBAAO,YAAY,KAAK,SAAS,GAAG;AAAA,QACrC;AAEA,YAAI,SAAS,kBAAkB,SAAS,SAAS,UAAU,GAAG;AAC7D,gBAAM,UAAU,MAAM,GAAG,qBAAqB,OAAO,UAAU,OAAO,SAAS,SAAS,MAAM;AAC9F,iBAAO,YAAY,KAAK,EAAE,IAAI,MAAM,QAAQ,GAAG,SAAS,WAAW,KAAK,GAAG,GAAG;AAAA,QAC/E;AAEA,cAAM,OAAO,MAAM,iBAAiB,OAAO;AAAA,UAC1C;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,OAAO,OAAO,EAAE,KAAK,KAAK;AAAA,QAC3B,CAAC;AACD,eAAO,YAAY,KAAK,EAAE,SAAS,KAAK,GAAG,GAAG;AAAA,MAC/C,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAAA,EACD;AAzKe;AA2Kf,iBAAe,KAAK,KAAU,KAAU,SAAiB,KAAU;AAClE,UAAM,MAAM,IAAI,OAAO;AACvB,QAAI,CAAC,IAAI,WAAW,6BAA6B,EAAG;AACpD,QAAI,CAAE,MAAM,qBAAqB,KAAK,OAAO,uBAAuB,OAAO,YAAY,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AACjI,QAAI;AACH,YAAM,OAAO,UAAU,GAAG;AAC1B,YAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,UAAI,CAAC,QAAQ,OAAO,OAAQ,OAAO,KAAM,QAAO,SAAS,KAAK,gBAAgB,GAAG;AACjF,YAAM,KAAK,KAAK,OAAO,SAAS,SAAS;AACzC,YAAM,SAAS,MAAM,wBAAwB,OAAO;AAAA,QACnD;AAAA,QACA;AAAA,QACA,QAAQ,CAAC,CAAC,KAAK;AAAA,QACf,UAAU,mBAAmB,GAAG;AAAA,MACjC,CAAC;AACD,aAAO,YAAY,KAAK,QAAQ,GAAG;AAAA,IACpC,SAAS,KAAU;AAClB,aAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,IAC9C;AAAA,EACD;AAnBe;AAqBf,SAAO,EAAE,KAAK,KAAK;AACpB,GArMe;;;ACvCf,YAAYK,SAAQ;AACpB,YAAYC,eAAc;AAiB1B,IAAI,WAAkC;AAEtC,SAAS,gBAAgB,OAAoB;AAC3C,QAAM,OAAO,OAAO,cAAc,QAAQ,IAAI;AAC9C,SAAgB,eAAK,MAAM,4BAA4B;AACzD;AAHS;AAKF,SAAS,eAAe,OAA4B;AACzD,MAAI,SAAU,QAAO;AACrB,QAAM,WAAW,gBAAgB,KAAK;AACtC,MAAI;AACF,UAAM,MAAS,iBAAa,UAAU,MAAM;AAC5C,eAAW,KAAK,MAAM,GAAG;AAAA,EAC3B,QAAQ;AACN,eAAW,EAAE,SAAS,KAAK,QAAQ,CAAC,EAAE;AAAA,EACxC;AACA,MAAI,MAAO,OAAM,aAAa;AAC9B,SAAO;AACT;AAXgB;AAaT,SAAS,SAAS,IAAmC;AAC1D,SAAO,UAAU,SAAS,EAAE,KAAK;AACnC;AAFgB;AAIT,SAAS,SAAS,IAAqB;AAC5C,SAAO,CAAC,CAAC,SAAS,EAAE;AACtB;AAFgB;AAIT,SAAS,SAAS,OAAY,IAAY,QAAyB;AACxE,QAAM,QAAQ,SAAS,EAAE;AACzB,QAAM,QAAQ,OAAO,QAAQ,QAAQ;AACrC,MAAI,OAAO;AACT,UAAM,OAAO,EAAE,KAAK,MAAM,MAAM,IAAI,MAAM,UAAU,IAAI,QAAQ,SAAS,SAAS,EAAE;AAAA,EACtF,OAAO;AACL,UAAM,OAAO,EAAE,KAAK,kBAAkB,QAAQ,SAAS,SAAS,EAAE;AAAA,EACpE;AACF;AARgB;AAUT,SAAS,oBAAoB,KAA6D;AAC/F,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,UAAM,IAAI;AACV,QAAI,OAAO,EAAE,OAAO,UAAU;AAC5B,YAAM,KAAK,MAAM,QAAQ,EAAE,EAAE,IACzB,EAAE,GAAG,IAAI,MAAM,IACf,EAAE,MAAM,OACN,CAAC,OAAO,EAAE,EAAE,CAAC,IACb;AACN,aAAO,EAAE,IAAI,EAAE,IAAI,GAAG;AAAA,IACxB;AAAA,EACF;AACA,MAAI,OAAO,QAAQ,YAAY,SAAS,GAAG,GAAG;AAC5C,WAAO,EAAE,IAAI,IAAI;AAAA,EACnB;AACA,SAAO,EAAE,KAAK,IAAI;AACpB;AAhBgB;AAkBhB,IAAO,oBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC7EA,IAAO,qBAAQ,wBAAC,UAAe;AAC9B,QAAM,EAAE,aAAa,SAAS,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AAEnE,WAAS,IAAI,KAAU,KAAU,UAAkB,KAAU;AAC5D,UAAM,MAAM,IAAI,OAAO;AACvB,QAAI,IAAI,WAAW,sBAAsB,GAAG;AAC3C,UAAI;AACH,eAAO,YAAY,KAAK,eAAe,KAAK,GAAG,GAAG;AAAA,MACnD,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAAA,EACD;AATS;AAWT,SAAO,EAAE,IAAI;AACd,GAfe;;;ACHf,IAAO,uBAAQ,wBAAC,UAAe;AAC7B,QAAM,EAAE,aAAa,UAAU,MAAM,IAAI,OAAO,MAAM,UAAU,KAAK,KAAK,CAAC;AAC3E,WAAS,SAAS,KAAY;AAC5B,YAAQ,UAAU,GAAG,GAAG;AAAA,EAC1B;AAFS;AAIT,SAAO,MAAM,KAAK,KAAK,OAAO;AAAA,IAC5B,MAAM;AAAA,IACN,KAAK;AAAA,MACH,UAAU;AAAA,MACV,QAAQ;AAAA,IACV;AAAA,IACA,OAAO;AAAA,MACL,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM,CAAC,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,OAAO;AAAA,IAC1G;AAAA,IACA,MAAM,8BAAO,KAAU,KAAU,SAAiB,KAAU,gBAAqB;AAC/E,UAAI,IAAI,IAAI,WAAW,6BAA6B,GAAG;AACrD,YAAI;AACF,gBAAM,QAAQ,0BAA0B;AACxC,wBAAc,KAAK,EAAE,MAAM,OAAO,GAAG,GAAG;AAAA,QAC1C,SAAS,KAAK;AACZ,gBAAM,SAAS,gBAAgB,GAAG;AAAA,QACpC;AACA,eAAO;AAAA,MACT;AAAA,IACF,GAVM;AAAA,IAWN,KAAK,8BAAO,KAAU,KAAU,SAAiB,KAAU,eAAoB;AAC7E,UAAI,IAAI,IAAI,WAAW,4BAA4B,GAAG;AACpD,YAAI;AACF,gBAAM,UAAe,IAAI;AACzB,gBAAM,UAAU,QAAQ,KAAK;AAC7B,gBAAM,QAAQ,MAAM,WAAW,MAAM;AAAA,YACnC,MAAM;AAAA,YACN,OAAO,QAAQ;AAAA,UACjB,CAAC;AACD,gBAAM,UAAU,WAAW;AAC3B,wBAAc,KAAK,OAAO,GAAG;AAAA,QAC/B,SAAS,OAAO;AACd,gBAAM,SAAS,UAAU,KAAK;AAC9B,qBAAW,KAAK,OAAO,GAAG;AAAA,QAC5B;AACA,eAAO;AAAA,MACT;AAAA,IACF,GAjBK;AAAA,EAkBP,CAAC;AACH,GA/Ce;;;ACGf,OAAOC,SAAQ;AAEf,SAAS,SAAS,MAAc,OAAwB,QAAyC;AAChG,QAAM,MAAM,SACT,IAAI,OAAO,QAAQ,MAAM,EACxB,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,OAAO,CAAC,EAAE,QAAQ,MAAM,KAAK,CAAC,GAAG,EAC1D,KAAK,GAAG,CAAC,MACV;AACH,SAAO,GAAG,IAAI,GAAG,GAAG,IAAI,KAAK;AAC9B;AAPS;AAST,IAAO,iBAAQ,wBAAC,UAAe;AAC9B,QAAM,EAAE,aAAa,SAAS,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AAEnE,iBAAe,IAAI,KAAU,KAAU,UAAkB,KAAU;AAClE,UAAM,MAAM,IAAI,OAAO;AAEvB,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC/C,UAAI;AACH,cAAM,MAAM,QAAQ,YAAY;AAChC,YAAI,YAAY;AAChB,YAAI,UAAU;AACd,mBAAW,OAAO,OAAO,OAAO,MAAM,mBAAmB,CAAC,CAAC,GAAG;AAC7D,uBAAc,KAAsB,QAAQ;AAAA,QAC7C;AACA,mBAAW,OAAO,OAAO,OAAO,MAAM,iBAAiB,CAAC,CAAC,GAAG;AAC3D,qBAAY,KAAsB,QAAQ;AAAA,QAC3C;AACA,cAAM,QAAQ;AAAA,UACb;AAAA,UACA;AAAA,UACA,SAAS,uBAAuB,KAAK,MAAM,QAAQ,OAAO,CAAC,CAAC;AAAA,UAC5D;AAAA,UACA;AAAA,UACA,SAAS,yBAAyB,IAAI,GAAG;AAAA,UACzC;AAAA,UACA;AAAA,UACA,SAAS,yBAAyB,SAAS;AAAA,UAC3C;AAAA,UACA;AAAA,UACA,SAAS,uBAAuB,OAAO;AAAA,UACvC;AAAA,UACA;AAAA,UACA,SAAS,mBAAmBC,IAAG,QAAQ,EAAE,CAAC,KAAK,CAAC;AAAA,QACjD;AACA,YAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,eAAO,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,MACvC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,yBAAyB,GAAG;AAC9C,aAAO;AAAA,QACN;AAAA,QACA;AAAA,UACC,QAAQ,QAAQ,OAAO;AAAA,UACvB,MAAM,QAAQ;AAAA,UACd,UAAU,QAAQ;AAAA,UAClB,QAAQ,QAAQ,YAAY;AAAA,UAC5B,OAAO;AAAA,YACN,MAAM,OAAO;AAAA,cACZ,OAAO,QAAQ,MAAM,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAI,GAAoB,QAAQ,CAAC,CAAC;AAAA,YAChG;AAAA,YACA,IAAI,OAAO;AAAA,cACV,OAAO,QAAQ,MAAM,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAI,GAAoB,QAAQ,CAAC,CAAC;AAAA,YAC9F;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,EACD;AA1De;AA4Df,SAAO,EAAE,IAAI;AACd,GAhEe;;;ACTf,SAAS,gBAAgB,OAAwB;AAChD,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,UAAM,IAAI,MAAM,WAAW,CAAC;AAC5B,QAAI,MAAM,IAAM,QAAO;AACvB,QAAI,KAAK,MAAQ,MAAM,KAAQ,MAAM,MAAQ,MAAM,GAAM,QAAO;AAAA,EACjE;AACA,SAAO;AACR;AAPS;AASF,SAAS,mBAAmB,OAAe,QAAQ,SAAiB;AAC1E,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,gBAAgB,KAAK,GAAG;AAC3B,UAAM,IAAI,MAAM,WAAW,KAAK,kCAAkC;AAAA,EACnE;AACA,SAAO;AACR;AANgB;AAQT,SAAS,eAAe,OAAgB,SAAS,MAAc;AACrE,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,MAAM,OAAO,KAAK;AACxB,qBAAmB,GAAG;AACtB,SAAO,IAAI,SAAS,SAAS,IAAI,MAAM,GAAG,MAAM,IAAI;AACrD;AALgB;;;ACtBhB,SAAS,YAAY,WAAW,kBAAkB;AAa3C,SAAS,gBAAgB,OAAoB;AACnD,QAAM,QAAQ,OAAO,YAAY,UAAU,mBAAmB;AAC9D,SAAO,OAAO,KAAK,IAAI,OAAO;AAC/B;AAHgB;AAKhB,IAAM,eAAe;AAQrB,SAAS,eAAe,SAAS,IAAY;AAC5C,QAAM,MAAM,aAAa,MAAM,EAAE;AACjC,WAAS,IAAI,IAAI,SAAS,GAAG,IAAI,GAAG,KAAK;AACxC,UAAM,IAAI,UAAU,IAAI,CAAC;AACzB,KAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AAAA,EACnC;AACA,SAAO,IAAI,MAAM,GAAG,KAAK,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE;AAC1D;AAPS;AASF,SAAS,kBAAkB,OAA6D;AAC9F,QAAM,YAAY,WAAW;AAC7B,QAAM,MAAM,eAAe;AAC3B,QAAM,KAAK,OAAO,YAAY;AAC9B,MAAI,CAAC,GAAI,OAAM,IAAI,MAAM,0CAA2B;AAIpD,QAAM,MAAM,MAAM,KAAK,OAAO,SAAS,KAAK,EAAE;AAC9C,SAAO,EAAE,KAAK,KAAK,UAAU;AAC9B;AAVgB;AAgBT,SAAS,mBAAmB,OAAY,IAAY,IAA2B;AACrF,QAAM,EAAE,KAAK,KAAK,UAAU,IAAI,kBAAkB,KAAK;AACvD,QAAM,MAAM,KAAK,IAAI;AACrB,SAAO;AAAA,IACN,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,WAAW,MAAM,gBAAgB,KAAK;AAAA,IACtC,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,EACD;AACD;AAbgB;;;AChDhB,IAAM,qBAAqB,CAAC,wBAAwB;AAE7C,SAAS,sBAAsB,UAAkB,OAAqB;AAC5E,MAAI,mBAAmB,KAAK,CAAC,MAAM,SAAS,WAAW,CAAC,CAAC,GAAG;AAC3D,QAAI,SAAS,SAAS,eAAe,KAAK,SAAS,SAAS,aAAa,KAAK,SAAS,SAAS,eAAe,GAAG;AACjH,aAAO,QAAQ,uBAAuB,OAAO,YAAY,IAAI,QAAQ;AAAA,IACtE;AACA,WAAO,QAAQ,uBAAuB,OAAO,WAAW,IAAI,QAAQ;AAAA,EACrE;AACA,SAAO;AACR;AARgB;AAUT,SAAS,SAAS,WAAmB,UAA2B;AACtE,SAAO,OAAO,SAAS,SAAS,KAAK,aAAa;AACnD;AAFgB;;;ACkBhB,SAASC,WAAU,KAAmC;AACrD,MAAI,CAAC,KAAK,KAAM,QAAO,CAAC;AACxB,MAAI,OAAO,IAAI,SAAS,UAAU;AACjC,QAAI;AACH,aAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IAC3B,QAAQ;AACP,aAAO,CAAC;AAAA,IACT;AAAA,EACD;AACA,SAAO,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,CAAC;AACnD;AAVS,OAAAA,YAAA;AAYT,SAAS,YAAY,OAAY;AAChC,SAAO,OAAO,YAAY,YAAY,CAAC;AACxC;AAFS;AAIT,SAASC,UAAS,OAAY;AAC7B,QAAM,MAAM,YAAY,KAAK;AAC7B,SAAO,IAAI,SAAS,CAAC;AACtB;AAHS,OAAAA,WAAA;AAKT,eAAe,SAAS,OAAY,IAAwD;AAC3F,QAAM,QAAQA,UAAS,KAAK;AAC5B,MAAI,CAAC,MAAM,QAAS,QAAO,EAAE,IAAI,KAAK;AAEtC,QAAM,QAAQ,gBAAgB,KAAK;AACnC,QAAM,QAAQ,MAAM,MAAM,cAAc;AACxC,QAAM,WAAW,MAAM,oBAAoB,OAAO,YAAY,OAAO,SAAS,aAAa;AAC3F,MAAI,SAAS,UAAU;AACtB,WAAO,EAAE,IAAI,OAAO,SAAS,mBAAmB;AAAA,EACjD;AAEA,QAAM,UAAU,MAAM,MAAM,oBAAoB,EAAE;AAClD,QAAM,aAAa,MAAM,sBAAsB;AAC/C,MAAI,WAAW,YAAY;AAC1B,WAAO,EAAE,IAAI,OAAO,SAAS,qBAAqB;AAAA,EACnD;AACA,SAAO,EAAE,IAAI,KAAK;AACnB;AAjBe;AAmBf,SAAS,WAAW,OAAY,MAAW;AAC1C,QAAM,OAAO,KAAK,QAAQ,oBAAoB,OAAO,KAAK,EAAE,EAAE;AAC9D,SAAO;AAAA,IACN,IAAI,KAAK;AAAA,IACT,IAAI,KAAK;AAAA,IACT;AAAA,IACA,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,oBAAoB,CAAC,CAAC,KAAK;AAAA,EAC5B;AACD;AAVS;AAYT,IAAI,mBAAyC;AAE7C,SAAS,YAAY,OAA2B;AAC/C,MAAI,CAAC,kBAAkB;AACtB,uBAAmB,QAAQ,IAAI,CAAC,qBAAqB,KAAK,GAAG,oBAAoB,KAAK,CAAC,CAAC,EAAE,KAAK,MAAM,MAAS;AAAA,EAC/G;AACA,SAAO;AACR;AALS;AAOT,IAAO,gBAAQ,wBAAC,UAAe;AAC9B,QAAM,EAAE,aAAa,UAAU,QAAQ,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AAC5E,QAAM,QAAQ,gBAAgB,KAAK;AAEnC,iBAAe,WAAW,KAAU,UAAkB,aAAwC;AAC7F,UAAM,sBAAsB,KAAK,KAAK;AACtC,UAAM,QAAQ,eAAe,sBAAsB,UAAU,KAAK;AAClE,WAAO,SAAS,oBAAoB,GAAG,GAAG,KAAK;AAAA,EAChD;AAJe;AAMf,iBAAe,KAAK,KAAU,KAAU,SAAiB,KAAU;AAClE,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,KAAK,YAAY,GAAG;AAC1B,UAAM,OAAOD,WAAU,GAAG;AAE1B,QAAI,IAAI,WAAW,6BAA6B,GAAG;AAClD,YAAM,YAAY,KAAK;AACvB,UAAI;AACH,cAAM,KAAK,eAAe,KAAK,IAAI,EAAE;AACrC,cAAM,OAAO,eAAe,KAAK,MAAM,GAAG;AAC1C,cAAM,UAAU,eAAe,KAAK,SAAS,GAAG;AAChD,YAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAS,QAAO,QAAQ,KAAK,6BAA6B,QAAW,GAAG;AAE7F,cAAM,OAAO,MAAM,MAAM,eAAe,EAAE;AAC1C,YAAI,CAAC,QAAQ,CAAC,eAAe,MAAM,KAAK,UAAU,KAAK,QAAQ,GAAG;AACjE,iBAAO,QAAQ,KAAK,4BAA4B,QAAW,GAAG;AAAA,QAC/D;AAEA,cAAM,SAAS,kBAAkB,KAAK;AACtC,cAAM,YAAY,uBAAuB,SAAS,OAAO,KAAK,WAAW;AACzE,YAAI,cAAc,sBAAsB;AACvC,iBAAO,QAAQ,KAAK,WAAW,CAAC,OAAO,OAAO,SAAS,CAAC,GAAG,GAAG;AAAA,QAC/D;AACA,YAAI,UAAW,QAAO,QAAQ,KAAK,WAAW,QAAW,GAAG;AAE5D,cAAM,EAAE,UAAU,SAAS,IAAI,aAAa,OAAO;AACnD,cAAM,cAAc,gBAAgB,MAAM,KAAK,aAAa,OAAO,YAAY;AAC/E,cAAM,MAAM,WAAW,IAAI;AAAA,UAC1B;AAAA,UACA;AAAA,UACA,oBAAoB;AAAA,UACpB,mBAAmB,KAAK,IAAI;AAAA,UAC5B;AAAA,QACD,CAAC;AAED,yBAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,mBAAmB,CAAC;AAClH,eAAO,YAAY,KAAK,EAAE,IAAI,KAAK,GAAG,GAAG;AAAA,MAC1C,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,2BAA2B,GAAG;AAChD,YAAM,YAAY,KAAK;AACvB,YAAM,MAAM,YAAY,KAAK;AAC7B,UAAI,IAAI,kBAAkB,GAAG;AAC5B,eAAO,QAAQ,KAAK,qBAAqB,QAAW,GAAG;AAAA,MACxD;AACA,UAAI;AACH,cAAM,KAAK,eAAe,KAAK,IAAI,EAAE;AACrC,cAAM,OAAO,eAAe,KAAK,MAAM,GAAG;AAC1C,cAAM,QAAQ,KAAK,QAAQ,eAAe,KAAK,OAAO,GAAG,IAAI;AAC7D,cAAM,YAAY,uBAAuB,MAAM,KAAK;AACpD,YAAI,cAAc,sBAAsB;AACvC,iBAAO,QAAQ,KAAK,WAAW,CAAC,OAAO,kBAAkB,KAAK,EAAE,SAAS,CAAC,GAAG,GAAG;AAAA,QACjF;AACA,YAAI,UAAW,QAAO,QAAQ,KAAK,WAAW,QAAW,GAAG;AAC5D,cAAM,EAAE,UAAU,SAAS,IAAI,aAAa,IAAI;AAChD,cAAM,OAAO,MAAM,MAAM,WAAW;AAAA,UACnC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,IAAI;AAAA,UACJ,mBAAmB,KAAK,IAAI;AAAA,UAC5B,aAAa;AAAA,QACd,CAAC;AACD,yBAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,cAAc,CAAC;AAC7G,eAAO,YAAY,KAAK,EAAE,MAAM,WAAW,OAAO,IAAI,EAAE,GAAG,GAAG;AAAA,MAC/D,SAAS,KAAU;AAClB,cAAM,MAAM,KAAK,WAAW,OAAO,GAAG;AACtC,YAAI,IAAI,SAAS,QAAQ,KAAK,IAAI,SAAS,oBAAK,GAAG;AAClD,iBAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAAA,QAC1D;AACA,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,uBAAuB,GAAG;AAC5C,YAAM,YAAY,KAAK;AACvB,UAAI;AACH,cAAM,KAAK,eAAe,KAAK,IAAI,EAAE;AACrC,cAAM,OAAO,eAAe,KAAK,MAAM,GAAG;AAC1C,YAAI,CAAC,MAAM,CAAC,KAAM,QAAO,QAAQ,KAAK,6BAA6B,QAAW,GAAG;AAEjF,cAAM,OAAO,MAAM,MAAM,eAAe,EAAE;AAC1C,YAAI,CAAC,QAAQ,CAAC,eAAe,MAAM,KAAK,UAAU,KAAK,QAAQ,GAAG;AACjE,cAAI,MAAM;AACT,kBAAM,MAAM,YAAY,KAAK;AAC7B,kBAAM,aAAa,IAAI,mBAAmB;AAC1C,kBAAM,aAAa,IAAI,kBAAkB;AACzC,kBAAM,aAAa,KAAK,aAAa,KAAK;AAC1C,kBAAM,QAAa,EAAE,UAAU;AAC/B,gBAAI,aAAa,YAAY;AAC5B,oBAAM,SAAS;AACf,oBAAM,cAAc,KAAK,IAAI,IAAI,aAAa,KAAK;AAAA,YACpD;AACA,kBAAM,MAAM,WAAW,IAAI,KAAK;AAAA,UACjC;AACA,2BAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,GAAG,CAAC;AACtF,iBAAO,QAAQ,KAAK,4BAA4B,QAAW,GAAG;AAAA,QAC/D;AAEA,YAAI,KAAK,WAAW,YAAY;AAC/B,iBAAO,QAAQ,KAAK,yBAAyB,QAAW,GAAG;AAAA,QAC5D;AAEA,YAAI,KAAK,WAAW,YAAY,KAAK,eAAe,KAAK,cAAc,KAAK,IAAI,GAAG;AAClF,iBAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAAA,QAC1D;AAEA,cAAM,SAAS,kBAAkB,KAAK;AACtC,cAAM,aACL,CAAC,CAAC,KAAK,sBACP,kBAAkB,KAAK,mBAAmB,OAAO,UAAU;AAE5D,cAAM,UAAU,MAAM,UAAU,OAAO,KAAK,CAAC;AAC7C,YAAI,QAAQ,QAAQ,iBAAiB,OAAO,IAAI,OAAO,GAAG;AACzD,2BAAiB,OAAO;AAAA,YACvB,MAAM;AAAA,YACN,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,MAAM;AAAA,YACN;AAAA,YACA,QAAQ;AAAA,UACT,CAAC;AACD,iBAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAAA,QAC1D;AAEA,cAAM,aAAa,MAAM,SAAS,OAAO,EAAE;AAC3C,YAAI,CAAC,WAAW,IAAI;AACnB,2BAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,WAAW,QAAQ,CAAC;AACnH,iBAAO,QAAQ,KAAK,WAAW,WAAW,oBAAoB,QAAW,GAAG;AAAA,QAC7E;AAEA,cAAM,MAAM,WAAW,IAAI,EAAE,WAAW,GAAG,QAAQ,UAAU,aAAa,OAAU,CAAC;AACrF,cAAM,UAAU,mBAAmB,OAAO,IAAI,EAAE;AAChD,gBAAQ,iBAAiB,KAAK,IAAI;AAClC,cAAM,MAAM,WAAW,OAAO;AAE9B,yBAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,WAAW,CAAC;AAE1G,eAAO;AAAA,UACN;AAAA,UACA;AAAA,YACC,MAAM,EAAE,GAAG,WAAW,OAAO,IAAI,GAAG,oBAAoB,WAAW;AAAA,YACnE,MAAM,aAAa,OAAO,CAAC,QAAQ,KAAK,QAAQ,GAAG;AAAA,YACnD,WAAW,aAAa,OAAO,QAAQ;AAAA,YACvC,oBAAoB;AAAA,UACrB;AAAA,UACA;AAAA,QACD;AAAA,MACD,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,yBAAyB,GAAG;AAC9C,UAAI;AACH,cAAM,UAAU,KAAK,YAAY,eAAe,KAAK,WAAW,EAAE,IAAI;AACtE,YAAI,QAAS,OAAM,MAAM,cAAc,OAAO;AAC9C,cAAM,KAAK,KAAK,WAAW,CAAC;AAC5B,YAAI,GAAI,kBAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,OAAO,EAAE,GAAG,IAAI,QAAQ,SAAS,CAAC;AACxH,eAAO,YAAY,KAAK,MAAM,GAAG;AAAA,MAClC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AAClD,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,YAAY,CAAC,GAAI;AAC/E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,YAAY,eAAe,KAAK,WAAW,EAAE;AACnD,YAAI,CAAC,UAAW,QAAO,QAAQ,KAAK,6BAA6B,QAAW,GAAG;AAC/E,cAAM,WAAW,MAAM,MAAM,YAAY;AACzC,cAAM,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AACtD,cAAM,MAAM,cAAc,SAAS;AACnC,cAAM,WAAW,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAChD,cAAM,oBAAoB,OAAO;AAAA,UAChC;AAAA,UACA;AAAA,UACA,UAAU,QAAQ;AAAA,UAClB;AAAA,QACD,CAAC;AACD,eAAO,YAAY,KAAK,EAAE,IAAI,KAAK,GAAG,GAAG;AAAA,MAC1C,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,+BAA+B,GAAG;AACpD,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,YAAY,CAAC,GAAI;AAC/E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,WAAW,eAAe,KAAK,IAAI,EAAE;AAC3C,YAAI,CAAC,YAAY,aAAa,QAAS,QAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAC3F,cAAM,KAAK,MAAM,MAAM,WAAW,QAAQ;AAC1C,YAAI,CAAC,GAAI,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAClE,cAAM,WAAW,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAChD,cAAM,gBAAgB,OAAO,EAAE,UAAU,UAAU,GAAG,CAAC;AACvD,eAAO,YAAY,KAAK,EAAE,IAAI,KAAK,GAAG,GAAG;AAAA,MAC1C,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,+BAA+B,GAAG;AACpD,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,YAAY,CAAC,GAAI;AAC/E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,SAAS,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK,SAAS;AAC1D,cAAM,aACL,KAAK,cAAc,OAAO,KAAK,eAAe,WAAY,KAAK,aAAyC;AACzG,cAAM,cAAc,MAAM,QAAQ,KAAK,WAAW,IAAI,KAAK,cAAc;AACzE,cAAM,WAAW,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAChD,cAAM,MAAM,MAAM;AAAA,UACjB;AAAA,UACA,EAAE,QAAuB,YAA+B,YAAgC;AAAA,UACxF;AAAA,QACD;AACA,cAAM,8BAA8B,OAAO;AAAA,UAC1C,SAAS;AAAA,UACT,QAAQ,KAAK,UAAU,EAAE,QAAQ,QAAQ,QAAQ,YAAY,CAAC,CAAC,YAAY,aAAa,aAAa,OAAO,CAAC;AAAA,UAC7G;AAAA,UACA;AAAA,QACD,CAAC;AACD,eAAO,YAAY,KAAK,KAAK,GAAG;AAAA,MACjC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,+BAA+B,GAAG;AACpD,YAAM,YAAY,KAAK;AACvB,UAAI,CAAE,MAAM,WAAW,KAAK,GAAG,GAAI;AAClC,yBAAiB,OAAO,EAAE,MAAM,iBAAiB,MAAM,KAAK,QAAQ,QAAQ,GAAG,CAAC;AAChF,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,WAAW,eAAe,KAAK,IAAI,EAAE;AAC3C,cAAM,QAAa,CAAC;AACpB,YAAI,KAAK,MAAM,MAAM;AACpB,gBAAM,QAAQ,OAAO,KAAK,EAAE;AAC5B,cAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,cAAc,OAAO,KAAK,GAAG;AAC5D,mBAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,UACrD;AACA,gBAAM,KAAK;AACX,gBAAM,OAAO,oBAAoB,OAAO,KAAK,EAAE;AAAA,QAChD;AACA,YAAI,KAAK,OAAQ,OAAM,SAAS,eAAe,KAAK,QAAQ,EAAE;AAC9D,YAAI,KAAK,WAAW;AACnB,gBAAM,YAAY;AAClB,gBAAM,SAAS;AACf,gBAAM,cAAc;AAAA,QACrB;AACA,YAAI,KAAK,sBAAsB,KAAM,OAAM,qBAAqB,KAAK,qBAAqB,IAAI;AAC9F,cAAM,UAAU,MAAM,MAAM,WAAW,UAAU,KAAK;AACtD,YAAI,CAAC,QAAS,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AACvE,YAAI,OAAO,KAAK,KAAK,EAAE,QAAQ;AAC9B,gBAAM,kBAAkB,OAAO;AAAA,YAC9B,UAAU,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAAA,YACzC;AAAA,YACA;AAAA,YACA;AAAA,UACD,CAAC;AAAA,QACF;AACA,eAAO,YAAY,KAAK,EAAE,MAAM,WAAW,OAAO,OAAO,EAAE,GAAG,GAAG;AAAA,MAClE,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC/C,YAAM,KAAK,KAAK,WAAW,CAAC;AAC5B,UAAI,CAAC,GAAI,QAAO,QAAQ,KAAK,qBAAqB,QAAW,GAAG;AAChE,UAAI;AACH,cAAM,OAAO,MAAM,MAAM,eAAe,OAAO,EAAE,CAAC;AAClD,YAAI,CAAC,KAAM,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAEpE,YAAI,KAAK,SAAS;AACjB,gBAAM,UAAU,eAAe,KAAK,SAAS,GAAG;AAChD,gBAAM,SAAS,kBAAkB,KAAK;AAEtC,cAAI,KAAK,MAAM;AACd,gBAAI,CAAC,eAAe,OAAO,KAAK,IAAI,GAAG,KAAK,UAAU,KAAK,QAAQ,GAAG;AACrE,qBAAO,QAAQ,KAAK,yBAAyB,QAAW,GAAG;AAAA,YAC5D;AAAA,UACD,WAAW,CAAC,KAAK,oBAAoB;AACpC,mBAAO,QAAQ,KAAK,yBAAyB,QAAW,GAAG;AAAA,UAC5D;AAEA,gBAAM,YAAY,uBAAuB,SAAS,OAAO,KAAK,WAAW;AACzE,cAAI,cAAc,sBAAsB;AACvC,mBAAO,QAAQ,KAAK,WAAW,CAAC,OAAO,OAAO,SAAS,CAAC,GAAG,GAAG;AAAA,UAC/D;AACA,cAAI,UAAW,QAAO,QAAQ,KAAK,WAAW,QAAW,GAAG;AAE5D,gBAAM,EAAE,UAAU,SAAS,IAAI,aAAa,OAAO;AACnD,gBAAM,cAAc,gBAAgB,OAAO,KAAK,QAAQ,OAAO,GAAG,KAAK,aAAa,OAAO,YAAY;AACvG,gBAAM,MAAM,WAAW,OAAO,EAAE,GAAG;AAAA,YAClC;AAAA,YACA;AAAA,YACA,oBAAoB;AAAA,YACpB,mBAAmB,KAAK,IAAI;AAAA,YAC5B;AAAA,UACD,CAAC;AAAA,QACF;AAEA,cAAM,QAAQ,MAAM,MAAM,eAAe,OAAO,EAAE,CAAC;AACnD,eAAO,YAAY,KAAK,EAAE,MAAM,QAAQ,WAAW,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG;AAAA,MAC/E,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAAA,EACD;AA9Te;AAgUf,iBAAe,IAAI,KAAU,KAAU,SAAiB,KAAU;AACjE,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,KAAK,YAAY,GAAG;AAE1B,QAAI,IAAI,WAAW,yBAAyB,GAAG;AAC9C,YAAM,OAAO,OAAO,KAAK,UAAU,iBAAiB,KAAK,KAAK,UAAU,iBAAiB,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AACnH,aAAO,YAAY,KAAK,wBAAwB,OAAO,IAAI,GAAG,GAAG;AAAA,IAClE;AAEA,QAAI,IAAI,WAAW,+BAA+B,GAAG;AACpD,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,WAAW,CAAC,GAAI;AAC9E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,YAAM,oBAAoB,KAAK;AAC/B,aAAO,YAAY,KAAK,uBAAuB,KAAK,GAAG,GAAG;AAAA,IAC3D;AAEA,QAAI,IAAI,WAAW,iCAAiC,GAAG;AACtD,UAAI,CAAE,MAAM,WAAW,KAAK,GAAG,GAAI;AAClC,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,YAAM,WAAW,MAAM,MAAM,YAAY;AACzC,aAAO;AAAA,QACN;AAAA,QACA;AAAA,UACC,UAAU,SAAS,IAAI,CAAC,OAAO;AAAA,YAC9B,IAAI,EAAE;AAAA,YACN,IAAI,EAAE;AAAA,YACN,IAAI,EAAE;AAAA,YACN,WAAW,EAAE;AAAA,YACb,WAAW,EAAE;AAAA,YACb,gBAAgB,EAAE;AAAA,UACnB,EAAE;AAAA,QACH;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AAClD,UAAI,CAAE,MAAM,WAAW,KAAK,GAAG,GAAI;AAClC,yBAAiB,OAAO,EAAE,MAAM,iBAAiB,MAAM,KAAK,QAAQ,OAAO,GAAG,CAAC;AAC/E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,YAAM,QAAQ,MAAM,MAAM,UAAU;AACpC,aAAO,YAAY,KAAK,EAAE,OAAO,MAAM,IAAI,CAAC,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG;AAAA,IAC/E;AAEA,QAAI,IAAI,WAAW,8BAA8B,GAAG;AACnD,UAAI,CAAE,MAAM,WAAW,KAAK,GAAG,GAAI;AAClC,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,YAAM,WAAW,MAAM,MAAM,YAAY;AACzC,YAAM,QAAQC,UAAS,KAAK;AAC5B,aAAO;AAAA,QACN;AAAA,QACA;AAAA,UACC,UAAU,SAAS;AAAA,UACnB,kBAAkB,MAAM,oBAAoB;AAAA,UAC5C,cAAc,CAAC,CAAC,MAAM;AAAA,UACtB,MAAM,MAAM;AAAA,UACZ,IAAI,MAAM;AAAA,QACX;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC/C,YAAM,KAAK,KAAK,WAAW,CAAC;AAC5B,UAAI,CAAC,GAAI,QAAO,QAAQ,KAAK,qBAAqB,QAAW,GAAG;AAChE,YAAM,OAAO,MAAM,MAAM,eAAe,OAAO,EAAE,CAAC;AAClD,aAAO,YAAY,KAAK,EAAE,MAAM,OAAO,WAAW,OAAO,IAAI,IAAI,KAAK,GAAG,GAAG;AAAA,IAC7E;AAAA,EACD;AAxEe;AA0Ef,SAAO,EAAE,MAAM,IAAI;AACpB,GArZe;;;ACtFf,IAAO,cAAQ;AAAA,EACb,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,cAAc;AAAA,EACd,qBAAqB;AAAA,EACrB,cAAc;AAChB;;;AChBA,IAAO,aAAQ;AAAA,EACb,OAAO,IAAY,QAAmC,OAAY,MAAM;AACtE,UAAM,KACJ,UAAU,OACN,SACA,MAAM,QAAQ,MAAM,IAClB,OAAO,IAAI,MAAM,IACjB,CAAC,OAAO,MAAM,CAAC;AACvB,WAAO,EAAE,MAAM,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE;AAAA,EACvC;AAAA,EACA,QAAQ,KAAU,MAAW,MAAM;AACjC,QAAI,OAAO,OAAO,QAAQ,YAAY,OAAO,IAAI,OAAO,UAAU;AAChE,aAAO,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,IAChC;AACA,QAAI,eAAe,OAAO;AACxB,YAAM,IAAI,WAAW,OAAO,GAAG;AAAA,IACjC,WAAW,OAAO,OAAO,QAAQ,YAAY,OAAO,IAAI,YAAY,UAAU;AAC5E,YAAM,IAAI;AAAA,IACZ;AACA,WAAO,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,EAChC;AAAA,EACA,SAAS,KAAa,MAAW,MAAM;AACrC,WAAO,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,EAChC;AAAA,EACA,WAAW,KAAU,MAAW,MAAM;AACpC,QAAI,OAAO,KAAK,WAAW,YAAY;AACrC,YAAM,IAAI,OAAO,GAAG;AAAA,IACtB;AACA,WAAO,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,EAChC;AAAA,EACA,QAAQ,MAAc,KAAK;AACzB,WAAO,KAAK,QAAQ,yBAAyB,EAAE;AAAA,EACjD;AAAA,EACA,QAAQ,MAAc,KAAK;AACzB,WAAO,KAAK,QAAQ,qBAAqB,EAAE;AAAA,EAC7C;AAAA,EAEA,UAAU,cAAsB;AAC9B,UAAM,UAAU,aAAa,MAAM,GAAG;AACtC,YAAQ,IAAI;AACZ,UAAM,UAAU,QAAQ,KAAK,GAAG,IAAI;AACpC,WAAO;AAAA,EACT;AAAA,EACA,eAAe,cAAsB;AACnC,mBAAe,QAAQ,IAAI,IAAI;AAC/B,mBAAe,aAAa,QAAQ,OAAO,GAAG;AAC9C,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,UAAUC,MAAS,cAAsB;AACvC,UAAM,aAAa,KAAK,UAAU,YAAY;AAC9C,UAAM,UAAU,KAAK,eAAe,YAAY;AAChD,QAAI,CAACA,KAAG,WAAW,OAAO,GAAG;AAC3B,UAAI,UAAkB;AACtB,iBAAW,MAAM,GAAG,EAAE,QAAQ,CAAC,OAAe;AAC5C,YAAI,IAAI;AACN,cAAI,SAAS;AACX,uBAAW;AAAA,UACb;AACA,qBAAW;AACX,cAAI,CAACA,KAAG,WAAW,OAAO,GAAG;AAC3B,gBAAI,CAACA,KAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC,GAAG;AAC/C,qBAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EACA,QAAQA,MAAS,WAAmB;AAClC,WAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAI;AACF,cAAM,UAAU,KAAK,UAAUD,MAAI,SAAS;AAC5C,QAAAC,SAAQ,OAAO;AAAA,MACjB,SAAS,KAAU;AACjB,eAAO,GAAG;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EACA,YAAY,MAAc,KAAK;AAC7B,QAAI,WAAW;AACf,QAAI,YAAY;AAChB,QAAI,IAAI,WAAW,GAAG,GAAG;AAEvB,iBAAW,KAAK,QAAQ,GAAG;AAAA,IAC7B,WAAW,IAAI,QAAQ,GAAG,IAAI,IAAI;AAEhC,UAAI,IAAI,WAAW,KAAK,GAAG;AACzB,mBAAW,KAAK,QAAQ,MAAM,GAAG;AAAA,MACnC,OAAO;AACL,mBAAW,qBAAqB,KAAK,QAAQ,GAAG;AAAA,MAClD;AAAA,IACF,OAAO;AACL,iBAAW,qBAAqB,KAAK,QAAQ,GAAG;AAAA,IAClD;AACA,gBAAY,KAAK,eAAe,QAAQ;AACxC,WAAO,EAAE,UAAU,UAAU;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAY,IAAS,KAAU;AAC7B,QAAI,KAAK,WAAW;AAElB,SAAG;AACH,UAAI,YAAY;AAAA,IAClB;AAAA,EACF;AAAA,EACA,eAAe,KAAU;AACvB,iBAAa,IAAI,OAAO;AACxB,QAAI,UAAU;AAAA,EAChB;AAAA,EACA,aAAa,IAAS,KAAU;AAC9B,WAAO,WAAW,MAAM;AACtB,SAAG;AACH,WAAK,eAAe,GAAG;AAAA,IACzB,GAAG,IAAI,IAAI;AAAA,EACb;AAAA;AAAA,EAEA,SAAS,IAAS,KAAU;AAC1B,SAAK,YAAY,IAAI,GAAG;AACxB,QAAI,WAAU,oBAAI,KAAK,GAAE,QAAQ;AACjC,QAAI,IAAI,UAAU,IAAI,YAAY,IAAI,MAAM;AAC1C,WAAK,eAAe,GAAG;AAAA,IACzB;AACA,QAAI,CAAC,KAAK,SAAS;AACjB,UAAI,YAAY,IAAI;AACpB,UAAI,UAAU,KAAK,aAAa,IAAI,GAAG;AAAA,IACzC;AAAA,EACF;AAAA;AAAA,EAEA,SAAS,IAAS,KAAU;AAC1B,SAAK,YAAY,IAAI,GAAG;AACxB,QAAI,CAAC,KAAK,SAAS;AACjB,UAAI,UAAU,KAAK,aAAa,IAAI,GAAG;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,aAAqB,IAAI,QAAgB,GAAG,MAAc,IAAY;AACzE,QAAI,MAAc,KAAK,IAAI,EAAE,SAAS,EAAE;AACxC,QAAI,QAAQ,GAAG;AACb,aAAO,MAAM,SAAS,EAAE;AAAA,IAC1B;AACA,UAAM,IAAI,MAAM,EAAE;AAClB,QAAI,YAAY;AACd,YAAM,WAAW,MAAM,EAAE,IAAI;AAAA,IAC/B;AACA,QAAI,SAAiB,IAAI;AACzB,WAAO,SAAS,IAAI;AAClB,cAAS,KAAK,OAAO,IAAI,MAAO,GAAG,SAAS,GAAG,EAAE,MAAM,EAAE;AACzD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EACA,MAAM,KAAU;AACd,UAAM,YAAY,IAAI,QAAQ,iBAAiB;AAC/C,WAAO,YAAY,UAAU,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,WAAW;AAAA,EAC9D;AACF;;;ACzKA,IAAO,iBAAQ;AAAA;AAAA,EAEX,SAAS,KAAa,MAAc;AAChC,UAAM,SAAiB,KAAK,UAAU;AACtC,UAAM,UAAkB,MAAM,UAAU;AACxC,QAAI,SAAiB;AACrB,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC7B,YAAM,OAAe,KAAK,MAAM,KAAK,OAAO,IAAI,GAAI,IAAI;AACxD,YAAM,QAAgB,OAAO,KAAK,SAAS,EAAE,MAAM,EAAE,CAAC,IAAI;AAC1D,YAAM,OAAe,UAAU;AAC/B,UAAI,SAAS,IAAI,YAAY,CAAC;AAC9B,YAAM,KAAa,SAAS;AAC5B,gBAAU,SAAS,MAAM;AACzB,YAAM,KAAa,SAAS;AAC5B,gBAAU,SAAS,MAAM;AACzB,gBACI,KAAM,SAAS,OAAQ,KAAK,IAC5B,KAAK,KAAK,KAAK,IACf,KAAK,KAAK,KAAK,IACf,KAAK,OAAO,IAAI;AAAA,IACxB;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,SAAS,KAAa,MAAc;AAChC,QAAI;AACA,YAAM,SAAiB,IAAI;AAC3B,YAAM,UAAkB,KAAK;AAC7B,UAAI,SAAiB;AACrB,eAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC7B,cAAM,OAAe,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC;AAC5C,cAAM,QAAgB,OAAO,KAAK,SAAS,EAAE,MAAM,EAAE,CAAC,IAAI;AAC1D,cAAM,OAAe,UAAU;AAC/B,kBAAU,QAAQ;AAAA,WACb,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,SAAS,OAAO,QACrC,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,SAAS,QAClC,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI;AAAA,QAClC;AAAA,MACJ;AACA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EACA,YAAY,MAAW,MAAc;AACjC,QAAI;AACA,aAAO,KAAK,MAAM,IAAI;AACtB,aAAO,KAAK;AAAA,QACR,KAAK,SAAS,KAAK,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI,CAAC;AAAA,MAC3D;AAAA,IACJ,SAAS,OAAO;AACZ;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,aAAa,MAAW,MAAc,MAAc;AAChD,WAAO;AAAA,MACH;AAAA,MACA,MAAM,KAAK;AAAA,QACP,KAAK,UAAU,IAAI;AAAA,QACnB,KAAK,SAAS,MAAM,IAAI;AAAA,MAC5B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA,EAEA,SAAS,KAAa;AAClB,UAAM,SAAmB,CAAC;AAC1B,QAAI,MAAM,EAAE,EAAE,QAAQ,CAAC,OAAe;AAClC,aAAO,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,OAAO,MAAM,GAAG,GAAG,EAAE;AAAA,IAClE,CAAC;AACD,WAAO,OAAO,KAAK,EAAE;AAAA,EACzB;AACJ;;;ACxEA,OAAO,YAAY;AAEnB,IAAO,gBAAQ,wBAAC,OAAY,MAAW,SAAS;AAC5C,QAAM,UAAU,OAAO,KAAK,MAAM,WAAW,IAAI,WAAW,QAAQ;AACpE,QAAM,UAAU,OAAO,KAAK,MAAM,WAAW,IAAI,KAAK,MAAM;AAE5D,WAAS,cAAc,OAAY;AAC/B,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI;AACA,aAAO,KAAK,MAAM,KAAK;AAAA,IAC3B,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAPS;AAST,WAAS,aAAa,OAAuB;AACzC,QAAI,OAAO,UAAU,UAAU;AAC3B,YAAM,IAAI,UAAU,yBAAyB;AAAA,IACjD;AACA,WAAO,OAAO,KAAK,OAAO,QAAQ;AAAA,EACtC;AALS;AAOT,WAAS,QAAQ,WAAmB;AAChC,UAAM,KAAK,OAAO,YAAY,MAAM,WAAW,IAAI,QAAQ;AAC3D,UAAM,SAAS,OAAO,eAAe,MAAM,WAAW,IAAI,WAAW,SAAS,EAAE;AAChF,WAAO,OAAO,OAAO;AACrB,UAAM,kBAAkB,OAAO,OAAO,CAAC,OAAO,OAAO,WAAW,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;AACxF,WAAO;AAAA,MACH,MAAM,gBAAgB,SAAS,QAAQ;AAAA,MACvC,IAAI,GAAG,SAAS,QAAQ;AAAA,MACxB,MAAM,OAAO,WAAW,EAAE,SAAS,QAAQ;AAAA,IAC/C;AAAA,EACJ;AAVS;AAYT,WAAS,QAAQ,UAAe;AAC5B,UAAM,KAAK,aAAa,SAAS,EAAE;AACnC,UAAM,UAAU,aAAa,SAAS,IAAI;AAC1C,UAAM,YAAY,aAAa,SAAS,IAAI;AAC5C,UAAM,WAAW,OAAO,iBAAiB,MAAM,WAAW,IAAI,WAAW,SAAS,EAAE;AACpF,aAAS,OAAO,OAAO;AACvB,aAAS,WAAW,OAAO;AAC3B,UAAM,kBAAkB,OAAO,OAAO,CAAC,SAAS,OAAO,SAAS,GAAG,SAAS,MAAM,CAAC,CAAC;AACpF,WAAO,gBAAgB,SAAS,MAAM;AAAA,EAC1C;AATS;AAWT,WAAS,eAAe,SAAc,QAAkB;AACpD,WAAO,OAAO,MAAM,CAAC,QAAQ,OAAO,UAAU,GAAG,MAAM,YAAY,QAAQ,GAAG,EAAE,SAAS,CAAC;AAAA,EAC9F;AAFS;AAIT,WAAS,OAAO,KAAU,KAAU,CAAC,SAAc,MAAM;AACrD,UAAM,UAAU,cAAc,IAAI,IAAI;AACtC,QAAI;AACA,UAAI,eAAe,SAAS,CAAC,QAAQ,MAAM,MAAM,CAAC,GAAG;AACjD,YAAI,UAAe,QAAQ,OAAO;AAClC,YAAI,SAAS,QAAQ,GAAG;AACpB,oBAAU,KAAK,MAAM,OAAO;AAAA,QAChC;AACA,eAAO,GAAG,OAAO;AAAA,MACrB,OAAO;AACH,eAAO,GAAG,OAAO;AAAA,MACrB;AAAA,IACJ,SAAS,OAAY;AACjB,aAAO;AAAA,IACX;AAAA,EACJ;AAfS;AAgBT,WAAS,OAAO,MAAW;AACvB,QAAI;AACA,UAAI,QAAgB;AACpB,UAAI,QAAQ,OAAO,SAAS,UAAU;AAClC,eAAO,KAAK,UAAU,IAAI;AAC1B,gBAAQ;AAAA,MACZ;AACA,aAAO,OAAO,OAAO,EAAE,KAAK,MAAM,GAAG,QAAQ,IAAI,CAAC;AAAA,IACtD,SAAS,OAAY;AACjB,aAAO;AAAA,IACX;AAAA,EACJ;AAXS;AAaT,SAAO,EAAE,SAAS,SAAS,QAAQ,OAAO;AAC9C,GA7Ee;;;ACAf,IAAO,eAAQ,wBAAC,OAAY,QAAa;AACvC,QAAM,aAAkB,qBAAqB,OAAO;AAAA,IAClD,MAAM,KAAK,QAAQ;AAAA,IACnB,KAAK;AAAA,MACH,GAAI,KAAK,OAAO;AAAA,QACd,UAAU;AAAA,QACV,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,IACA,UAAU,KAAK;AAAA,EACjB,CAAC;AAED,WAAS,YAAY,KAAU;AAC7B,QAAI,KAAK,SAAS,YAAY,KAAK,SAAS,SAAS;AACnD,aAAO,IAAI,GAAG;AAAA,IAChB;AACA,WAAO;AAAA,EACT;AALS;AAOT,WAAS,SAAS,WAAgB;AAChC,QAAI,WAAW,IAAI;AACjB,aAAO,UAAU,GAAG,MAAM,GAAG;AAAA,IAC/B;AACA,WAAO,IAAI,MAAM;AAAA,EACnB;AALS;AAOT,WAAS,SAAS,WAAgB;AAChC,UAAM,WAAkB,CAAC;AACzB,SAAK,KAAK,SAAS,YAAY,KAAK,SAAS,YAAY,WAAW,KAAK;AACvE,YAAM,SAAS,UAAU,IAAI,MAAM,GAAG;AACtC,eAAS,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAAA,IACxD;AACA,QAAI,WAAW,IAAI;AACjB,eAAS,KAAK,CAAC,IAAI,MAAM,OAAO,QAAQ,YAAY,GAAG,UAAU,EAAE,GAAG,CAAC,CAAC;AAAA,IAC1E;AACA,QAAI,WAAW,MAAM,WAAW,MAAM;AACpC,eAAS,KAAK,CAAC,UAAU,MAAM,QAAQ,YAAY,IAAI,UAAU,EAAE,GAAG,CAAC,CAAC;AAAA,IAC1E;AACA,QAAI,SAAS,SAAS,GAAG;AACvB,eAAS,QAAQ,KAAK;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AAhBS;AAkBT,WAAS,SAAS,WAAgB;AAChC,UAAM,WAAkB,CAAC;AACzB,QAAI,WAAW,IAAI;AACjB,eAAS,KAAK,CAAC,UAAU,IAAI,WAAW,QAAQ,IAAI,SAAS,KAAK,CAAC;AAAA,IACrE;AACA,WAAO;AAAA,EACT;AANS;AAQT,WAAS,SAAS,WAAgB;AAChC,QAAI,WAAW;AACf,QAAI,UAAkB,WAAW;AACjC,QAAI,WAAW,IAAI;AACjB,gBAAU,WAAW;AACrB,iBAAW,IAAI,UAAU,KAAK,KAAK,OAAO,IAAI,OAAO;AAAA,IACvD,WAAW,SAAS;AAClB,kBAAY;AAAA,IACd;AACA,WAAO;AAAA,EACT;AAVS;AAYT,WAAS,kBAAkB,KAAU,KAAU;AAC7C,QAAI;AACJ,UAAM,SAAc,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC;AAC5D,UAAM,SAAS,KAAK,QAAQ,SAAS,KAAK,MAAM,SAAS,OAAO,CAAC,GAAG,WAAW,KAAK,GAAG;AACvF,QAAI,CAAC,MAAO,QAAO;AAEnB,mBAAe;AAAA,MACb,MAAM;AAAA,MACN;AAAA,IACF;AAEA,QAAI,OAAO,CAAC,GAAG;AACb,UAAI,OAAO,CAAC,MAAM,UAAU;AAC1B,qBAAa,OAAO,OAAO,CAAC;AAC5B,YAAI,KAAK,SAAS,QAAQ;AACxB,uBAAa,QAAQ,IAAI,MAAM;AAC/B,uBAAa,QAAQ,CAAC,CAAC,YAAY,OAAO,CAAC,CAAC,GAAG,YAAY,IAAI,IAAI,CAAC,CAAC;AAAA,QACvE,OAAO;AACL,uBAAa,QAAQ,CAAC;AACtB,uBAAa,QAAQ,CAAC;AACtB,gBAAM,WAAkB,CAAC;AACzB,gBAAM,SAAc,OAAO,IAAI,SAAS,WAAW,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI;AAC9E,iBAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,OAAY;AAC1C,gBAAI,IAAI,MAAM,KAAK,SAAS,GAAG,CAAC,CAAC,GAAG;AAClC,2BAAa,MAAM,KAAK,GAAG,CAAC,CAAC;AAC7B,uBAAS,KAAK,GAAG,CAAC,CAAC;AAAA,YACrB;AAAA,UACF,CAAC;AACD,cAAI,CAAC,aAAa,MAAM,SAAS,IAAI,MAAM,GAAG,GAAG;AAC/C,yBAAa,MAAM,KAAK,IAAI,MAAM,GAAG;AACrC,qBAAS,KAAK,OAAO,CAAC,CAAC;AAAA,UACzB;AACA,uBAAa,MAAM,KAAK,QAAQ;AAAA,QAClC;AAAA,MACF,WAAW,OAAO,CAAC,MAAM,UAAU;AACjC,qBAAa,OAAO,OAAO,CAAC;AAC5B,qBAAa,QAAQ,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,YAAI,KAAK,SAAS,QAAQ;AACxB,uBAAa,MAAM,CAAC,CAAC,IAAI,MAAM,KAAK,YAAY,IAAI,IAAI,CAAC,CAAC;AAAA,QAC5D,OAAO;AACL,uBAAa,MAAM,CAAC;AACpB,gBAAM,SAAc,OAAO,IAAI,SAAS,WAAW,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI;AAC9E,iBAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,OAAY;AAC1C,gBAAI,IAAI,MAAM,KAAK,SAAS,GAAG,CAAC,CAAC,GAAG;AAClC,kBAAI,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG;AACxB,6BAAa,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;AAAA,cACzC,OAAO;AACL,6BAAa,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAAA,cACtC;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,WAAW,OAAO,CAAC,MAAM,UAAU;AACjC,qBAAa,OAAO,OAAO,CAAC;AAC5B,qBAAa,QAAQ,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,CAAC;AAAA,MACpE,OAAO;AACL,YAAI,KAAK,KAAK,GAAG;AACf,uBAAa,KAAK,CAAC,IAAI,KAAK;AAAA,QAC9B;AACA,qBAAa,QAAQ,IAAI,MAAM;AAC/B,qBAAa,QAAQ,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,CAAC;AAAA,MACpE;AAAA,IACF,OAAO;AACL,mBAAa,KAAK,KAAK;AACvB,mBAAa,QAAQ,SAAS,IAAI,IAAI;AACtC,mBAAa,QAAQ,SAAS,IAAI,IAAI;AACtC,mBAAa,QAAQ,SAAS,IAAI,IAAI;AACtC,mBAAa,QAAQ,SAAS,IAAI,IAAI;AAAA,IACxC;AAEA,WAAO;AAAA,EACT;AAvES;AAyET,WAAS,QAAQ,KAAU,OAAY;AACrC,QAAI,KAAK,KAAK,SAAS,cAAc,GAAG;AACtC,YAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO;AACnD,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,cAAM,SAAS,KAAK,IAAI,CAAC,OAAY;AACnC,gBAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ;AACtC,cAAI,UAAkB,OAAO,OAAO,EAAE,UAAU,OAAO,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;AACpF,gBAAM,MAAM,QAAQ,YAAY,GAAG;AACnC,iBAAO,MAAM,KAAK,QAAQ,UAAU,GAAG,GAAG,IAAI;AAAA,QAChD,CAAC;AACD,YAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,cAAM,OAAO;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAfS;AAiBT,WAAS,SAAS,KAAU,OAAY;AACtC,QAAI,KAAK,YAAY,KAAK,SAAS,CAAC,GAAG;AACrC,YAAM,OAAO,MAAM,KAAK,OAAO,SAAS,KAAK,UAAU,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC,CAAC;AAAA,IACrF;AACA,WAAO;AAAA,EACT;AALS;AAOT,WAAS,eAAe,KAAU,KAAU,KAAU;AACpD,UAAM,SAAS,kBAAkB,KAAK,GAAG;AACzC,QAAI,QAAQ;AACV,iBAAW,MAAM,MAAM,EACpB,KAAK,CAAC,UAAe;AACpB,YAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,WAAW,SAAS,KAAK,QAAQ,KAAK,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,MAC3F,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,cAAM,MAAM,OAAO,OAAO,WAAW,SAAS,EAAE;AAChD,YAAI,QAAQ,SAAS,YAAY,IAAI,SAAS,eAAe,GAAG;AAC9D,cAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC;AACzD;AAAA,QACF;AACA,YAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,MACtD,CAAC;AAAA,IACL,OAAO;AACL,UAAI,IAAI,KAAK,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,IACvC;AAAA,EACF;AAlBS;AAoBT,WAAS,cAAc,KAAU,KAAU,KAAU;AACnD,UAAM,SAAS,kBAAkB,KAAK,GAAG;AACzC,QAAI,UAAU,OAAO,WAAW,UAAU,YAAY;AACpD,UAAI;AACF,mBAAW,MAAM,MAAM,EACpB,KAAK,CAAC,UAAe;AACpB,cAAI,UAAe,QAAQ,KAAK,KAAK;AACrC,cAAI,QAAQ,OAAO,KAAK,QAAQ,OAAO,SAAS,GAAG;AACjD,gBAAI,WAAkB,CAAC;AACvB,gBAAI,OAAO,OAAO,MAAM,GAAG,GAAG,SAAS,GAAG;AACxC,yBAAW,CAAC,GAAG,CAAC,OAAO,OAAO,MAAM,GAAG,IAAI,CAAC,CAAC;AAAA,YAC/C,OAAO;AACL,yBAAW,OAAO,MAAM,MAAM,GAAG;AACjC,yBAAW,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAAA,YACvD;AACA,gBAAI,QAAQ,MAAM,QAAQ;AACxB,sBAAQ,OAAO,QAAQ,KAAK,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAAA,YAC9D;AAAA,UACF;AACA,oBAAU,SAAS,KAAK,OAAO;AAC/B,cAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,WAAW,SAAS,GAAG,CAAC,CAAC;AAAA,QAChE,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,gBAAM,MAAM,OAAO,OAAO,WAAW,SAAS,EAAE;AAChD,cAAI,QAAQ,SAAS,YAAY,IAAI,SAAS,eAAe,GAAG;AAC9D,gBAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC;AACzD;AAAA,UACF;AACA,cAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,QACtD,CAAC;AAAA,MACL,QAAQ;AACN,YAAI,IAAI,KAAK,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,MACvC;AAAA,IACF,OAAO;AACL,UAAI,IAAI,KAAK,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,IACvC;AAAA,EACF;AApCS;AAsCT,WAAS,KAAK,KAAU,KAAU,SAAiB,KAAU;AAC3D,QAAI,KAAK,QAAQ,OAAO,IAAI,SAAS,YAAY;AAC/C,cAAQ,QAAQ,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,UAAU,CAAC,EACzD,KAAK,CAAC,YAAY;AACjB,YAAI,CAAC,QAAS,gBAAe,KAAK,KAAK,GAAG;AAAA,MAC5C,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,YAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,MACtD,CAAC;AACH;AAAA,IACF;AACA,mBAAe,KAAK,KAAK,GAAG;AAAA,EAC9B;AAZS;AAcT,WAAS,IAAI,KAAU,KAAU,SAAiB,KAAU;AAC1D,QAAI,KAAK,OAAO,OAAO,IAAI,QAAQ,YAAY;AAC7C,cAAQ,QAAQ,IAAI,IAAI,KAAK,KAAK,SAAS,KAAK,UAAU,CAAC,EACxD,KAAK,CAAC,YAAY;AACjB,YAAI,CAAC,QAAS,eAAc,KAAK,KAAK,GAAG;AAAA,MAC3C,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,YAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,MACtD,CAAC;AACH;AAAA,IACF;AACA,kBAAc,KAAK,KAAK,GAAG;AAAA,EAC7B;AAZS;AAcT,SAAO,EAAE,YAAY,MAAM,IAAI;AACjC,GAxPe;;;ACFf,IAAO,kBAAQ,wBAAC,UAAe;AAE7B,WAASC,aAAe,KAAW;AACjC,QAAI,OAAO,OAAO,QAAQ,YAAY,aAAc,KAAgB;AAClE,YAAM,IAAK,IAAkC;AAC7C,UAAI,MAAM,OAAW,QAAO;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AANS,SAAAA,cAAA;AAUT,WAAS,eAAe,KAAkB;AACxC,UAAM,UAAU,IAAI,QAAQ,QAAQ,IAAI,MAAM;AAC9C,WAAO,mBAAmB,OAAO;AAAA,EACnC;AAHS;AAQT,WAAS,YAAY,KAAU,MAAW,KAAU;AAClD,UAAM,WAAW,MAAM,KAAK,GAAG,WAAW,MAAM,GAAG;AACnD,QAAI,IAAI,KAAK,UAAU,QAAQ,CAAC;AAAA,EAClC;AAHS;AAQT,WAAS,QAAQ,KAAU,IAAY,QAA4B,KAAW;AAC5E,UAAM,YAAY,MAAM,MAAM;AAC9B,eAAW,iBAAiB,KAAK;AACjC,eAAW,WAAW,OAAO,IAAI,MAAM,QAAQ,MAAM,IAAI,OAAO,IAAI,MAAM,IAAI,UAAU,OAAO,CAAC,OAAO,MAAM,CAAC,IAAI,MAAS;AAC3H,UAAM,WAAW,MAAM,KAAK,GAAG,OAAO,IAAI,QAAQ,GAAG;AACrD,QAAI,IAAI,KAAK,UAAU,QAAQ,CAAC;AAAA,EAClC;AANS;AAWT,WAAS,SAAS,KAAU,KAAU,KAAW;AAC/C,UAAM,YAAY,MAAM,MAAM;AAC9B,eAAW,iBAAiB,KAAK;AACjC,UAAM,aAAa,WAAW,sBAAsB,GAAG;AACvD,QAAI,YAAY,IAAI;AAClB,aAAO,QAAQ,KAAK,WAAW,IAAI,WAAW,IAAI,GAAG;AAAA,IACvD;AACA,UAAM,WAAW,MAAM,KAAK,GAAG,QAAQ,GAAG;AAC1C,QAAI,IAAI,KAAK,UAAU,QAAQ,CAAC;AAAA,EAClC;AATS;AAcT,WAAS,SAAS,KAAU;AAC1B,KAAC,OAAO,QAAQ,QAAQ,KAAK,GAAG,GAAG;AAAA,EACrC;AAFS;AAGT,SAAO,EAAE,aAAAA,cAAa,gBAAgB,aAAa,UAAU,SAAS,MAAM;AAC9E,GAzDe;;;ACAf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAGjB,eAAsB,WAAW,UAAiC;AAChE,QAAM,aAAaC,MAAK,UAAU,QAAQ;AAC1C,QAAMC,IAAG,MAAMD,MAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,QAAM,KAAK,MAAMC,IAAG,KAAK,YAAY,GAAG;AACxC,QAAM,GAAG,MAAM;AACjB;AALsB;AAOtB,eAAsB,WAAW,UAAoC;AACnE,MAAI;AACF,UAAMA,IAAG,OAAOD,MAAK,UAAU,QAAQ,CAAC;AACxC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAPsB;AAStB,eAAsB,SAAsB,UAA8B;AACxE,QAAM,MAAM,MAAMC,IAAG,SAASD,MAAK,UAAU,QAAQ,GAAG,MAAM;AAC9D,SAAO,KAAK,MAAM,GAAG;AACvB;AAHsB;AAMf,SAAS,qBAAqB,SAAiB,SAAyB;AAC7E,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,UAAM,IAAI,MAAM,cAAc;AAAA,EAChC;AACA,MAAI,QAAQ,SAAS,IAAI,GAAG;AAC1B,UAAM,IAAI,MAAM,cAAc;AAAA,EAChC;AACA,QAAM,OAAOA,MAAK,QAAQ,OAAO;AACjC,QAAM,SAASA,MAAK,QAAQ,MAAM,QAAQ,QAAQ,OAAO,GAAG,CAAC;AAC7D,QAAM,MAAMA,MAAK,SAAS,MAAM,MAAM;AACtC,MAAI,IAAI,WAAW,IAAI,KAAKA,MAAK,WAAW,GAAG,GAAG;AAChD,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACpC;AACA,SAAO;AACT;AAdgB;AAiBhB,eAAsB,WAAW,KAAa;AAC5C,QAAM,WAAWA,MAAK,QAAQ,GAAG;AACjC,QAAM,QAAQ,MAAMC,IAAG,KAAK,QAAQ;AACpC,MAAI,CAAC,MAAM,YAAY,GAAG;AACxB,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AACA,QAAM,UAAUD,MAAK,SAAS,QAAQ;AACtC,QAAM,UAAU,MAAMC,IAAG,QAAQ,UAAU,EAAE,eAAe,KAAK,CAAC;AAClE,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,QAAQ,IAAI,OAAO,UAAU;AAC3B,YAAM,WAAWD,MAAK,KAAK,UAAU,MAAM,IAAI;AAC/C,YAAM,KAAK,MAAMC,IAAG,KAAK,QAAQ;AACjC,YAAM,MAAM,MAAM,KAAK,YAAY,GAAG;AACtC,YAAM,OAAO,MAAM,YAAY,IAC3B,QACA,MAAM,KACJ,MAAM,KAAK,UAAU,GAAG,IACxB;AACN,aAAO;AAAA,QACL,MAAM,MAAM;AAAA,QACZ,MAAM,GAAG;AAAA,QACT,MAAM,GAAG,MAAM,YAAY;AAAA,QAC3B,MAAMD,MAAK,UAAU,QAAQ;AAAA,QAC7B;AAAA,QACA,SAAS,GAAG,UAAU,YAAY;AAAA,QAClC,aAAa,GAAG,KAAK,SAAS,CAAC,EAAE,MAAM,EAAE;AAAA,MAC3C;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,MAAM;AAAA,IACZ,MAAM,MAAM,MAAM,YAAY;AAAA,IAC9B,MAAMA,MAAK,UAAU,QAAQ;AAAA,IAC7B,MAAM;AAAA,IACN,SAAS,MAAM,UAAU,YAAY;AAAA,IACrC,aAAa,MAAM,KAAK,SAAS,CAAC,EAAE,MAAM,EAAE;AAAA,IAC5C;AAAA,EACF;AACF;AAvCsB;AA0CtB,eAAsB,WAAW,UAAiC;AAChE,MAAI;AACF,UAAMC,IAAG,OAAOD,MAAK,UAAU,QAAQ,CAAC;AAAA,EAC1C,SAAS,KAAc;AACrB,QAAK,KAA+B,SAAS,SAAU,OAAM;AAAA,EAC/D;AACF;AANsB;AASf,IAAM,SAAS;AAGtB,eAAsB,MAAM,UAAkB,SAAgC;AAC5E,QAAM,aAAaA,MAAK,UAAU,QAAQ;AAC1C,QAAMC,IAAG,MAAMD,MAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,QAAMC,IAAG,UAAU,YAAY,SAAS,MAAM;AAChD;AAJsB;AAOtB,eAAsB,KAAK,UAAmC;AAC5D,SAAOA,IAAG,SAASD,MAAK,UAAU,QAAQ,GAAG,MAAM;AACrD;AAFsB;AAKtB,eAAsB,UAAU,UAAkB,MAA8B;AAC9E,QAAM,MAAM,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACrD;AAFsB;;;AChHtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,YAAYE,UAAQ;AACpB,YAAYC,eAAc;AAOnB,SAAS,eAAwB;AACtC,SAAO,OAAQ,QAAuB,QAAQ;AAChD;AAFgB;AAQT,SAAS,oBAAwC;AACtD,MAAI,CAAC,aAAa,EAAG,QAAO;AAC5B,QAAM,QACH,QAAuB,KAAK,cAC5B,QAAuB,KAAK;AAC/B,MAAI,CAAC,MAAO,QAAO;AACnB,SAAgB,kBAAiB,kBAAQ,KAAK,CAAC;AACjD;AAPgB;AAUT,SAAS,cAAsB;AACpC,QAAM,WAAW,kBAAkB;AACnC,MAAI,SAAU,QAAO;AAErB,QAAM,QAAQ,QAAQ,KAAK,CAAC;AAC5B,MAAI,CAAC,OAAO;AACV,WAAgB,kBAAQ,QAAQ,QAAQ;AAAA,EAC1C;AACA,SAAgB,kBAAiB,kBAAQ,KAAK,CAAC;AACjD;AATgB;AAYT,SAAS,aAAqB;AACnC,SAAgB,kBAAQ,QAAQ,QAAQ;AAC1C;AAFgB;AAQT,SAAS,qBAA+B;AAC7C,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAM,wBAAC,MAA0B;AACrC,QAAI,CAAC,EAAG;AACR,UAAM,MAAe,kBAAQ,CAAC;AAC9B,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,WAAK,IAAI,GAAG;AACZ,YAAM,KAAK,GAAG;AAAA,IAChB;AAAA,EACF,GAPY;AASZ,MAAI,QAAQ,IAAI,CAAC;AACjB,MAAI,WAAW,CAAC;AAEhB,MAAI,aAAa,GAAG;AAClB,QAAI,kBAAkB,CAAC;AAAA,EACzB,OAAO;AACL,UAAM,WAAW,YAAY;AAC7B,QAAI,aAAa,WAAW,GAAG;AAC7B,UAAI,QAAQ;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AACT;AAzBgB;AA4BT,SAAS,uBAA+B;AAC7C,aAAW,QAAQ,mBAAmB,GAAG;AACvC,QAAI;AACF,UAAO,cAAkB,eAAK,MAAM,QAAQ,CAAC,EAAE,YAAY,GAAG;AAC5D,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI,aAAa,GAAG;AAClB,WAAO,WAAW;AAAA,EACpB;AACA,SAAO,YAAY;AACrB;AAdgB;;;ACrEhB,IAAO,cAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACxBA,YAAYC,WAAU;AAcf,SAAS,eACd,OACA,KACkB;AAClB,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAM,KAAK,CAAC,KAAK,WAAW;AAC1B,UAAI,KAAK;AACP,eAAO,GAAG;AACV;AAAA,MACF;AACA,UAAI,CAAC,UAAW,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,GAAI;AAC7D,QAAAA,SAAQ,EAAE;AACV;AAAA,MACF;AACA,MAAAA,SAAQ,MAAM;AAAA,IAChB,CAAC;AAAA,EACH,CAAC;AACH;AAjBgB;AAoBT,SAAS,aAAa,OAA+B;AAC1D,MAAI,CAAC,MAAO,QAAO,CAAC;AACpB,SAAO,OAAO,UAAU,WAAW,MAAM,MAAM,GAAG,IAAI;AACxD;AAHgB;AAsDT,SAAS,aAAa,SAAiB,YAA6B;AACzE,QAAM,OAAY,cAAQ,OAAO;AACjC,QAAM,SAAc,cAAQ,UAAU;AACtC,QAAMC,YAAgB,eAAS,MAAM,MAAM;AAC3C,MAAI,CAACA,UAAU,QAAO;AACtB,SAAO,CAACA,UAAS,WAAW,IAAI,KAAK,CAAM,iBAAWA,SAAQ;AAChE;AANgB;AAYT,SAAS,cAAc,UAAkB,UAA4B;AAC1E,QAAM,QAAQ,CAAC,MAAM,QAAQ,OAAO,GAAG,GAAG,GAAG,SAAS,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,QAAQ,OAAO,GAAG,CAAC,CAAC;AAC/F,SAAO,MAAM,OAAO,OAAO,EAAE,KAAK,GAAG;AACvC;AAHgB;AAMT,SAAS,WAAW,OAA8B;AACvD,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,SAAS,IAAI;AACzD,SAAO,MAAM,SAAS,IAAI;AAC5B;AAJgB;AAOT,SAAS,oBAAoB,KAAsE;AACxG,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,MAAM,IAAI,WAAW;AAC3B,MAAI,IAAI,SAAS,sBAAsB,IAAI,SAAS,gBAAgB;AAClE,WAAO,IAAI,SAAS,eAAe,KAAK,IAAI,SAAS,eAAe;AAAA,EACtE;AACA,SAAO,IAAI,SAAS,eAAe,KAAK,IAAI,SAAS,eAAe;AACtE;AAPgB;;;AC3GhB,SAAS,WAAW,OAAuB;AACzC,QAAM,OAAO,OAAO,KAAK,EAAE,QAAQ,MAAM,IAAI;AAC7C,SAAO,IAAI,IAAI;AACjB;AAHS;AAMT,SAAS,iBAAiB,OAA0C;AAClE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,OAAQ,QAAO;AAEnD,QAAM,QAAkB,CAAC;AACzB,MAAI,YAAY;AAEhB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,SAAS,QAAQ,SAAS,OAAO;AACnC,kBAAY;AACZ;AAAA,IACF;AACA,QAAI,CAAC,MAAM,QAAQ,IAAI,EAAG;AAC1B,UAAM,CAAC,OAAO,IAAI,GAAG,IAAI;AACzB,QAAI,CAAC,MAAM,QAAQ;AACjB,YAAM,KAAK,GAAG,KAAK,IAAI,EAAE,IAAI,GAAG,EAAE;AAAA,IACpC,OAAO;AACL,YAAM,KAAK,GAAG,SAAS,IAAI,KAAK,IAAI,EAAE,IAAI,GAAG,EAAE;AAAA,IACjD;AAAA,EACF;AAEA,SAAO,MAAM,SAAS,UAAU,MAAM,KAAK,GAAG,CAAC,KAAK;AACtD;AAtBS;AAyBT,SAAS,iBAAiB,OAA0C;AAClE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,OAAQ,QAAO;AACnD,QAAM,QAAQ,MAAM,IAAI,CAAC,IAAI,MAAM;AACjC,UAAM,SAAS,IAAI,IAAI,MAAM;AAC7B,WAAO,GAAG,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;AAAA,EACpC,CAAC;AACD,SAAO,YAAY,MAAM,KAAK,EAAE,CAAC;AACnC;AAPS;AAUT,SAAS,iBAAiB,OAAwB;AAChD,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,IAAI,OAAO,KAAK;AACtB,MAAI,kBAAkB,KAAK,CAAC,EAAG,QAAO;AACtC,MAAI,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG,EAAG,QAAO;AACjD,SAAO,IAAI,EAAE,QAAQ,MAAM,IAAI,CAAC;AAClC;AANS;AAST,SAAS,iBAAiB,QAA2C;AACnE,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,CAAC,OAAO,OAAQ,QAAO;AACrD,QAAM,OAAQ,OAAuB,IAAI,CAAC,QAAQ,IAAI,IAAI,IAAI,gBAAgB,EAAE,KAAK,GAAG,CAAC,GAAG;AAC5F,SAAO,WAAW,KAAK,KAAK,GAAG,CAAC;AAClC;AAJS;AAOT,SAAS,eAAe,MAAuC;AAC7D,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC,KAAK,OAAQ,QAAO;AAEjD,QAAM,QAAQ,KAAK,IAAI,CAAC,MAAM,MAAM;AAClC,UAAM,SAAS,IAAI,IAAI,MAAM;AAC7B,UAAM,KAAK;AACX,UAAM,CAAC,OAAO,SAAS,GAAG,IAAI;AAE9B,QAAI,OAAO,QAAQ,YAAY,SAAS;AACtC,aAAO,GAAG,MAAM,GAAG,KAAK,IAAI,KAAK,GAAG,OAAO,GAAG,GAAG;AAAA,IACnD;AACA,QAAI,OAAO,QAAQ,YAAY,SAAS;AACtC,UAAI,YAAY,UAAU;AACxB,eAAO,GAAG,MAAM,GAAG,KAAK,IAAI,OAAO,IAAI,KAAK,KAAK,GAAG;AAAA,MACtD;AACA,aAAO,GAAG,MAAM,GAAG,KAAK,IAAI,KAAK,GAAG,OAAO,IAAI,GAAG;AAAA,IACpD;AACA,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,GAAG,MAAM,GAAG,KAAK,IAAI,OAAO;AAAA,IACrC;AACA,WAAO,GAAG,MAAM,GAAG,KAAK,KAAK,OAAO;AAAA,EACtC,CAAC;AAED,SAAO,QAAQ,MAAM,KAAK,EAAE,CAAC;AAC/B;AAxBS;AA2BT,SAAS,iBAAiB,QAA2C;AACnE,QAAM,OAAO,aAAa,MAAM;AAChC,SAAO,KAAK,SAAS,KAAK,KAAK,KAAK,GAAG,CAAC,MAAM;AAChD;AAHS;AAKT,IAAO,cAAQ;AAAA;AAAA;AAAA;AAAA,EAIb,QAAQ,KAAU,MAAwB;AACxC,UAAM,MAAM,IAAI,IAAI;AACpB,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,UAAI,CAAC,IAAI,OAAQ,QAAO;AACxB,cAAQ,MAAM;AAAA,QACZ,KAAK;AACH,iBAAO,iBAAiB,GAAgC;AAAA,QAC1D,KAAK;AACH,iBAAO,iBAAiB,GAAgC;AAAA,QAC1D,KAAK;AACH,iBAAO,iBAAiB,GAAgC;AAAA,QAC1D,KAAK;AACH,iBAAO,eAAe,GAA8B;AAAA,QACtD,KAAK;AACH,iBAAO,iBAAiB,GAAgC;AAAA,MAC5D;AAAA,IACF;AACA,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,MAAM,OAAO,GAAG;AACtB,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,UAAU,GAAG;AAAA,MACtB,KAAK;AACH,eAAO,aAAa,GAAG;AAAA,MACzB,KAAK;AACH,eAAO,YAAY,GAAG;AAAA,MACxB,KAAK;AACH,eAAO,QAAQ,GAAG;AAAA,MACpB,KAAK;AACH,eAAO,KAAK,GAAG;AAAA,MACjB;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,KAAkB;AACxB,UAAM,QAAQ,WAAW,IAAI,KAAK;AAClC,UAAM,KAAK,IAAI;AACf,YAAQ,IAAI;AAAA,MACV,KAAK;AACH,eAAO,eAAe,KAAK,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC;AAAA,MACvF,KAAK;AACH,eAAO,eAAe,KAAK,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC;AAAA,MAC1D,KAAK;AACH,eAAO,UAAU,KAAK,GAAG,KAAK,QAAQ,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC;AAAA,MAChF,KAAK,UAAU;AACb,cAAM,SAAS,IAAI,QAAQ,IAAI,IAAI,KAAK,KAAK;AAC7C,cAAM,QAAQ,IAAI,QAAQ,UAAU,IAAI,KAAK,KAAK;AAClD,eAAO,SAAS,MAAM,SAAS,KAAK,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC,GAAG,KAAK;AAAA,MACxG;AAAA,MACA;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,KAAU,UAAuC,SAAiB;AAC1E,UAAM,SAAS,YAAY,WAAW,kBAAkB;AACxD,UAAM,SAAS,aAAa,IAAI,KAAK;AACrC,UAAM,UAAoB,CAAC;AAE3B,QAAI,CAAC,WAAW,IAAI,KAAK,GAAG;AAC1B,cAAQ,KAAK,0BAA0B,MAAM,EAAE;AAAA,IACjD;AACA,WAAO,QAAQ,CAAC,SAAS,QAAQ,KAAK,GAAG,IAAI,OAAO,CAAC;AACrD,UAAM,YACJ,YAAY,WAAW,0CAA0C;AACnE,YAAQ,KAAK,SAAS;AAEtB,WAAO,8BAA8B,WAAW,IAAI,KAAK,CAAC,KAAK,QAAQ,KAAK,GAAG,CAAC;AAAA,EAClF;AACF;;;AC9KA,OAAO,WAAW;AAWlB,IAAM,UAAN,MAAc;AAAA,EAdd,OAcc;AAAA;AAAA;AAAA,EAIZ,YAAY,QAAqB;AAC/B,SAAK,SAAS;AACd,SAAK,OAAO,MAAM,WAAW,MAAM;AAAA,EACrC;AAAA,EAEQ,OAAO,KAAU,KAA6D;AACpF,QAAI,KAAK,OAAO,UAAU,oBAAoB,GAA0C,GAAG;AACzF,WAAK,YAAY,GAAG;AAAA,IACtB;AACA,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEQ,UAAU,MAAwB;AACxC,WAAO,QAAQ;AAAA,EACjB;AAAA,EAEA,MAAM,KAAU,UAA+D;AAC7E,SAAK,KAAK,cAAc,CAAC,OAAO,eAAe;AAC7C,UAAI,OAAO;AACT,iBAAS,KAAK,OAAO,KAAK,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC;AACtD;AAAA,MACF;AAEA,iBAAW,MAAM,YAAI,QAAQ,GAAG,GAAG,CAAC,KAAK,SAAS;AAChD,YAAI;AACF,mBAAS,KAAK,OAAO,KAAK,GAAG,GAAG,KAAK,UAAU,IAAI,CAAC;AAAA,QACtD,UAAE;AACA,qBAAW,QAAQ;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,KAA4B;AAChC,WAAO,eAAe,KAAK,MAAM,KAAK,IAAI,GAAG,GAAG;AAAA,EAClD;AAAA;AAAA,EAGA,MAAM,UAA8C;AAClD,SAAK,KAAK,IAAI,QAAQ;AAAA,EACxB;AAAA;AAAA,EAGQ,YAAY,KAAgB;AAClC,QAAI,CAAC,KAAK,OAAO,OAAQ;AAEzB,UAAM,OAAO,MAAM,iBAAiB;AAAA,MAClC,MAAM,KAAK,OAAO;AAAA,MAClB,MAAM,KAAK,OAAO;AAAA,MAClB,UAAU,KAAK,OAAO;AAAA,IACxB,CAAC;AAED,SAAK,QAAQ,CAAC,QAAQ;AACpB,UAAI,KAAK;AACP,aAAK,IAAI;AACT;AAAA,MACF;AAEA,WAAK,MAAM,iCAAiC,KAAK,OAAO,QAAQ,KAAK,CAAC,UAAU;AAC9E,YAAI,OAAO;AACT,eAAK,IAAI;AACT;AAAA,QACF;AAEA,aAAK,OAAO,MAAM,WAAW,KAAK,MAAM;AACxC,aAAK,KAAK,cAAc,CAAC,SAAS,eAAe;AAC/C,cAAI,WAAW,CAAC,YAAY;AAC1B,iBAAK,IAAI;AACT;AAAA,UACF;AAEA,qBAAW,MAAM,YAAI,UAAU,KAAK,OAAO,GAAG,MAAM;AAClD,uBAAW,QAAQ;AACnB,iBAAK,IAAI;AAAA,UACX,CAAC;AAAA,QACH,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AAEA,IAAOC,iBAAQ;;;AChGf,YAAYC,UAAQ;AACpB,YAAYC,WAAU;AACtB,OAAO,mBAAmB;AAG1B,IAAM,UACH,cAAgE,WAAW;AAG9E,IAAM,0BAA0B;AAChC,IAAM,6BAA6B;AAKnC,SAAS,0BAA0B,IAAS,gBAAwB,yBAAwC;AAC1G,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,CAAC;AACpD,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,OAAG,UAAU,MAAM;AACjB,SAAG,IAAI,2BAA2B;AAClC,SAAG,IAAI,yBAAyB,MAAM,EAAE;AACxC,SAAG,IAAI,+BAA+B,CAAC,QAAsB;AAC3D,YAAI,IAAK,QAAO,GAAG;AAAA,YACd,CAAAA,SAAQ;AAAA,MACf,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;AAZS;AA+BT,IAAM,mBAAN,MAAM,kBAAiB;AAAA,EAjDvB,OAiDuB;AAAA;AAAA;AAAA;AAAA,EAOb,YAAY,IAAS,QAAoB;AAC/C,SAAK,KAAK;AACV,SAAK,SAAS;AACd,SAAK,WAAW,KAAK,IAAI;AACzB,SAAK,QAAQ;AACb,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAO,QAA+C;AACjE,aAAS,SAAS,MAAa;AAC7B,OAAC,QAAQ,OAAO,QAAQ,QAAQ,KAAK,UAAU,GAAG,IAAI;AAAA,IACxD;AAFS;AAIT,UAAM,eAAoB,cAAQ,OAAO,QAAQ;AACjD,UAAM,MAAW,cAAQ,YAAY;AACrC,QAAI,CAAI,gBAAW,GAAG,GAAG;AACvB,MAAG,eAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACrC,YAAM,SAAS,GAAG;AAAA,IACpB;AAEA,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,YAAM,KAAK,IAAI,QAAQ,SAAS,cAAc,QAAQ,iBAAiB,QAAQ,aAAa,OAAO,QAAa;AAC9G,YAAI,KAAK;AACP,gBAAM,eAAe,oCAAoC,cAAc,IAAI,OAAO;AAClF,iBAAO,GAAG;AACV;AAAA,QACF;AACA,YAAI;AACF,gBAAM,0BAA0B,IAAI,OAAO,eAAe,uBAAuB;AACjF,gBAAM,QAAQ,YAAY;AAC1B,UAAAA,SAAQ,IAAI,kBAAiB,IAAI,MAAM,CAAC;AAAA,QAC1C,SAAS,WAAgB;AACvB,aAAG,MAAM,MAAM;AAAA,UAAC,CAAC;AACjB,iBAAO,SAAS;AAAA,QAClB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,OAAyB;AAC7B,WAAO,IAAI,QAAQ,CAACA,aAAY;AAC9B,UAAI,CAAC,KAAK,QAAS,QAAOA,SAAQ,KAAK;AACvC,WAAK,GAAG,IAAI,YAAY,CAAC,QAAa;AACpC,aAAK,UAAU,CAAC;AAChB,QAAAA,SAAQ,KAAK,OAAO;AAAA,MACtB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,QAAuB;AAC3B,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,WAAK,GAAG,MAAM,CAAC,QAAa;AAC1B,YAAI,IAAK,QAAO,GAAG;AAAA,YACd,CAAAA,SAAQ;AAAA,MACf,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,aAAa;AACX,SAAK,UAAU;AAAA,EACjB;AACF;AAMO,IAAM,aAAN,MAAiB;AAAA;AAAA,EAYtB,YAAY,QAAoB;AAVhC,SAAQ,OAA2B,CAAC;AACpC,SAAQ,eAIH,CAAC;AACN,SAAQ,mBAA0C;AAClD,SAAQ,cAAc;AAIpB,SAAK,SAAS;AAAA,MACZ,UAAU,OAAO;AAAA,MACjB,SAAS,OAAO,WAAW;AAAA,MAC3B,SAAS,OAAO,WAAW;AAAA,MAC3B,aAAa,OAAO,eAAe;AAAA,MACnC,gBAAgB,OAAO,kBAAkB;AAAA,MACzC,aAAa,OAAO,eAAe;AAAA,MACnC,mBAAmB,OAAO,qBAAqB;AAAA,MAC/C,OAAO,OAAO,SAAS;AAAA,IACzB;AAEA,SAAK,cAAc,KAAK,eAAe;AACvC,SAAK,iBAAiB;AAAA,EACxB;AAAA,EA3JF,OAiIwB;AAAA;AAAA;AAAA;AAAA,EA6Bd,SAAS,MAAa;AAC5B,KAAC,KAAK,QAAQ,OAAO,QAAQ,QAAQ,KAAK,UAAU,GAAG,IAAI;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAc,iBAAiB;AAC7B,UAAM,WAA4B,CAAC;AACnC,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,SAAS,KAAK;AAC5C,eAAS,KAAK,KAAK,iBAAiB,CAAC;AAAA,IACvC;AACA,UAAM,UAAU,MAAM,QAAQ,WAAW,QAAQ;AACjD,UAAM,eAAe,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW,EAAE;AACrE,QAAI,iBAAiB,GAAG;AACtB,WAAK,MAAM,yBAAyB,sDAAsD;AAAA,IAC5F,OAAO;AACL,WAAK,MAAM,eAAe,6BAA6B,KAAK,KAAK,MAAM;AAAA,IACzE;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,mBAAkC;AAC9C,QAAI,KAAK,KAAK,UAAU,KAAK,OAAO,QAAS;AAC7C,QAAI;AACF,YAAM,OAAO,MAAM,iBAAiB,OAAO,KAAK,MAAM;AACtD,YAAM,UAAU,MAAM,KAAK,KAAK;AAChC,UAAI,SAAS;AACX,aAAK,KAAK,KAAK,IAAI;AAAA,MACrB,OAAO;AACL,cAAM,KAAK,MAAM,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AACjC,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAAA,IACF,SAAS,KAAU;AACjB,WAAK,MAAM,0BAA0B,uCAAuC,IAAI,OAAO;AACvF,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAqC;AACzC,UAAM,KAAK;AAEX,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,eAAe,KAAK,IAAI,KAAK,OAAO,aAAa,GAAI;AAG3D,eAAW,QAAQ,KAAK,MAAM;AAC5B,UAAI,CAAC,KAAK,OAAO;AACf,YAAI,MAAM,KAAK,WAAW,cAAc;AACtC,gBAAM,UAAU,MAAM,KAAK,KAAK;AAChC,cAAI,CAAC,SAAS;AACZ,iBAAK,iBAAiB,IAAI;AAC1B;AAAA,UACF;AAAA,QACF;AACA,aAAK,QAAQ;AACb,aAAK,WAAW;AAChB,eAAO;AAAA,MACT;AAAA,IACF;AAGA,QAAI,KAAK,KAAK,SAAS,KAAK,OAAO,SAAS;AAC1C,UAAI;AACF,cAAM,OAAO,MAAM,iBAAiB,OAAO,KAAK,MAAM;AACtD,cAAM,UAAU,MAAM,KAAK,KAAK;AAChC,YAAI,SAAS;AACX,eAAK,QAAQ;AACb,eAAK,WAAW,KAAK,IAAI;AACzB,eAAK,KAAK,KAAK,IAAI;AACnB,iBAAO;AAAA,QACT,OAAO;AACL,gBAAM,KAAK,MAAM,EAAE,MAAM,MAAM;AAAA,UAAC,CAAC;AAAA,QACnC;AAAA,MACF,SAAS,GAAQ;AACf,aAAK,MAAM,iBAAiB,uDAAuD,EAAE,OAAO;AAAA,MAC9F;AAAA,IACF;AAGA,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,YAAM,QAAQ,WAAW,MAAM;AAC7B,cAAM,MAAM,KAAK,aAAa,UAAU,CAAC,SAAS,KAAK,UAAU,KAAK;AACtE,YAAI,QAAQ,IAAI;AACd,eAAK,aAAa,OAAO,KAAK,CAAC;AAAA,QACjC;AACA,eAAO,IAAI,MAAM,oBAAoB,KAAK,OAAO,cAAc,KAAK,CAAC;AAAA,MACvE,GAAG,KAAK,OAAO,cAAc;AAE7B,WAAK,aAAa,KAAK,EAAE,SAAAA,UAAS,QAAQ,MAAM,CAAC;AAAA,IACnD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,QAAQ,MAAwB;AAC9B,QAAI,CAAC,KAAM;AACX,SAAK,QAAQ;AACb,SAAK,WAAW,KAAK,IAAI;AAEzB,QAAI,KAAK,aAAa,SAAS,GAAG;AAChC,YAAM,OAAO,KAAK,aAAa,MAAM;AACrC,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AACb,WAAK,WAAW,KAAK,IAAI;AACzB,WAAK,QAAQ,IAAI;AAAA,IACnB;AAAA,EACF;AAAA;AAAA,EAGQ,iBAAiB,MAAwB;AAC/C,UAAM,QAAQ,KAAK,KAAK,QAAQ,IAAI;AACpC,QAAI,UAAU,IAAI;AAChB,WAAK,KAAK,OAAO,OAAO,CAAC;AACzB,WAAK,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA,EAGQ,mBAAmB;AACzB,SAAK,mBAAmB,YAAY,YAAY;AAC9C,UAAI,KAAK,YAAa;AAEtB,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,WAA+B,CAAC;AAEtC,iBAAW,QAAQ,KAAK,MAAM;AAC5B,YAAI,CAAC,KAAK,SAAS,MAAM,KAAK,WAAW,KAAK,OAAO,eAAe,KAAK,KAAK,SAAS,KAAK,OAAO,SAAS;AAC1G,mBAAS,KAAK,IAAI;AAAA,QACpB;AAAA,MACF;AAEA,iBAAW,QAAQ,UAAU;AAC3B,aAAK,iBAAiB,IAAI;AAAA,MAC5B;AAEA,UAAI,SAAS,SAAS,GAAG;AACvB,aAAK,MAAM,aAAa,oBAAoB,SAAS,QAAQ,wCAAwC,KAAK,KAAK,MAAM;AAAA,MACvH;AAAA,IACF,GAAG,GAAK;AAAA,EACV;AAAA;AAAA,EAGA,YAAY;AACV,UAAM,QAAQ,KAAK,KAAK,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE;AAC/C,WAAO;AAAA,MACL,OAAO,KAAK,KAAK;AAAA,MACjB;AAAA,MACA,MAAM,KAAK,KAAK,SAAS;AAAA,MACzB,SAAS,KAAK,aAAa;AAAA,MAC3B,KAAK,KAAK,OAAO;AAAA,MACjB,KAAK,KAAK,OAAO;AAAA,IACnB;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,UAAU;AACd,QAAI,KAAK,YAAa;AACtB,SAAK,cAAc;AAEnB,QAAI,KAAK,kBAAkB;AACzB,oBAAc,KAAK,gBAAgB;AACnC,WAAK,mBAAmB;AAAA,IAC1B;AAEA,eAAW,UAAU,KAAK,cAAc;AACtC,mBAAa,OAAO,KAAK;AACzB,aAAO,OAAO,IAAI,MAAM,sBAAsB,CAAC;AAAA,IACjD;AACA,SAAK,eAAe,CAAC;AAErB,UAAM,QAAQ,WAAW,KAAK,KAAK,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC;AAC9D,SAAK,OAAO,CAAC;AACb,SAAK,MAAM,aAAa,kBAAkB;AAAA,EAC5C;AACF;AAOA,IAAM,YAAN,MAAgB;AAAA,EAQd,YAAY,QAAa;AANzB,SAAQ,OAA0B;AAClC,SAAQ,WAAgB;AACxB,SAAQ,gBAAsC;AAE9C;AAAA,SAAQ,UAAyB,QAAQ,QAAQ;AAG/C,SAAK,SAAS;AACd,UAAM,UAAU,QAAQ,QAAQ;AAEhC,QAAI,OAAO,YAAY,MAAM;AAC3B,WAAK,OAAO,IAAI,WAAW;AAAA,QACzB,UAAU,OAAO;AAAA,QACjB,SAAS,OAAO,WAAW;AAAA,QAC3B,SAAS,OAAO,WAAW;AAAA,QAC3B,aAAa,OAAO;AAAA,QACpB,gBAAgB,OAAO,kBAAkB;AAAA,QACzC,aAAa,OAAO,eAAe;AAAA,QACnC,mBAAmB,OAAO;AAAA,QAC1B,OAAO,OAAO;AAAA,MAChB,CAAC;AAAA,IACH,OAAO;AAEL,WAAK,gBAAgB,KAAK,qBAAqB,OAAO,UAAU,OAAO;AAAA,IACzE;AAAA,EACF;AAAA,EAtXF,OA2VgB;AAAA;AAAA;AAAA,EA6BN,cAAiB,MAAoC;AAC3D,UAAM,MAAM,KAAK,QAAQ,KAAK,MAAM,KAAK,CAAC;AAC1C,SAAK,UAAU,IAAI;AAAA,MACjB,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,MAAa;AAC5B,KAAC,KAAK,QAAQ,OAAO,QAAQ,QAAQ,KAAK,UAAU,GAAG,IAAI;AAAA,EAC7D;AAAA,EAEA,MAAc,qBAAqB,cAAsB,SAA6B;AACpF,UAAM,eAAoB,cAAQ,YAAY;AAC9C,UAAM,MAAW,cAAQ,YAAY;AACrC,QAAI,CAAI,gBAAW,GAAG,GAAG;AACvB,MAAG,eAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACrC,WAAK,MAAM,SAAS,WAAW,GAAG;AAAA,IACpC;AAEA,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,WAAK,WAAW,IAAI,QAAQ,SAAS,cAAc,QAAQ,iBAAiB,QAAQ,aAAa,OAAO,QAAa;AACnH,YAAI,KAAK;AACP,eAAK,MAAM,eAAe,6CAA6C,cAAc,IAAI,OAAO;AAChG,iBAAO,GAAG;AACV;AAAA,QACF;AACA,YAAI;AACF,gBAAM,0BAA0B,KAAK,UAAU,KAAK,OAAO,eAAe,uBAAuB;AACjG,eAAK,MAAM,QAAQ,6BAA6B,YAAY;AAC5D,UAAAA,SAAQ;AAAA,QACV,SAAS,WAAW;AAClB,eAAK,SAAS,MAAM,MAAM;AAAA,UAAC,CAAC;AAC5B,iBAAO,SAAS;AAAA,QAClB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,OAAO,MAAW,KAA4E;AACpG,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEQ,UAAU,MAAgB;AAChC,WAAO,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAU,UAAqD;AACnE,UAAM,SAAS,YAAI,QAAQ,GAAG;AAE9B,UAAM,eAAe,wBAAC,IAAS,YAAyB;AACtD,YAAM,SAAS,wBAAC,KAAU,SAAc;AACtC,kBAAU;AACV,iBAAS,KAAK,OAAO,KAAK,GAAG,GAAG,KAAK,UAAU,IAAI,CAAC;AAAA,MACtD,GAHe;AAKf,UAAI;AACF,YAAI,IAAI,SAAS,UAAU;AACzB,aAAG,IAAI,QAAQ,MAAM;AAAA,QACvB,OAAO;AACL,aAAG,IAAI,QAAQ,CAAC,QAAa;AAC3B,mBAAO,KAAK,IAAI;AAAA,UAClB,CAAC;AAAA,QACH;AAAA,MACF,SAAS,GAAG;AACV,kBAAU;AACV,iBAAS,KAAK,OAAO,KAAK,CAAwC,GAAG,KAAK,UAAU,WAAW,CAAC;AAAA,MAClG;AAAA,IACF,GAlBqB;AAoBrB,QAAI,KAAK,MAAM;AACb,WAAK,KACF,QAAQ,EACR,KAAK,CAAC,SAAS;AACd,qBAAa,KAAK,IAAI,MAAM,KAAK,KAAM,QAAQ,IAAI,CAAC;AAAA,MACtD,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,iBAAS,KAAK,OAAO,KAAK,GAAG,GAAG,KAAK,UAAU,YAAY,CAAC;AAAA,MAC9D,CAAC;AAAA,IACL,OAAO;AACL,OAAC,KAAK,iBAAiB,QAAQ,QAAQ,GACpC,KAAK,MAAM;AACV,qBAAa,KAAK,QAAQ;AAAA,MAC5B,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,iBAAS,KAAK,OAAO,KAAK,GAAG,GAAG,KAAK,UAAU,kBAAkB,CAAC;AAAA,MACpE,CAAC;AAAA,IACL;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAA4B;AAChC,WAAO,KAAK,cAAc,MAAM,KAAK,aAAa,GAAG,CAAC;AAAA,EACxD;AAAA,EAEA,MAAc,aAAa,KAA4B;AACrD,QAAI;AACF,aAAO,MAAM,eAAe,KAAK,MAAM,KAAK,IAAI,GAAG,GAAG;AAAA,IACxD,SAAS,KAAU;AACjB,YAAM,SAAS,EAAE,SAAS,OAAO,KAAK,WAAW,OAAO,EAAE,EAAE;AAC5D,UAAI,KAAK,OAAO,UAAU,IAAI,SAAS,YAAY,oBAAoB,MAAM,GAAG;AAC9E,cAAM,KAAK,YAAY,GAAG;AAC1B,eAAO,eAAe,KAAK,MAAM,KAAK,IAAI,GAAG,GAAG;AAAA,MAClD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YAAY,KAAyB;AACjD,UAAM,YAAY,YAAI,UAAU,KAAK,QAAQ;AAC7C,QAAI,CAAC,UAAW;AAEhB,QAAI,KAAK,MAAM;AACb,UAAI,OAAgC;AACpC,UAAI;AACF,eAAO,MAAM,KAAK,KAAK,QAAQ;AAC/B,cAAM,IAAI,QAAc,CAACA,UAAS,WAAW;AAC3C,eAAM,GAAG,IAAI,WAAW,CAAC,QAAa;AACpC,gBAAI,IAAK,QAAO,GAAG;AAAA,gBACd,CAAAA,SAAQ;AAAA,UACf,CAAC;AAAA,QACH,CAAC;AACD,aAAK,MAAM,WAAW,oBAAoB,SAAS;AAAA,MACrD,SAAS,GAAG;AACV,aAAK,MAAM,mBAAmB,4BAA4B,CAAC;AAAA,MAC7D,UAAE;AACA,YAAI,KAAM,MAAK,KAAK,QAAQ,IAAI;AAAA,MAClC;AAAA,IACF,OAAO;AACL,YAAM,KAAK;AACX,YAAM,IAAI,QAAc,CAACA,UAAS,WAAW;AAC3C,aAAK,SAAS,IAAI,WAAW,CAAC,QAAa;AACzC,cAAI,IAAK,QAAO,GAAG;AAAA,cACd,CAAAA,SAAQ;AAAA,QACf,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA,EAGA,gBAAgB;AACd,QAAI,KAAK,MAAM;AACb,aAAO,KAAK,KAAK,UAAU;AAAA,IAC7B;AACA,WAAO,EAAE,MAAM,oBAAoB;AAAA,EACrC;AAAA;AAAA,EAGA,MAAM,QAAQ;AACZ,QAAI,KAAK,MAAM;AACb,YAAM,KAAK,KAAK,QAAQ;AAAA,IAC1B,WAAW,KAAK,UAAU;AACxB,YAAM,IAAI,QAAc,CAACA,UAAS,WAAW;AAC3C,aAAK,SAAS,MAAM,CAAC,QAAa;AAChC,cAAI,IAAK,QAAO,GAAG;AAAA,cACd,CAAAA,SAAQ;AAAA,QACf,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,IAAOC,iBAAQ;;;AC/hBf,YAAYC,UAAQ;AACpB,YAAYC,WAAU;AAUtB,IAAM,SAAN,MAAa;AAAA,EAbb,OAaa;AAAA;AAAA;AAAA,EAOX,YAAY,QAAsB;AAChC,SAAK,SAAS;AACd,SAAK,UAAU,OAAO,QAAQ,OAAO,KAAK,OAAO,OAAO;AACxD,SAAK,WAAW,OAAO,OAAO,OAAO;AACrC,SAAK,YAAY,OAAO,UAAU;AAClC,SAAK,aAAkB,cAAQ,QAAQ,IAAI,GAAG,OAAO,GAAG;AAAA,EAC1D;AAAA,EAEQ,SAAS,MAAa;AAC5B,KAAC,KAAK,QAAQ,OAAO,QAAQ,QAAQ,KAAK,QAAQ,GAAG,IAAI;AAAA,EAC3D;AAAA,EAEA,UAAU,MAAuB;AAC/B,WAAU,gBAAW,KAAK,WAAW,MAAM,KAAK,CAAC;AAAA,EACnD;AAAA;AAAA,EAGQ,YAAY,SAAyB;AAC3C,QAAI,CAAC,SAAS;AACZ,aAAO,KAAK;AAAA,IACd;AACA,UAAM,MAAW,iBAAW,OAAO,IAC1B,gBAAU,OAAO,IACjB,cAAQ,KAAK,YAAY,OAAO;AACzC,QAAI,CAAC,aAAa,KAAK,YAAY,GAAG,GAAG;AACvC,aAAO,KAAK;AAAA,IACd;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,cAAc,UAAkB,UAA4B;AAClE,WAAO,cAAc,OAAO,GAAG,QAAQ;AAAA,EACzC;AAAA,EAEQ,iBAAiB,SAAyB;AAChD,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AACA,WAAY,iBAAW,OAAO,IAAS,eAAS,KAAK,YAAY,OAAO,IAAI;AAAA,EAC9E;AAAA,EAEQ,UAAU,SAAyB;AACzC,UAAMC,YAAW,KAAK,iBAAiB,OAAO;AAC9C,UAAM,UAAe,cAAQA,SAAQ;AACrC,UAAM,SAAS,KAAK,YAAY,YAAY,MAAM,KAAK,OAAO;AAC9D,QAAI,KAAK,aAAa,CAAI,gBAAW,MAAM,GAAG;AAC5C,WAAK,MAAM,SAAS,WAAW,MAAM;AACrC,MAAG,eAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,MAAc,gBAAyB,MAAc;AACtE,QAAI,MAAM;AACV,QAAI,KAAK,WAAW,CAAC,IAAI,SAAS,KAAK,OAAO,GAAG;AAC/C,aAAO,KAAK;AAAA,IACd;AACA,QAAI,eAAe;AACjB,WAAK,UAAU,GAAG;AAAA,IACpB;AACA,WAAO,KAAK,YAAY,GAAG;AAAA,EAC7B;AAAA,EAEA,OAAO,cAA4B;AACjC,UAAM,UAAU,KAAK,YAAY,YAAY;AAC7C,QAAI,CAAI,gBAAW,OAAO,GAAG;AAC3B;AAAA,IACF;AAEA,SAAK,MAAM,UAAU,WAAW,OAAO;AACvC,UAAM,UAAa,iBAAY,SAAS,EAAE,eAAe,KAAK,CAAC;AAC/D,eAAW,SAAS,SAAS;AAC3B,YAAM,UAAe,WAAK,SAAS,MAAM,IAAI;AAC7C,UAAI,MAAM,YAAY,GAAG;AACvB,aAAK,OAAY,WAAK,cAAc,MAAM,IAAI,CAAC;AAAA,MACjD,OAAO;AACL,aAAK,MAAM,UAAU,YAAY,OAAO;AACxC,QAAG,gBAAW,OAAO;AAAA,MACvB;AAAA,IACF;AACA,IAAG,eAAU,OAAO;AAAA,EACtB;AAAA,EAEQ,YAAY,MAAc,KAAyC;AACzE,UAAM,aAAqC,CAAC;AAE5C,QAAI,KAAK,UAAU;AACjB,iBAAW,KAAK,EAAE,KAAU,WAAK,MAAM,IAAI,QAAQ,EAAE,CAAC;AACtD,iBAAW,KAAK,EAAE,KAAU,WAAK,OAAO,YAAY,KAAK,SAAS,IAAI,QAAQ,EAAE,CAAC;AAAA,IACnF,OAAO;AACL,iBAAW,KAAK,EAAE,KAAK,KAAK,CAAC;AAC7B,iBAAW,KAAK,EAAE,KAAK,OAAO,KAAK,UAAU,UAAU,CAAC;AAAA,IAC1D;AAEA,eAAW,aAAa,YAAY;AAClC,YAAM,MAAM,KAAK,WAAW,UAAU,KAAK,KAAK;AAChD,UAAO,gBAAW,GAAG,GAAG;AACtB,eAAO,EAAE,MAAM,KAAK,KAAK,UAAU,IAAI;AAAA,MACzC;AAAA,IACF;AAEA,WAAO,EAAE,MAAM,IAAI,KAAK,GAAG;AAAA,EAC7B;AAAA,EAEQ,WAAW,MAAc,KAAyC;AACxE,UAAMC,QAAO,KAAK,YAAY,MAAM,GAAG;AACvC,QAAI,CAACA,MAAK,MAAM;AACd,aAAO,EAAE,MAAM,IAAI,KAAKA,MAAK,IAAI;AAAA,IACnC;AACA,QAAI,KAAK,UAAU;AACjB,aAAO,EAAE,MAAW,cAAQA,MAAK,IAAI,GAAG,KAAU,cAAQA,MAAK,GAAG,EAAE;AAAA,IACtE;AACA,WAAO,EAAE,MAAMA,MAAK,MAAM,KAAKA,MAAK,IAAI;AAAA,EAC1C;AAAA,EAEQ,WAAW,MAAc,KAAkB;AACjD,QAAI,KAAK,UAAU;AACjB,aAAO,KAAK,WAAgB,WAAK,MAAM,IAAI,QAAQ,GAAG,IAAI;AAAA,IAC5D;AACA,WAAO,KAAK,WAAW,MAAM,IAAI;AAAA,EACnC;AAAA,EAEA,MAAM,MAAc,MAAW,KAA0B;AACvD,QAAI;AACF,YAAM,WAAW,KAAK,SAAS,WAAW,KAAK,WAAW,MAAM,GAAG,IAAI,KAAK,YAAY,MAAM,GAAG,EAAE,QAAQ,KAAK,WAAW,MAAM,GAAG;AACpI,WAAK,MAAM,SAAS,WAAW,QAAQ;AACvC,MAAG,mBAAc,UAAU,MAAM,MAAM;AACvC,aAAO;AAAA,IACT,SAAS,GAAG;AACV,WAAK,MAAM,gBAAgB,iBAAiB,CAAC;AAC7C,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,KAAK,MAAc,KAAU,WAA2B,QAAa;AACnE,QAAI;AACF,YAAMA,QAAO,KAAK,YAAY,MAAM,GAAG;AACvC,UAAI,CAACA,MAAK,MAAM;AACd,eAAO,EAAE,OAAO,QAAQ;AAAA,MAC1B;AACA,WAAK,MAAM,QAAQ,UAAUA,MAAK,IAAI;AACtC,YAAM,OAAU,kBAAaA,MAAK,MAAM,EAAE,SAAS,CAAC,KAAK;AACzD,YAAM,WAAW,KAAK,WAAWA,MAAK,IAAI,SAAS,KAAK,OAAO,IAAIA,MAAK,MAAMA,MAAK,MAAM,KAAK;AAC9F,aAAO,CAAC,EAAE,MAAM,MAAM,SAAS,CAAC;AAAA,IAClC,SAAS,GAAG;AACV,WAAK,MAAM,eAAe,gBAAgB,CAAC;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,IAAI,MAAc,KAA0B;AAC1C,QAAI;AACF,YAAM,MAAM,KAAK,WAAW,MAAM,GAAG;AACrC,UAAI,CAAC,IAAI,MAAM;AACb,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,WAAW,KAAK,SAAS;AAChC,cAAM,SAAS,IAAI,OAAO,YAAY,KAAK;AAC3C,aAAK,MAAM,eAAe,iBAAiB,GAAG,IAAI,IAAI,OAAO,MAAM,EAAE;AACrE,QAAG,gBAAW,IAAI,MAAM,MAAM;AAAA,MAChC,WAAW,KAAK,UAAU;AACxB,aAAK,OAAO,IAAI,GAAG;AAAA,MACrB,OAAO;AACL,aAAK,MAAM,UAAU,YAAY,IAAI,IAAI;AACzC,QAAG,gBAAW,IAAI,IAAI;AAAA,MACxB;AACA,aAAO;AAAA,IACT,SAAS,GAAG;AACV,WAAK,MAAM,iBAAiB,kBAAkB,CAAC;AAC/C,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,GAAG,MAAc,KAA0B;AACzC,QAAI;AACF,YAAM,MAAM,KAAK,WAAW,MAAM,GAAG;AACrC,UAAI,CAAC,IAAI,MAAM;AACb,eAAO;AAAA,MACT;AACA,UAAI,KAAK,SAAS;AAChB,cAAM,aAAa,KAAK,UAAU,KAAK,QAAQ,QAAQ,OAAO,KAAK,IAAI;AACvE,cAAM,WAAW,IAAI,KAAK,QAAQ,IAAI,OAAO,UAAW,UAAU,GAAG,GAAG,EAAE;AAC1E,YAAI,aAAa,IAAI,MAAM;AACzB,eAAK,MAAM,WAAW,aAAa,GAAG,IAAI,IAAI,OAAO,QAAQ,EAAE;AAC/D,UAAG,gBAAW,IAAI,MAAM,QAAQ;AAAA,QAClC;AAAA,MACF,OAAO;AACL,aAAK,MAAM,gBAAgB,kBAAkB,IAAI,IAAI;AACrD,QAAG,gBAAW,IAAI,IAAI;AAAA,MACxB;AACA,aAAO;AAAA,IACT,SAAS,GAAG;AACV,WAAK,MAAM,kBAAkB,mBAAmB,CAAC;AACjD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,KAAK,KAAa,KAAe;AAC/B,QAAI;AACF,YAAM,SAAS,KAAK,YAAY,GAAG;AACnC,WAAK,MAAM,QAAQ,UAAU,MAAM;AACnC,UAAI;AACJ,UAAI;AACF,kBAAa,iBAAY,QAAQ,EAAE,eAAe,KAAK,CAAC;AAAA,MAC1D,QAAQ;AACN,eAAO,KAAK,OAAO,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,IAAI,CAAC;AAAA,MACjD;AAEA,YAAM,SAAc,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE;AAC3C,YAAM,eAAe,YAAY,KAAK;AACtC,iBAAW,SAAS,SAAS;AAC3B,YAAI,CAAC,MAAM,OAAO,EAAG;AACrB,cAAM,WAAW,MAAM;AACvB,cAAM,WAAW,SAAS,SAAS,YAAY;AAC/C,cAAM,WAAW,WAAW,SAAS,MAAM,GAAG,CAAC,aAAa,MAAM,IAAI;AACtE,YAAI,KAAK,WAAW,CAAC,SAAS,SAAS,KAAK,OAAO,EAAG;AACtD,cAAM,WAAgB,WAAK,QAAQ,QAAQ;AAC3C,YAAI;AACF,gBAAM,OAAU,kBAAa,UAAU,MAAM;AAC7C,gBAAM,YAAY,EAAE,MAAM,MAAM,SAAS;AACzC,cAAI,UAAU;AACZ,gBAAI,KAAK,KAAM,QAAO,OAAO,KAAK,SAAS;AAAA,UAC7C,OAAO;AACL,mBAAO,KAAK,KAAK,SAAS;AAAA,UAC5B;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AACA,aAAO,KAAK,OAAO,SAAS,OAAO;AAAA,IACrC,SAAS,GAAG;AACV,WAAK,MAAM,eAAe,gBAAgB,CAAC;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGQ,qBAAqB,OAA6B;AACxD,QAAI,CAAC,SAAS,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAC5C,UAAM,QAAQ,MAAM,KAAK,CAAC,SAAS,MAAM,QAAQ,IAAI,CAAC;AACtD,UAAM,MAAM,QAAQ,CAAC;AACrB,QAAI,OAAO,QAAQ,UAAU;AAC3B,aAAO,IAAI,QAAQ,YAAY,EAAE;AAAA,IACnC;AACA,WAAO,OAAO,OAAO,EAAE;AAAA,EACzB;AAAA,EAEA,MAAM,KAAwB;AAC5B,WAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAI;AACF,YAAI;AACJ,cAAM,WAAW,KAAK,cAAc,IAAI,KAAK;AAE7C,YAAI,IAAI,SAAS,UAAU;AACzB,gBAAM,CAAC,MAAM,IAAI,IAAK,IAAI,MAAqB,CAAC;AAChD,mBAAS,KAAK,MAAM,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,MAAM,GAAG;AAAA,QACpE,WAAW,IAAI,SAAS,UAAU;AAChC,gBAAM,OAAO,KAAK,qBAAqB,IAAI,KAAK;AAChD,mBAAS,KAAK,IAAI,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,GAAG;AAAA,QAC5D,WAAW,IAAI,SAAS,MAAM;AAC5B,gBAAM,OAAO,KAAK,qBAAqB,IAAI,KAAK;AAChD,mBAAS,KAAK,GAAG,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,GAAG;AAAA,QAC3D,WAAW,IAAI,SAAS,UAAU;AAChC,gBAAM,OAAO,KAAK,qBAAqB,IAAI,KAAK;AAChD,gBAAM,OAAQ,IAAI,IAAmB,CAAC,EAAE,CAAC;AACzC,mBAAS,KAAK,MAAM,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,MAAM,GAAG;AAAA,QACpE,WAAW,IAAI,SAAS,UAAU;AAChC,cAAI,KAAK,OAAO,UAAU,KAAK,OAAO,GAAG;AACvC,kBAAM,OAAO,KAAK,qBAAqB,IAAI,KAAK;AAChD,kBAAM,UAAU,KAAK,KAAK,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,GAAG;AAClE,kBAAM,SAAc,CAAC;AACrB,gBAAI,UAAU,CAAC,GAAG,QAAQ,CAAC,QAAQ,OAAO;AACxC,kBAAI,IAAI,OAAO,GAAG;AAChB,oBAAI;AACF,wBAAM,SAAS,KAAK,MAAM,QAAQ,CAAC,EAAE,IAAI;AACzC,sBAAI,IAAI,OAAO,QAAQ;AACrB,oBAAC,IAAI,MAAmB,QAAQ,CAAC,MAAM;AACrC,6BAAO,CAAC,IAAI,OAAO,CAAC,KAAK;AAAA,oBAC3B,CAAC;AAAA,kBACH,OAAO;AACL,2BAAO,OAAO,QAAQ,MAAM;AAAA,kBAC9B;AAAA,gBACF,QAAQ;AAAA,gBAER;AAAA,cACF,OAAO;AACL,sBAAM,SAAS,IAAI;AACnB,uBAAO,OAAO,CAAC,CAAC,IAAI,QAAQ,CAAC,EAAE;AAC/B,oBAAI,OAAO,CAAC,GAAG;AACb,yBAAO,OAAO,CAAC,CAAC,IAAI,QAAQ,CAAC,EAAE;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AACA,qBAAS,CAAC,MAAM;AAAA,UAClB,OAAO;AACL,kBAAM,UAAU,KAAK,KAAK,UAAU,GAAG;AACvC,gBAAI,WAAW,CAAC,QAAQ,OAAO;AAC7B,kBAAI,KAAK,MAAM;AACb,sBAAM,WAAW,wBAAC,OAAY;AAC5B,wBAAM,SAAS,IAAI;AACnB,wBAAM,OAAY,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG,KAAK;AACzC,sBAAI,OAAO,CAAC,EAAG,MAAK,OAAO,CAAC,CAAC,IAAI,GAAG;AACpC,yBAAO;AAAA,gBACT,GALiB;AAMjB,oBAAI,QAAQ,KAAM,SAAQ,OAAO,QAAQ,KAAK,IAAI,QAAQ;AAC1D,oBAAI,QAAQ,OAAQ,SAAQ,SAAS,QAAQ,OAAO,IAAI,QAAQ;AAChE,yBAAS;AAAA,cACX,OAAO;AACL,oBAAI,KAAK,OAAO,GAAG;AACjB,sBAAI,QAAQ;AACZ,sBAAI,IAAI,OAAO,QAAQ;AACrB,0BAAM,QAAQ,IAAI;AAClB,0BAAM,YAAY,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAC5D,4BAAQ,MAAM,OAAO,CAAC,OAAY;AAChC,0BAAI,QAAQ,cAAc;AAC1B,+BAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,4BAAI,OAAO,MAAM,CAAC,MAAM,SAAU;AAClC,8BAAM,OAAO,MAAM,CAAC;AACpB,4BAAI,CAAC,KAAM;AACX,8BAAM,QAAQ,KAAK,CAAC;AACpB,8BAAM,YAAY,OAAO,KAAK,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE;AAClD,4BAAI,WAAW;AACf,4BAAI;AACF,qCAAW,KAAK,MAAM,GAAG,IAAI,EAAE,KAAK,KAAK;AAAA,wBAC3C,QAAQ;AAAA,wBAER;AACA,8BAAM,YAAY,OAAO,QAAQ,EAAE,SAAS,SAAS;AACrD,4BAAI,cAAc,OAAO;AACvB,kCAAQ,SAAS;AACjB,8BAAI,CAAC,MAAO;AAAA,wBACd,OAAO;AACL,kCAAQ,SAAS;AACjB,8BAAI,MAAO;AAAA,wBACb;AAAA,sBACF;AACA,6BAAO;AAAA,oBACT,CAAC;AAAA,kBACH;AACA,0BAAQ,MAAM,IAAI,CAAC,OAAY;AAC7B,0BAAM,MAAW,CAAC;AAClB,wBAAI;AACF,4BAAM,SAAS,KAAK,MAAM,GAAG,IAAI;AACjC,0BAAI,IAAI,OAAO,QAAQ;AACrB,wBAAC,IAAI,MAAmB,QAAQ,CAAC,MAAM;AACrC,8BAAI,CAAC,IAAI,OAAO,CAAC,KAAK;AAAA,wBACxB,CAAC;AAAA,sBACH,OAAO;AACL,+BAAO,OAAO,KAAK,MAAM;AAAA,sBAC3B;AAAA,oBACF,QAAQ;AAAA,oBAER;AACA,2BAAO;AAAA,kBACT,CAAC;AACD,sBAAI,IAAI,OAAO,QAAQ;AACrB,0BAAM,aAAa,IAAI,MAAM,CAAC;AAC9B,0BAAM,iBAAiB,OAAO,eAAe,WAAW,aAAa,WAAW,CAAC;AACjF,0BAAM,YAAY,OAAO,eAAe,WAAW,QAAQ,OAAO,WAAW,CAAC,CAAC,EAAE,YAAY;AAC7F,0BAAM,KAAK,CAAC,GAAQ,MAAW;AAC7B,4BAAM,OAAO,OAAO,EAAE,cAAc,KAAK,EAAE;AAC3C,4BAAM,OAAO,OAAO,EAAE,cAAc,KAAK,EAAE;AAC3C,4BAAM,MAAM,KAAK,cAAc,IAAI;AACnC,6BAAO,cAAc,SAAS,CAAC,MAAM;AAAA,oBACvC,CAAC;AAAA,kBACH;AACA,2BAAS;AAAA,gBACX,OAAO;AACL,wBAAM,SAAS,IAAI;AACnB,2BAAS,QAAQ,IAAI,CAAC,QAAa;AAAA,oBACjC,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG;AAAA,oBAChB,GAAI,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG,KAAK,IAAI,CAAC;AAAA,kBAC9C,EAAE;AAAA,gBACJ;AAAA,cACF;AAAA,YACF,OAAO;AACL,uBAAS,KAAK,OAAO,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,IAAI,CAAC;AAAA,YACnD;AAAA,UACF;AAAA,QACF;AAEA,YAAI,WAAW,QAAW;AACxB,UAAAA,SAAQ,MAAM;AAAA,QAChB,OAAO;AACL,iBAAO,EAAE;AAAA,QACX;AAAA,MACF,SAAS,GAAG;AACV,eAAO,CAAC;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,IAAOC,iBAAQ;;;ACpZf,IAAM,UAAyC;AAAA,EAC7C,OAAOC;AAAA,EACP,QAAQA;AAAA,EACR,MAAMA;AACR;AAOA,SAAS,OACP,OAAwB,QACxB,SAAkC,CAAC,GACC;AACpC,QAAM,SAAS,QAAQ,IAAc;AACrC,MAAI,QAAQ;AACV,WAAO,IAAI,OAAO,MAAM;AAAA,EAC1B;AACA,SAAO,CAAC;AACV;AATS;AAWT,IAAO,aAAQ;;;AC5Bf,IAAO,oBAAQ,wBAAC,UAAe;AAC7B,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO,CAAC;AAC/B,QAAM,aAAa;AACnB,QAAM,OAAO,EAAE,GAAG,aAAc,GAAG,MAAM,KAAK;AAC9C,MAAI,CAAC,MAAM,QAAQ;AACjB,UAAM,SAAS,MAAM,KAAK;AAAA,EAC5B;AACA,QAAM,KAAK,WAAW,iBAAiB,KAAK;AAC5C,MAAI,CAAC,MAAM,KAAK,IAAK,OAAM,KAAK,MAAM,CAAC;AACvC,QAAM,KAAK,MAAM,EAAE,GAAG,aAAc,GAAG,MAAM,KAAK,IAAI;AACtD,MAAI,CAAC,MAAM,KAAK,GAAI,OAAM,KAAK,KAAK,CAAC;AACrC,QAAM,KAAK,KAAK,EAAE,GAAG,YAAa,GAAG,MAAM,KAAK,GAAG;AACrD,GAZe;;;ACCR,SAAS,oBAAoB,KAA+C;AAClF,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO,CAAC;AAC7C,0BAAwB,GAAG;AAC3B,2BAAyB,GAAG;AAC5B,MAAI,IAAI,UAAU,OAAO,IAAI,WAAW,UAAU;AACjD,+BAA2B,IAAI,MAAM;AAAA,EACtC;AACA,4BAA0B,GAAG;AAC7B,uBAAqB,GAAG;AACxB,SAAO;AACR;AAVgB;AAYhB,SAAS,qBAAqB,KAAgC;AAC7D,MAAI,CAAC,IAAI,SAAS,OAAO,IAAI,UAAU,SAAU;AACjD,MAAI,IAAI,MAAM,WAAW,OAAO,IAAI,MAAM,YAAY,UAAU;AAC/D,8BAA0B,IAAI,MAAM,OAAO;AAAA,EAC5C;AACA,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,IAAI,KAAK,GAAG;AACrD,QAAI,SAAS,aAAa,CAAC,QAAQ,OAAO,SAAS,SAAU;AAC7D,8BAA0B,IAA+B;AAAA,EAC1D;AACD;AATS;AAYF,SAAS,wBAAwB,KAAgC;AACvE,MAAI,CAAC,IAAI,YAAY,OAAO,IAAI,aAAa,UAAU;AACtD,QAAI,WAAW,EAAE,aAAa,GAAG,KAAK,GAAG,UAAU,EAAE;AACrD;AAAA,EACD;AACA,QAAM,MAAM,IAAI;AAChB,MAAI,IAAI,eAAe,KAAM,KAAI,cAAc;AAC/C,MAAI,IAAI,OAAO,KAAM,KAAI,MAAM;AAC/B,MAAI,IAAI,YAAY,KAAM,KAAI,WAAW;AACzC,MAAI,CAAC,MAAM,QAAQ,IAAI,aAAa,GAAG;AACtC,QAAI,gBAAgB;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACA,MAAI,CAAC,IAAI,SAAS,OAAO,IAAI,UAAU,UAAU;AAChD,QAAI,QAAQ,EAAE,SAAS,EAAE;AAAA,EAC1B;AACA,MAAI,IAAI,iBAAiB,KAAM,KAAI,gBAAgB;AACnD,MAAI,IAAI,mBAAmB,KAAM,KAAI,kBAAkB;AACvD,MAAI,IAAI,kBAAkB,KAAM,KAAI,iBAAiB;AACrD,MAAI,IAAI,mBAAmB,KAAM,KAAI,kBAAkB;AACvD,MAAI,IAAI,qBAAqB,KAAM,KAAI,oBAAoB;AAC3D,MAAI,CAAC,IAAI,kBAAkB,OAAO,IAAI,mBAAmB,UAAU;AAClE,QAAI,iBAAiB;AAAA,MACpB,WAAW,IAAI;AAAA,MACf,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,cAAc;AAAA,IACf;AAAA,EACD;AACA,MAAI,CAAC,IAAI,UAAU,OAAO,IAAI,WAAW,UAAU;AAClD,QAAI,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG;AAAA,EACrC;AACA,MAAI,IAAI,sBAAsB,KAAM,KAAI,qBAAqB;AAC7D,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,QAAQ;AACnD,QAAI,QAAQ;AAAA,MACX,EAAE,MAAM,UAAU,OAAO,GAAG,aAAa,CAAC,MAAM,EAAE;AAAA,MAClD,EAAE,MAAM,YAAY,OAAO,GAAG,aAAa,CAAC,QAAQ,SAAS,EAAE;AAAA,MAC/D,EAAE,MAAM,YAAY,OAAO,GAAG,aAAa,CAAC,QAAQ,WAAW,OAAO,EAAE;AAAA,MACxE,EAAE,MAAM,SAAS,OAAO,GAAG,aAAa,CAAC,QAAQ,WAAW,SAAS,OAAO,EAAE;AAAA,MAC9E,EAAE,MAAM,aAAa,OAAO,GAAG,aAAa,CAAC,QAAQ,WAAW,SAAS,SAAS,SAAS,EAAE;AAAA,MAC7F,EAAE,MAAM,cAAc,OAAO,IAAI,aAAa,CAAC,QAAQ,WAAW,SAAS,SAAS,WAAW,OAAO,EAAE;AAAA,IACzG;AAAA,EACD;AACA,MAAI,IAAI,YAAY,KAAM,KAAI,WAAW;AACzC,MAAI,CAAC,MAAM,QAAQ,IAAI,UAAU,KAAK,CAAC,IAAI,WAAW,QAAQ;AAC7D,QAAI,aAAa;AAAA,MAChB,EAAE,IAAI,GAAG,KAAK,SAAS,MAAM,4BAAQ,QAAQ,QAAQ;AAAA,MACrD,EAAE,IAAI,GAAG,KAAK,YAAY,MAAM,sBAAO,QAAQ,WAAW;AAAA,MAC1D,EAAE,IAAI,GAAG,KAAK,YAAY,MAAM,sBAAO,QAAQ,WAAW;AAAA,MAC1D,EAAE,IAAI,GAAG,KAAK,SAAS,MAAM,sBAAO,QAAQ,gBAAgB;AAAA,MAC5D,EAAE,IAAI,GAAG,KAAK,aAAa,MAAM,sBAAO,QAAQ,YAAY;AAAA,MAC5D,EAAE,IAAI,IAAI,KAAK,cAAc,MAAM,kCAAS,QAAQ,sBAAsB;AAAA,IAC3E;AAAA,EACD;AACA,MAAI,CAAC,IAAI,wBAAwB,OAAO,IAAI,yBAAyB,UAAU;AAC9E,QAAI,uBAAuB,EAAE,SAAS,GAAG,WAAW,GAAG,YAAY,EAAE;AAAA,EACtE;AACD;AArEgB;AAwET,SAAS,yBAAyB,KAAgC;AACxE,MAAI,CAAC,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AACxD,QAAI,YAAY;AAAA,MACf,MAAM;AAAA,MACN,KAAK,EAAE,KAAK,wBAAwB,KAAK,SAAS,QAAQ,EAAE;AAAA,IAC7D;AACA;AAAA,EACD;AACA,QAAM,QAAQ,IAAI;AAClB,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO;AAC9B,MAAI,CAAC,MAAM,OAAO,OAAO,MAAM,QAAQ,SAAU,OAAM,MAAM,CAAC;AAC9D,MAAI,MAAM,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAM,IAAI,IAAK,OAAM,IAAI,MAAM;AACpC,QAAI,CAAC,MAAM,IAAI,IAAK,OAAM,IAAI,MAAM;AACpC,QAAI,MAAM,IAAI,UAAU,KAAM,OAAM,IAAI,SAAS;AAAA,EAClD,WAAW,MAAM,SAAS,UAAU;AACnC,QAAI,CAAC,MAAM,IAAI,SAAU,OAAM,IAAI,WAAW;AAC9C,QAAI,MAAM,IAAI,UAAU,KAAM,OAAM,IAAI,SAAS;AAAA,EAClD;AACD;AAnBgB;AAsBT,SAAS,2BAA2B,QAAmC;AAC7E,MAAI,CAAC,OAAO,SAAS,OAAO,OAAO,UAAU,UAAU;AACtD,WAAO,QAAQ,EAAE,MAAM,QAAQ,KAAK,4BAA4B,KAAK,SAAS,QAAQ,EAAE;AACxF;AAAA,EACD;AACA,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO;AAC9B,MAAI,MAAM,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAM,IAAK,OAAM,MAAM;AAC5B,QAAI,CAAC,MAAM,IAAK,OAAM,MAAM;AAAA,EAC7B,WAAW,MAAM,SAAS,UAAU;AACnC,QAAI,CAAC,MAAM,SAAU,OAAM,WAAW;AAAA,EACvC,WAAW,MAAM,SAAS,SAAS;AAClC,QAAI,CAAC,MAAM,KAAM,OAAM,OAAO;AAC9B,QAAI,CAAC,MAAM,KAAM,OAAM,OAAO;AAC9B,QAAI,MAAM,YAAY,KAAM,OAAM,WAAW;AAC7C,QAAI,CAAC,MAAM,SAAU,OAAM,WAAW;AAAA,EACvC;AACA,MAAI,MAAM,UAAU,KAAM,OAAM,SAAS;AACzC,MAAI,CAAC,OAAO,aAAc,QAAO,eAAe,CAAC;AACjD,MAAI,CAAC,OAAO,aAAa,aAAa;AACrC,WAAO,aAAa,cAAc;AAAA,EACnC;AACA,MAAI,CAAC,OAAO,QAAQ,OAAO,OAAO,SAAS,UAAU;AACpD,WAAO,OAAO,EAAE,SAAS,EAAE;AAAA,EAC5B;AACA,MAAI,OAAO,KAAK,WAAW,KAAM,QAAO,KAAK,UAAU;AACvD,MAAI,OAAO,eAAe,KAAM,QAAO,cAAc;AACrD,MAAI,OAAO,2BAA2B,KAAM,QAAO,0BAA0B;AAC9E;AA7BgB;AAkCT,SAAS,0BAA0B,KAAgC;AACzE,MAAI,CAAC,IAAI,cAAc,OAAO,IAAI,eAAe,UAAU;AAC1D,QAAI,aAAa,CAAC;AAAA,EACnB;AACA,QAAM,SAAS,IAAI;AAEnB,MAAI,CAAC,OAAO,QAAQ,IAAI,WAAW;AAClC,WAAO,OAAO,EAAE,MAAM,IAAI,UAAU,QAAQ,QAAQ,KAAK,EAAE,GAAI,IAAI,UAAU,OAAO,CAAC,EAAG,EAAE;AAAA,EAC3F;AACA,MAAI,CAAC,OAAO,OAAO,IAAI,QAAQ,OAAO;AACrC,UAAM,IAAI,IAAI,OAAO;AACrB,WAAO,MAAM;AAAA,MACZ,MAAM,EAAE,QAAQ;AAAA,MAChB,KAAK;AAAA,QACJ,UAAU,EAAE;AAAA,QACZ,KAAK,EAAE;AAAA,QACP,KAAK,EAAE;AAAA,QACP,MAAM,EAAE;AAAA,QACR,MAAM,EAAE;AAAA,QACR,UAAU,EAAE;AAAA,QACZ,QAAQ,EAAE;AAAA,MACX;AAAA,IACD;AAAA,EACD;AACA,MAAI,OAAO,OAAO,OAAO,OAAO,QAAQ,UAAU;AACjD,UAAM,WAAW,OAAO;AACxB,UAAM,UAAW,SAAS,QAAQ;AAClC,QAAI,CAAC,SAAS,OAAO,OAAO,SAAS,QAAQ,SAAU,UAAS,MAAM,CAAC;AACvE,QAAI,YAAY,QAAQ;AACvB,UAAI,CAAC,SAAS,IAAI,IAAK,UAAS,IAAI,MAAM;AAC1C,UAAI,CAAC,SAAS,IAAI,IAAK,UAAS,IAAI,MAAM;AAAA,IAC3C,WAAW,YAAY,UAAU;AAChC,UAAI,CAAC,SAAS,IAAI,SAAU,UAAS,IAAI,WAAW;AAAA,IACrD;AACA,QAAI,SAAS,IAAI,UAAU,KAAM,UAAS,IAAI,SAAS;AAAA,EACxD;AACA,MAAI,CAAC,OAAO,SAAS;AACpB,WAAO,UAAU;AAAA,MAChB,MAAM;AAAA,MACN,KAAK,EAAE,UAAU,wCAAwC,QAAQ,EAAE;AAAA,IACpE;AAAA,EACD;AAGA,MAAI,OAAO,MAAM;AAChB,QAAI,YAAY,EAAE,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,OAAO,KAAK,OAAO,CAAC,EAAE;AAC/E,6BAAyB,GAAG;AAAA,EAC7B;AACA,MAAI,OAAO,OAAO,IAAI,QAAQ;AAC7B,UAAM,KAAK,OAAO,IAAI,OAAO,CAAC;AAC9B,QAAI,OAAO,QAAQ;AAAA,MAClB,MAAM,OAAO,IAAI,QAAQ;AAAA,MACzB,UAAU,GAAG;AAAA,MACb,KAAK,GAAG;AAAA,MACR,KAAK,GAAG;AAAA,MACR,MAAM,GAAG;AAAA,MACT,MAAM,GAAG;AAAA,MACT,UAAU,GAAG;AAAA,MACb,QAAQ,GAAG;AAAA,IACZ;AACA,+BAA2B,IAAI,MAAM;AAAA,EACtC;AACD;AA9DgB;AAgET,SAAS,mBAAmB,KAAoC;AACtE,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACpC,WAAO,CAAC,uDAAoB;AAAA,EAC7B;AAGA,MAAI,IAAI,YAAY,MAAM;AACzB,WAAO,KAAK,+HAAkF;AAAA,EAC/F;AACA,MAAI,IAAI,UAAU,MAAM;AACvB,WAAO,KAAK,mFAA2C;AAAA,EACxD;AACA,MAAI,IAAI,KAAK,aAAa,MAAM;AAC/B,WAAO,KAAK,iGAAyD;AAAA,EACtE;AACA,MAAI,IAAI,WAAW,OAAO,QAAQ,IAAI,WAAW,QAAQ,MAAM;AAC9D,WAAO,KAAK,yIAAmE;AAAA,EAChF;AACA,MAAI,IAAI,UAAU,iBAAiB,MAAM;AACxC,WAAO,KAAK,2GAAmE;AAAA,EAChF;AACA,MAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,OAAO,IAAI,MAAM,CAAC,MAAM,YAAY,IAAI,MAAM,CAAC,EAAE,SAAS,GAAG;AAC5F,WAAO,KAAK,0FAAkD;AAAA,EAC/D;AAEA,0BAAwB,GAAG;AAC3B,2BAAyB,GAAG;AAE5B,MAAI,IAAI,UAAU,OAAO,IAAI,WAAW,UAAU;AACjD,+BAA2B,IAAI,MAAM;AAAA,EACtC;AACA,4BAA0B,GAAG;AAE7B,MAAI,IAAI,cAAc,OAAO,IAAI,eAAe,UAAU;AACzD,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,UAAU,GAAG;AAC3D,YAAM,IAAI;AACV,UAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,UAAU,OAAO,EAAE,SAAS,EAAE,IAAI,GAAG;AAC7D,eAAO,KAAK,cAAc,IAAI,4CAA6B;AAAA,MAC5D;AAAA,IACD;AAAA,EACD;AAEA,MAAI,IAAI,YAAY,OAAO,IAAI,aAAa,UAAU;AACrD,UAAM,MAAM,IAAI;AAChB,QAAI,IAAI,eAAe,QAAQ,IAAI,gBAAgB,KAAK,IAAI,gBAAgB,GAAG;AAC9E,aAAO,KAAK,oDAAgC;AAAA,IAC7C;AACA,QAAI,IAAI,OAAO,QAAQ,IAAI,QAAQ,KAAK,IAAI,QAAQ,GAAG;AACtD,aAAO,KAAK,4CAAwB;AAAA,IACrC;AACA,QAAI,IAAI,gBAAgB,SAAS,OAAO,IAAI,iBAAiB,YAAY,IAAI,eAAe,IAAI;AAC/F,aAAO,KAAK,kEAA+B;AAAA,IAC5C;AAAA,EACD;AAEA,MAAI,CAAC,IAAI,SAAS,OAAO,IAAI,UAAU,UAAU;AAChD,WAAO,KAAK,sCAAa;AAAA,EAC1B,OAAO;AACN,QAAI,CAAC,IAAI,MAAM,SAAS;AACvB,aAAO,KAAK,4BAAkB;AAAA,IAC/B,OAAO;AACN,gCAA0B,IAAI,MAAM,OAAkC;AAAA,IACvE;AACA,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,IAAI,KAAK,GAAG;AACrD,YAAM,IAAI;AACV,UAAI,SAAS,WAAW;AACvB,+BAAuB,MAAM,GAAG,MAAM;AACtC;AAAA,MACD;AACA,UAAI,EAAE,QAAQ,SAAS,OAAO,EAAE,SAAS,YAAY,EAAE,QAAQ,KAAK,EAAE,OAAO,QAAQ;AACpF,eAAO,KAAK,SAAS,IAAI,uBAAa,EAAE,IAAI,EAAE;AAAA,MAC/C;AACA,UAAI,EAAE,YAAY,QAAQ,CAAC,MAAM,QAAQ,EAAE,QAAQ,GAAG;AACrD,eAAO,KAAK,SAAS,IAAI,0CAAiB;AAAA,MAC3C;AACA,6BAAuB,MAAM,GAAG,MAAM;AAAA,IACvC;AAAA,EACD;AAEA,MAAI,IAAI,QAAQ,UAAU,OAAO,IAAI,OAAO,WAAW,UAAU;AAChE,WAAO,KAAK,qFAA6C;AAAA,EAC1D;AACA,MAAI,IAAI,QAAQ,QAAQ,QAAQ,CAAC,MAAM,QAAQ,IAAI,OAAO,IAAI,GAAG;AAChE,WAAO,KAAK,sGAA+C;AAAA,EAC5D;AAEA,MAAI,IAAI,cAAc,OAAO,IAAI,eAAe,UAAU;AACzD,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,UAAU,GAAG;AAC3D,YAAM,IAAI;AACV,UAAI,EAAE,OAAO,EAAE,aAAa,QAAQ,OAAO,EAAE,cAAc,UAAU;AACpE,eAAO,KAAK,cAAc,IAAI,yBAAe;AAAA,MAC9C;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAjGgB;AAmGhB,SAAS,uBAAuB,MAAc,GAAwB,QAAwB;AAC7F,QAAM,QAAQ,CAAC,SAAS,MAAM,UAAU,QAAQ,QAAQ;AACxD,aAAW,OAAO,OAAO;AACxB,QAAI,EAAE,GAAG,KAAK,QAAQ,EAAE,GAAG,MAAM,KAAK,EAAE,GAAG,MAAM,GAAG;AACnD,aAAO,KAAK,SAAS,IAAI,IAAI,GAAG,gCAAY;AAAA,IAC7C;AAAA,EACD;AACA,aAAW,OAAO,CAAC,WAAW,SAAS,WAAW,GAAY;AAC7D,QAAI,EAAE,GAAG,KAAK,SAAS,OAAO,EAAE,GAAG,MAAM,YAAY,EAAE,GAAG,KAAK,IAAI;AAClE,aAAO,KAAK,SAAS,IAAI,IAAI,GAAG,uCAAS;AAAA,IAC1C;AAAA,EACD;AACA,MAAI,EAAE,QAAQ,QAAQ,CAAC,MAAM,QAAQ,EAAE,IAAI,GAAG;AAC7C,WAAO,KAAK,SAAS,IAAI,wDAAgB;AAAA,EAC1C;AACD;AAfS;AAkBF,SAAS,2BAA2B,KAAoC;AAC9E,QAAM,SAAmB,CAAC;AAC1B,MAAI,QAAQ,IAAI,aAAa,aAAc,QAAO;AAElD,QAAM,MAAM,KAAK;AACjB,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACpC,WAAO,KAAK,wEAAsB;AAClC,WAAO;AAAA,EACR;AACA,MAAI,IAAI,gBAAgB,GAAG;AAC1B,WAAO,KAAK,+GAA8C;AAAA,EAC3D;AACA,MAAI,IAAI,kBAAkB,GAAG;AAC5B,WAAO,KAAK,uHAAiD;AAAA,EAC9D;AACA,MAAI,CAAC,IAAI,OAAO,SAAS;AACxB,WAAO,KAAK,2GAA+C;AAAA,EAC5D;AACA,MAAI,IAAI,QAAQ,GAAG;AAClB,WAAO,KAAK,6GAAuC;AAAA,EACpD;AACA,MAAI,OAAO,IAAI,iBAAiB,YAAY,IAAI,eAAe,GAAG;AACjE,WAAO,KAAK,+EAAkC;AAAA,EAC/C;AACA,MAAI,IAAI,aAAa,KAAK,CAAC,KAAK,WAAW,WAAW,CAAC,KAAK,WAAW,KAAK;AAC3E,WAAO,KAAK,0FAAwC;AAAA,EACrD;AAEA,SAAO;AACR;AA7BgB;;;AC1ThB,IAAM,kBAAiD;AAAA,EACtD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AACR;AAEA,IAAM,oBAA6D;AAAA,EAClE,KAAK,EAAE,SAAS,MAAM,YAAY,IAAI,cAAc,KAAM,UAAU,KAAO,QAAQ,EAAE;AAAA,EACrF,MAAM,EAAE,SAAS,MAAM,YAAY,IAAI,cAAc,KAAM,UAAU,KAAO,QAAQ,EAAE;AAAA,EACtF,OAAO,EAAE,SAAS,MAAM,YAAY,IAAI,cAAc,KAAM,UAAU,KAAO,QAAQ,EAAE;AACxF;AAuBO,SAAS,kBAAkB,KAAU,MAAiD;AAC5F,QAAM,QAAQ,MAAM,IAAI;AACxB,SAAO,SAAS,OAAO,UAAU,WAAW,QAAQ;AACrD;AAHgB;AAKT,SAAS,oBAAoB,KAAU,MAAiD;AAC9F,QAAM,MAAM,kBAAkB,KAAK,IAAI,GAAG;AAC1C,SAAO,OAAO,OAAO,QAAQ,WAAW,MAAM;AAC/C;AAHgB;AAKT,SAAS,oBAAoB,KAAU,MAA8B;AAC3E,SAAO,CAAC,CAAC,oBAAoB,KAAK,IAAI;AACvC;AAFgB;AAKT,SAAS,iBAAiB,KAAU,MAA6B;AACvE,QAAM,MAAM,oBAAoB,KAAK,IAAI;AACzC,QAAM,KAAK,KAAK;AAChB,SAAO,OAAO,OAAO,YAAY,GAAG,SAAS,IAAI,KAAK,gBAAgB,IAAI;AAC3E;AAJgB;AAOT,SAAS,kBAAkB,KAAsD;AACvF,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,IAAI,gBAAgB;AAC5B;AAHgB;AAMT,SAAS,wBACf,KACA,MACA,KACmB;AACnB,QAAM,OAAO,kBAAkB,IAAI;AACnC,QAAM,KAAK,KAAK;AAChB,QAAM,WAAW,KAAK,IAAI;AAE1B,SAAO;AAAA,IACN,SAAS,IAAI,YAAY,SAAS,KAAK,YAAY;AAAA,IACnD,YAAY,IAAI,cAAc,YAAY,KAAK,cAAc;AAAA,IAC7D,cAAc,IAAI,gBAAgB,KAAK,gBAAgB;AAAA,IACvD,UAAU,IAAI,YAAY,KAAK,YAAY;AAAA,IAC3C,QAAQ,IAAI,UAAU,KAAK,UAAU;AAAA,EACtC;AACD;AAhBgB;;;AC3EhB,IAAM,kBAAiD;AAAA,EACtD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AACR;AAgBO,SAAS,oBAAoB,MAAmC;AACtE,QAAM,EAAE,OAAO,QAAQ,IAAI;AAC3B,QAAM,KAAK,UAAU,IAAI;AACzB,MAAI,CAAC,MAAM,KAAK,UAAU,GAAG;AAC5B,UAAM,KAAK,UAAU,IAAI,CAAC;AAAA,EAC3B;AAEA,QAAM,aAAa,oBAAoB,MAAM,YAAY,KAAK,SAAS;AACvE,QAAM,SAAS,iBAAiB,MAAM,YAAY,KAAK,SAAS;AAEhE,MAAI,YAAY;AACf,UAAM,QAAQ,KAAK,mBAAmB,UAAU;AAChD,UAAM,gBAAgB,KAAK,SAAS,CAAC,IAAI,EAAE,QAAQ,QAAQ,MAAM;AACjE,QAAI,kBAAkB,UAAU,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,MAAM,GAAG;AACrE,YAAM,KAAK,UAAU,EAAE,MAAM,IAAI,QAAQ,QAAQ,KAAK;AAAA,IACvD;AAAA,EACD;AAEA,cAAY,OAAO,KAAK,UAAU,KAAK,UAAU;AACjD,aAAW,OAAO,KAAK,SAAS,KAAK,SAAS;AAC9C,SAAO;AACR;AArBgB;AAwBT,SAAS,wBAAwB,OAAY,WAAyC;AAC5F,QAAM,UAAU,MAAM,gBAAgB,SAAS,CAAC;AAChD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,aACL,cAAc,QAAQ,gBAAgB,cAAc,SAAS,iBAAiB;AAC/E,QAAM,aACL,cAAc,QACX,sBACA,cAAc,SACb,uBACA;AAEL,QAAM,UAAU,MAAM,UAAU;AAChC,MAAI,CAAC,WAAW,CAAC,QAAQ,OAAQ,QAAO;AAExC,MAAI,CAAC,MAAM,UAAU,EAAG,OAAM,UAAU,IAAI,CAAC;AAC7C,MAAI,CAAC,MAAM,UAAU,EAAE,QAAQ,MAAM,GAAG;AACvC,UAAM,UAAU,EAAE,QAAQ,MAAM,IAAI,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EACnE;AACA,SAAO,QAAQ;AAChB;AArBgB;AAwBT,SAAS,2BAA2B,OAAY,SAAc;AACpE,SAAO,CAAC,UAAe;AACtB,QAAI,OAAO,MAAM,SAAS,UAAU;AACnC,UAAI;AACH,cAAM,OAAO,KAAK,MAAM,MAAM,IAAI;AAAA,MACnC,QAAQ;AAAA,MAER;AAAA,IACD;AACA,QAAI,MAAM,MAAM,IAAI;AACnB,cAAQ,MAAM,MAAM,IAAI,MAAM,IAAI;AAClC;AAAA,IACD;AACA,QAAI;AACH,YAAM,QAAQ,OAAO,SAAS,eAAe,QAAQ;AACrD,YAAM,YAAY,KAAK,GAAG,UAAU,MAAM,IAAI;AAAA,IAC/C,QAAQ;AAAA,IAER;AAAA,EACD;AACD;AApBgB;AAuBT,SAAS,4BACf,SACA,QACA,WACO;AACP,UAAQ,GAAG,OAAO,WAAW,CAAC,UAAe;AAC5C,YAAQ,IAAI,GAAG,SAAS,6BAAS,MAAM,IAAI,MAAM,SAAS,EAAE;AAAA,EAC7D,CAAC;AACD,UAAQ,GAAG,OAAO,cAAc,CAAC,UAAe;AAC/C,YAAQ,IAAI,GAAG,SAAS,6BAAS,MAAM,IAAI,MAAM,SAAS,EAAE;AAAA,EAC7D,CAAC;AAED,MAAI,OAAO,OAAO;AACjB,YAAQ,GAAG,OAAO,OAAO,MAAM;AAAA,IAAC,CAAC;AAAA,EAClC;AACD;AAfgB;;;ACyET,IAAM,cAAc;;;ACrH3B,SAAS,YAAe,KAAW;AAClC,MAAI,OAAO,OAAO,QAAQ,YAAY,aAAc,KAAgB;AACnE,UAAM,IAAK,IAAmC;AAC9C,QAAI,MAAM,OAAW,QAAO;AAAA,EAC7B;AACA,SAAO;AACR;AANS;AAQT,IAAM,WAAW,YAAY,WAAW;AAExC,IAAMC,gBAAqC;AAAA,EAC1C,MAAM;AAAA,EACN,IAAI,wBAAC,OAAoB,QACxB,SAAS,OAAO,GAAG,GADhB;AAAA,EAEJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAiEO,IAAM,iBACZ,OACG,UACA;AAEJ,IAAO,gBAAQC;","names":["ensureFile","resolve","ensureFile","fs","fs","logSecurityConfigIntervention","getComplianceReport","ws","WebSocket","WebSocket","ws","fs","path","fs","nodePath","fs","path","fs","process","process","ws","createUserStore","path","$asai","postdata","ws","$asai","resolve","ws","ws","fs","path","ensureFile","pathExists","readLogDir","removeFile","resolvePathUnderBase","fs","path","data","fs","nodePath","os","os","parseBody","getQuota","fs","resolve","hostDefault","fs","path","path","fs","fs","nodePath","path","resolve","relative","Index_default","fs","path","resolve","Index_default","fs","path","relative","read","resolve","Index_default","Index_default","initAsaiHost","initAsaiHost"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/network.ts","../src/core/host-config.ts","../src/infra/process.ts","../src/infra/logger.ts","../src/ws/route-index.ts","../src/infra/registry.ts","../src/infra/security-audit.ts","../src/infra/crypto-compliance.ts","../src/infra/ntp-check.ts","../src/infra/config-integrity.ts","../src/core/init.ts","../src/http/server.ts","../src/ws/server.ts","../src/ws/auth.ts","../src/utils/userinfo.ts","../src/ws/message.ts","../src/infra/connection-quota.ts","../src/http/static-path-cache.ts","../src/http/security.ts","../src/http/log.ts","../src/http/static.ts","../src/infra/safe-path.ts","../src/http/server-paths.ts","../src/http/connection.ts","../src/infra/port-release.ts","../src/proxy/server.ts","../src/utils/index.ts","../src/utils/ws-mock.ts","../src/infra/user-auth.ts","../src/infra/access-control.ts","../src/infra/host-limits.ts","../src/common/server/Api.ts","../src/common/server/Ws.ts","../src/common/server/Sys.ts","../src/common/server/WsClient.ts","../src/common/Index.ts","../src/sysserver/ws/common/ping.ts","../src/sysserver/ws/chat/web.ts","../src/sysserver/ws/index.ts","../src/sysserver/api/common/logmanage.ts","../src/infra/siem-auth.ts","../src/sysserver/api/common/interventionlog.ts","../src/sysserver/api/common/unifiedlog.ts","../src/sysserver/lib/common/ErrorCode.ts","../src/sysserver/api/common/errorcodes.ts","../src/sysserver/api/common/sqlitemanage.ts","../src/sysserver/api/common/health.ts","../src/infra/input-sanitize.ts","../src/sysserver/api/login/service/session.ts","../src/sysserver/api/login/service/rbac.ts","../src/sysserver/api/login/service/request-body.ts","../src/sysserver/api/login/service/online-sessions.ts","../src/sysserver/api/login/index.ts","../src/sysserver/api/index.ts","../src/sysserver/lib/common/As.ts","../src/sysserver/lib/common/AsCode.ts","../src/sysserver/lib/common/AsAES.ts","../src/sysserver/lib/common/AsDb.ts","../src/sysserver/lib/common/reqWork.ts","../src/sysserver/lib/common/AsFs.ts","../src/sysserver/lib/common/AsPath.ts","../src/sysserver/lib/index.ts","../src/sysserver/db/src/common.ts","../src/sysserver/db/src/Sql.ts","../src/sysserver/db/src/file/Index.ts","../src/sysserver/db/db.ts","../src/sysserver/index.ts","../src/config/validate.ts","../src/config/syscom.ts","../src/infra/transport-bridge.ts","../src/types.ts","../index.ts"],"sourcesContent":["/**\r\n * index.ts — AsaiHostNodejs 插件入口\r\n *\r\n * 启动流程:注册 sys/api/ws/jsonp 处理器 → 按 hosts 配置拉起 HTTP/WS → 按 proxyhosts 拉起反向代理。\r\n * workHandlers 使用模块级 Map,避免 global 污染且支持多实例。\r\n */\r\nimport * as ws from \"ws\";\r\nimport { initAsaiHostNodejs, validateHostdir } from \"./core\";\r\nimport { startHTTPServer } from \"./http/server\";\r\nimport { startProxyServer } from \"./proxy/server\";\r\nimport { releaseConfiguredPorts } from \"./infra/port-release\";\r\n\r\n/** 业务处理器注册表(sysWork / apiWork / wsWork / jsonpWork) */\r\nconst workHandlers = new Map<string, Function>();\r\nexport function getWorkHandler(name: string): Function | undefined {\r\n return workHandlers.get(name);\r\n}\r\n\r\nexport default function ($asai: any, opt: any) {\r\n // [优化] 将处理器存入模块级 Map,而非挂载到 global\r\n workHandlers.set(\"sysWork\", opt.sysWork);\r\n workHandlers.set(\"apiWork\", opt.apiWork);\r\n workHandlers.set(\"wsWork\", opt.wsWork);\r\n workHandlers.set(\"jsonpWork\", opt.jsonpWork);\r\n\r\n function StartAsaiHostNodejs(): void {\r\n initAsaiHostNodejs($asai, opt);\r\n\r\n console.log(`※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※`);\r\n\r\n releaseConfiguredPorts($asai);\r\n\r\n if ($asai.hostconfig?.hosts) {\r\n $asai.startHTTPServer = (hostdir: string) =>\r\n startHTTPServer($asai, hostdir);\r\n Object.keys($asai.hostconfig.hosts).forEach((el: string) => {\r\n if (validateHostdir(el)) {\r\n startHTTPServer($asai, el);\r\n }\r\n });\r\n // asai 被 validateHostdir 排除,需显式启动(9199 主站);default 仅作模板不单独监听\r\n if ($asai.hostconfig.hosts.asai) {\r\n startHTTPServer($asai, \"asai\");\r\n }\r\n }\r\n\r\n if ($asai.hostconfig?.proxyhosts) {\r\n Object.keys($asai.hostconfig.proxyhosts).forEach((el: string) => {\r\n if (validateHostdir(el)) {\r\n startProxyServer($asai, el);\r\n }\r\n });\r\n }\r\n }\r\n\r\n return { StartAsaiHostNodejs, asaiWs: ws };\r\n}\r\n","/** 网络工具 — 本机 IP 探测与绑定地址解析 */\r\nimport * as os from 'os';\r\n\r\nexport function getIp(): string {\r\n\ttry {\r\n\t\tconst interfaces = os.networkInterfaces();\r\n\t\tfor (const name of Object.keys(interfaces)) {\r\n\t\t\tconst iface = interfaces[name];\r\n\t\t\tif (!iface) continue;\r\n\t\t\tfor (const alias of iface) {\r\n\t\t\t\tif (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {\r\n\t\t\t\t\treturn alias.address;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t} catch (err) {\r\n\t\tconsole.error('Get IP address error:', err);\r\n\t}\r\n\treturn '127.0.0.1';\r\n}\r\n\r\nexport function getHostIP(ip?: string | null, $asai?: any): string {\r\n\tif (ip && typeof ip === 'string') return ip;\r\n\tif ($asai?.hostconfig?.ip === 'asai') return 'localhost';\r\n\treturn $asai?.hostconfig?.ip || '127.0.0.1';\r\n}\r\n","/** 主机/代理配置合并与缓存 — 启动后配置不变,进程级缓存 */\r\nimport { getHostIP } from './network';\r\n\r\nconst hostCfgCache = new Map<string, any>();\r\nconst proxyHostCfgCache = new Map<string, any>();\r\n\r\nexport function validateHostdir(hostdir: string): boolean {\r\n\tif (typeof hostdir !== 'string' || hostdir.length === 0 || hostdir.length > 100 || hostdir === 'default' || hostdir === 'asai') {\r\n\t\treturn false;\r\n\t}\r\n\treturn /^[a-zA-Z0-9_-]+$/.test(hostdir);\r\n}\r\n\r\nfunction loadHostCFG(hostdir: string, $asai: any): any {\r\n\tlet base = hostCfgCache.get(hostdir);\r\n\tif (!base) {\r\n\t\tconst defaultCfg = $asai.hostconfig.hosts.default || {};\r\n\t\tconst hostCfg = $asai.hostconfig.hosts[hostdir] || {};\r\n\t\tbase = { ...defaultCfg, ...hostCfg };\r\n\t\thostCfgCache.set(hostdir, base);\r\n\t}\r\n\treturn base;\r\n}\r\n\r\n/** 返回浅拷贝,避免调用方修改污染缓存 */\r\nexport function getHostCFG(hostdir: string, $asai: any): any {\r\n\treturn { ...loadHostCFG(hostdir, $asai) };\r\n}\r\n\r\nfunction loadProxyHostCFG(proxyhostdir: string, $asai: any): any {\r\n\tlet base = proxyHostCfgCache.get(proxyhostdir);\r\n\tif (!base) {\r\n\t\tconst defaultCfg = $asai.hostconfig.proxyhosts?.default || {};\r\n\t\tconst proxyCfg = $asai.hostconfig.proxyhosts?.[proxyhostdir] || {};\r\n\t\tbase = { ...defaultCfg, ...proxyCfg };\r\n\t\tif (!base.url && base.port) {\r\n\t\t\tbase.url = (base.httptype || 'http://') + getHostIP(base.ip, $asai) + ':' + base.port;\r\n\t\t}\r\n\t\tproxyHostCfgCache.set(proxyhostdir, base);\r\n\t}\r\n\treturn base;\r\n}\r\n\r\nexport function getProxyHostCFG(proxyhostdir: string, $asai: any): any {\r\n\treturn { ...loadProxyHostCFG(proxyhostdir, $asai) };\r\n}\r\n","/**\r\n * process.ts — 进程级异常守护与优雅退出\r\n *\r\n * - uncaughtException:记录日志并按窗口限流,超限则 gracefulShutdown\r\n * - unhandledRejection:记录完整堆栈\r\n * - SIGTERM/SIGINT:关闭 HTTP/WS 后退出\r\n */\r\nexport function initProcess($asai: any, cb?: ((err: Error) => void) | null): void {\r\n const MAX_RESTARTS = $asai?.hostconfig?.tm?.maxtry || 10;\r\n const RESTART_WINDOW = $asai?.hostconfig?.tm?.restartwindow || 60000;\r\n const restartTimes: number[] = [];\r\n\r\n // uncaughtExceptionMonitor: 主 handler 崩溃时兜底记录,永不退出\r\n if (process.on && typeof process.on === 'function' && 'uncaughtExceptionMonitor' in process) {\r\n process.on('uncaughtExceptionMonitor', (err: Error) => {\r\n try {\r\n $asai.$log('FATAL', `Monitor caught: ${err?.message || err}`);\r\n } catch {\r\n /* ignore */\r\n }\r\n });\r\n }\r\n\r\n process.on('unhandledRejection', (reason: unknown, promise: Promise<unknown>) => {\r\n const stackTrace = new Error().stack;\r\n let promiseInfo = '';\r\n if (promise && typeof promise === 'object') {\r\n promiseInfo = promise.constructor?.name || 'Promise';\r\n const stackLines = stackTrace?.split('\\n') || [];\r\n const relevantStack = stackLines.slice(3, 6).join(' | ');\r\n promiseInfo += ` Created at: ${relevantStack}`;\r\n }\r\n\r\n let reasonInfo = '';\r\n if (reason instanceof Error) {\r\n reasonInfo = `\\n${reason.name}: ${reason.message}`;\r\n if (reason.stack) reasonInfo += `\\n【Stack】${reason.stack}`;\r\n } else if (typeof reason === 'object' && reason !== null) {\r\n try {\r\n reasonInfo = JSON.stringify(reason, null, 2).substring(0, 500);\r\n } catch {\r\n reasonInfo = String(reason);\r\n }\r\n } else {\r\n reasonInfo = String(reason);\r\n }\r\n\r\n const errorMsg = `Unhandled Promise Rejection:\\n【Reason】 ${reasonInfo}\\n【Promise】${promiseInfo}`;\r\n $asai.$log('UNHANDLED_REJECTION', errorMsg);\r\n });\r\n\r\n process.on('uncaughtException', (err: Error) => {\r\n const errorMsg = `Uncaught Exception: ${JSON.stringify(err)}`;\r\n try {\r\n $asai.$log('UNCAUGHT_EXCEPTIONS', errorMsg);\r\n } catch {\r\n /* $log itself threw */\r\n }\r\n\r\n const now = Date.now();\r\n restartTimes.push(now);\r\n while (restartTimes.length > 0 && restartTimes[0] < now - RESTART_WINDOW) {\r\n restartTimes.shift();\r\n }\r\n\r\n if (restartTimes.length > MAX_RESTARTS) {\r\n try {\r\n $asai.$log('NO_RESTART', 'Process crashed too frequently, gracefully shutdown and wait for daemon restart.');\r\n void import('../sysserver/lib/common/intervention-hooks').then(({ logProcessGuardEvent }) =>\r\n logProcessGuardEvent($asai, {\r\n action: 'crash_loop_shutdown',\r\n detail: `${restartTimes.length} crashes in ${RESTART_WINDOW}ms window`,\r\n outcome: 'Failure',\r\n severity: 10,\r\n }),\r\n ).catch(() => undefined);\r\n } catch {\r\n /* $log itself threw */\r\n }\r\n try {\r\n $asai.$log('SHUTDOWN', 'Error:', err?.message || err);\r\n } catch {\r\n /* $log itself threw */\r\n }\r\n gracefulShutdown($asai);\r\n return;\r\n }\r\n\r\n if (cb && typeof cb === 'function') {\r\n try {\r\n cb(err);\r\n } catch (callbackErr) {\r\n console.error('Error in process error callback:', callbackErr);\r\n }\r\n }\r\n });\r\n\r\n process.on('SIGTERM', () => {\r\n try {\r\n $asai.$log('SIGTERM', 'SIGTERM,CLOSING...');\r\n } catch {\r\n /* ignore */\r\n }\r\n gracefulShutdown($asai);\r\n });\r\n\r\n process.on('SIGINT', () => {\r\n try {\r\n $asai.$log('SIGINT', 'SIGINT,CLOSING...');\r\n } catch {\r\n /* ignore */\r\n }\r\n gracefulShutdown($asai);\r\n });\r\n}\r\n\r\nexport function gracefulShutdown($asai: any): void {\r\n void import('../sysserver/lib/common/intervention-hooks').then(({ logProcessGuardEvent }) =>\r\n logProcessGuardEvent($asai, {\r\n action: 'graceful_shutdown',\r\n detail: 'SIGTERM/SIGINT or crash guard triggered',\r\n outcome: 'Success',\r\n }),\r\n ).catch(() => undefined);\r\n\r\n const shutdownTimeout = 60000;\r\n let shutdownTimer: NodeJS.Timeout;\r\n\r\n const startTime = Date.now();\r\n shutdownTimer = setTimeout(() => {\r\n $asai.$log('SHUTDOWN', `Timeout! Exiting after ${Date.now() - startTime}ms`);\r\n process.exit(1);\r\n }, shutdownTimeout);\r\n\r\n try {\r\n Object.values($asai.servershttp || {}).forEach((server: any) => {\r\n if (server && typeof server.close === 'function') {\r\n server.close((err?: Error) => {\r\n if (err) $asai.$log('HTTP', 'HTTP server close error:', err);\r\n });\r\n }\r\n });\r\n\r\n Object.values($asai.serversws || {}).forEach((server: any) => {\r\n if (server && typeof server.close === 'function') {\r\n server.close((err?: Error) => {\r\n if (err) $asai.$log('WS', 'WS server close error:', err);\r\n });\r\n }\r\n });\r\n\r\n if ($asai.hostconfig.guardtm) {\r\n clearTimeout($asai.hostconfig.guardtm);\r\n $asai.hostconfig.guardtm = null;\r\n }\r\n\r\n Object.keys($asai.tasksws || {}).forEach((hostdir) => {\r\n if ($asai.tasksws[hostdir].httpMonitor) {\r\n clearInterval($asai.tasksws[hostdir].httpMonitor);\r\n delete $asai.tasksws[hostdir].httpMonitor;\r\n }\r\n });\r\n\r\n setTimeout(() => {\r\n clearTimeout(shutdownTimer);\r\n $asai.$log('SHUTDOWN', `Web Server Closed (${Date.now() - startTime}ms)`);\r\n process.exit(0);\r\n }, 3000);\r\n } catch (err) {\r\n $asai.$log('SHUTDOWN', 'Graceful shutdown error:', err);\r\n clearTimeout(shutdownTimer);\r\n process.exit(1);\r\n }\r\n}\r\n","/**\r\n * 日志系统 — 带缓冲区异步写入,支持按日轮转\r\n *\r\n * 功能:\r\n * 1. LogBuffer:缓冲区批量写入+定时刷新,避免频繁 I/O\r\n * 2. 按文件大小自动轮转(默认 1MB)\r\n * 3. 进程退出时自动刷新所有缓冲区,防止日志丢失\r\n * 4. 支持控制台显示(view)与文件记录(record)独立开关\r\n */\r\n\r\nimport fs from \"node:fs/promises\";\r\nimport { getNowTime } from \"../core/time\";\r\nimport { mirrorWebLog, mirrorAccessLog } from \"../sysserver/lib/common/LogStore\";\r\nimport {\r\n formatW3CHeader,\r\n formatW3CServerRecord,\r\n W3C_SERVER_FIELDS,\r\n W3C_ACCESS_FIELDS,\r\n parseCLF,\r\n} from \"../sysserver/lib/common/log-formats\";\r\n\r\n/** 全局日志缓冲区实例 Map(key = `${$asai.id}_${src}`) */\r\nconst logBuffers = new Map<string, LogBuffer>();\r\n\r\n/** 进程退出时刷新所有 LogBuffer 实例 */\r\nfunction flushAllLogBuffers(): void {\r\n logBuffers.forEach((buffer) => {\r\n buffer.forceFlush();\r\n });\r\n}\r\n\r\n/**\r\n * 异步日志缓冲区 — 攒批写入文件\r\n * - 满 maxBufferSize 条或超时 flushInterval 自动刷出\r\n * - 进程退出时通过 process.on('beforeExit') 统一刷出全部缓冲区\r\n */\r\nclass LogBuffer {\r\n private buffer: string[] = [];\r\n private timer: ReturnType<typeof setTimeout> | null = null;\r\n private readonly flushInterval = 100; // 攒批超时(ms)\r\n private readonly maxBufferSize = 100; // 单次攒批上限(条)\r\n\r\n /** 全局只注册一次 beforeExit,避免重复订阅 */\r\n private static globalFlushRegistered = false;\r\n\r\n constructor(\r\n private $asai: any,\r\n private filePath: string,\r\n ) {\r\n // 全局只注册一次 beforeExit:统一 flush 所有缓冲区\r\n if (!LogBuffer.globalFlushRegistered) {\r\n LogBuffer.globalFlushRegistered = true;\r\n process.once(\"beforeExit\", () => flushAllLogBuffers());\r\n }\r\n }\r\n\r\n /** 入队一条日志 */\r\n public add(logData: string): void {\r\n this.buffer.push(logData);\r\n\r\n if (this.buffer.length >= this.maxBufferSize) {\r\n this.flush(); // 攒满 → 立即刷出\r\n } else if (!this.timer) {\r\n this.timer = setTimeout(() => this.flush(), this.flushInterval);\r\n }\r\n }\r\n\r\n /** 强制刷出(供外部调用,如进程退出时) */\r\n public forceFlush(): void {\r\n this.flush();\r\n }\r\n\r\n /** 刷出缓冲区 → 异步写入文件(ensureFile 在 flush 时执行,避免每请求 stat) */\r\n private flush(): void {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n if (this.buffer.length === 0) return;\r\n\r\n const logContent = this.buffer.join(\"\");\r\n this.buffer = [];\r\n void this.writeBatch(logContent);\r\n }\r\n\r\n private async writeBatch(logContent: string): Promise<void> {\r\n try {\r\n const { ensureFile } = this.$asai.$lib.AsFs;\r\n await ensureFile(this.filePath);\r\n const stat = await fs.stat(this.filePath);\r\n const maxSize = this.$asai.hostconfig.logger?.path?.maxsize || 1_048_576;\r\n if (stat.size >= maxSize) {\r\n const lastIndex = this.filePath.lastIndexOf(\".\");\r\n const filename = this.filePath.substring(0, lastIndex);\r\n const fileext = this.filePath.substring(lastIndex);\r\n await fs.rename(\r\n this.filePath,\r\n `${filename}-${getNowTime(5)}${fileext}`,\r\n );\r\n }\r\n await fs.appendFile(this.filePath, logContent, \"utf8\");\r\n const src = this.filePath.includes(\"/client/\") || this.filePath.includes(\"\\\\client\\\\\") ? \"client\" : \"server\";\r\n const kind = logContent.includes(\"[SEC-AUDIT]\") ? \"sec\" : src;\r\n void mirrorWebLog(this.$asai, {\r\n source: kind === \"sec\" ? \"sec\" : src,\r\n rawLine: logContent,\r\n }).catch(() => undefined);\r\n } catch (err) {\r\n console.error(\"Log write error:\", err);\r\n }\r\n }\r\n\r\n /** 销毁:清定时器+刷出残余数据 */\r\n public destroy(): void {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n this.flush();\r\n }\r\n}\r\n\r\n/**\r\n * 写入一条日志(通过缓冲区异步写入文件)\r\n * saveLog → LogBuffer.add\r\n */\r\nfunction saveLog($asai: any, src: string, logstr: string): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const bufferKey = `${$asai.id || \"default\"}_${src}`;\r\n let logBuffer = logBuffers.get(bufferKey);\r\n if (!logBuffer) {\r\n logBuffer = new LogBuffer($asai, src);\r\n logBuffers.set(bufferKey, logBuffer);\r\n }\r\n logBuffer.add(logstr);\r\n resolve();\r\n } catch (err) {\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/* eslint-disable @typescript-eslint/no-unused-vars */\r\nfunction newLoggerFile($asai: any, _dateCur: any, logstr: string) {\r\n return formatW3CHeader({\r\n software: $asai.hostconfig.website?.title || \"AsaiHostNodejs\",\r\n version: $asai.hostconfig.website?.ver || \"1.0.0.0\",\r\n fields: [...W3C_SERVER_FIELDS],\r\n date: _dateCur,\r\n }) + logstr;\r\n}\r\n/* eslint-enable @typescript-eslint/no-unused-vars */\r\n\r\n/** 新 W3C 日志文件是否已写入头部(按路径缓存) */\r\nconst w3cHeaderWritten = new Set<string>();\r\n\r\nasync function ensureW3CHeader($asai: any, filePath: string, dateCur: Date): Promise<void> {\r\n if (w3cHeaderWritten.has(filePath)) return;\r\n try {\r\n const stat = await fs.stat(filePath);\r\n if (stat.size > 0) {\r\n w3cHeaderWritten.add(filePath);\r\n return;\r\n }\r\n } catch {\r\n /* 文件不存在,继续写头 */\r\n }\r\n const header = formatW3CHeader({\r\n software: $asai.hostconfig.website?.title || \"AsaiHostNodejs\",\r\n version: $asai.hostconfig.website?.ver || \"1.0.0.0\",\r\n fields: [...W3C_SERVER_FIELDS],\r\n date: dateCur,\r\n });\r\n await fs.appendFile(filePath, header, \"utf8\");\r\n w3cHeaderWritten.add(filePath);\r\n}\r\n\r\n/**\r\n * 每个日志文件的轮转元信息缓存。\r\n * 性能关键:避免每条日志都执行 ensureFile + stat(两次磁盘 I/O),\r\n * 改为按字节累加估算大小 + 周期性 stat 校准,I/O 从「每行 2 次」降到「每文件每隔数秒 1 次」。\r\n */\r\ninterface LogFileMeta {\r\n ensured: boolean; // 文件是否已确保存在\r\n size: number; // 当前大小(字节,写入时累加估算)\r\n lastStatMs: number; // 上次 stat 校准时间戳\r\n}\r\nconst logFileMeta = new Map<string, LogFileMeta>();\r\n/** stat 校准最小间隔(ms):两次校准之间用累加字节判断轮转 */\r\nconst STAT_REFRESH_INTERVAL = 5000;\r\n\r\n/**\r\n * 追加日志(外部接口)\r\n * - 自动确保文件存在\r\n * - 超 maxsize(默认 1MB)自动轮转 + 重命名\r\n * - 仅在文件未确保或超过校准间隔时才触碰磁盘元信息,其余时间走内存累加\r\n */\r\nexport async function setAppend(\r\n $asai: any,\r\n src: string,\r\n logstr: string,\r\n): Promise<void> {\r\n try {\r\n const maxSize = $asai.hostconfig.logger?.path?.maxsize || 1_048_576;\r\n let meta = logFileMeta.get(src);\r\n const now = Date.now();\r\n\r\n // 首次写入或到达校准窗口:确保文件存在并以真实大小校准缓存\r\n if (\r\n !meta ||\r\n !meta.ensured ||\r\n now - meta.lastStatMs >= STAT_REFRESH_INTERVAL\r\n ) {\r\n const { ensureFile } = $asai.$lib.AsFs;\r\n await ensureFile(src);\r\n const stat = await fs.stat(src);\r\n meta = { ensured: true, size: stat.size, lastStatMs: now };\r\n logFileMeta.set(src, meta);\r\n }\r\n\r\n // 大小达到阈值则轮转:重命名旧文件,重置缓存(下次写入会重新 ensureFile)\r\n if (meta.size >= maxSize) {\r\n const dateCur: any = new Date();\r\n const lastIndex = src.lastIndexOf(\".\");\r\n const filename = src.substring(0, lastIndex);\r\n const fileext = src.substring(lastIndex);\r\n await fs.rename(src, `${filename}-${getNowTime(5, dateCur)}${fileext}`);\r\n meta.ensured = false;\r\n meta.size = 0;\r\n }\r\n\r\n // 内存累加估算大小,避免下次写入再次 stat\r\n meta.size += Buffer.byteLength(logstr);\r\n await saveLog($asai, src, logstr);\r\n } catch (err) {\r\n console.error(err);\r\n // 出错时让该文件下次重新校准\r\n logFileMeta.delete(src);\r\n }\r\n}\r\n\r\n/** CLF + W3C Extended 访问日志双写(HTTP 响应完成时调用) */\r\nexport async function appendAccessLog($asai: any, clfLine: string, w3cLine: string): Promise<void> {\r\n const accessDir = $asai.hostconfig.logger?.path?.access;\r\n if (!accessDir) return;\r\n const dateCur = new Date();\r\n const dateStr = getNowTime(2, dateCur);\r\n const clfPath = `${accessDir}access-clf-${dateStr}.log`;\r\n const w3cPath = `${accessDir}access-w3c-${dateStr}.log`;\r\n\r\n try {\r\n const { ensureFile } = $asai.$lib.AsFs;\r\n await ensureFile(clfPath);\r\n await fs.appendFile(clfPath, clfLine, \"utf8\");\r\n await ensureW3CAccessHeader($asai, w3cPath, dateCur);\r\n await fs.appendFile(w3cPath, w3cLine, \"utf8\");\r\n const clfParsed = parseCLF(clfLine);\r\n void mirrorAccessLog($asai, {\r\n format: 'clf',\r\n rawLine: clfLine,\r\n host: clfParsed?.host as string,\r\n method: clfParsed?.method as string,\r\n url: clfParsed?.url as string,\r\n status: clfParsed?.status as number,\r\n }).catch(() => undefined);\r\n void mirrorAccessLog($asai, {\r\n format: 'w3c',\r\n rawLine: w3cLine,\r\n }).catch(() => undefined);\r\n } catch (err) {\r\n console.error(\"Access log write error:\", err);\r\n }\r\n}\r\n\r\nconst w3cAccessHeaderWritten = new Set<string>();\r\n\r\nasync function ensureW3CAccessHeader($asai: any, filePath: string, dateCur: Date): Promise<void> {\r\n if (w3cAccessHeaderWritten.has(filePath)) return;\r\n try {\r\n const stat = await fs.stat(filePath);\r\n if (stat.size > 0) {\r\n w3cAccessHeaderWritten.add(filePath);\r\n return;\r\n }\r\n } catch {\r\n /* 新文件 */\r\n }\r\n const header = formatW3CHeader({\r\n software: $asai.hostconfig.website?.title || \"AsaiHostNodejs\",\r\n version: $asai.hostconfig.website?.ver || \"1.0.0.0\",\r\n fields: [...W3C_ACCESS_FIELDS],\r\n date: dateCur,\r\n });\r\n await fs.appendFile(filePath, header, \"utf8\");\r\n w3cAccessHeaderWritten.add(filePath);\r\n}\r\n\r\n/** 同步风格日志写入(包装 setAppend) */\r\nexport function setLog($asai: any, src: string, logstr: string): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n setAppend($asai, src, logstr).then(resolve).catch(reject);\r\n } catch (err) {\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 初始化日志系统\r\n * - 挂载 $asai.$log 函数\r\n * - $asai.hostconfig.logger.lv.record ? llog(写文件) : xlog(仅控制台)\r\n * - 参数 0 / 不传:服务端日志(自动加时间戳);参数 1:客户端日志\r\n * - 参数 > 666:静默日志(仅记录,控制台不输出)\r\n */\r\nexport function initLog($asai: any): void {\r\n /** 控制台输出(受 lv.view 开关控制) */\r\n function clog(...args: any[]): void {\r\n if ($asai.hostconfig.logger?.lv?.view) {\r\n console.log(...args);\r\n }\r\n }\r\n\r\n function formatArg(item: any): string {\r\n if (item instanceof Error) return item.message || String(item);\r\n if (typeof item === \"object\") {\r\n try {\r\n return JSON.stringify(item);\r\n } catch {\r\n return String(item);\r\n }\r\n }\r\n return String(item);\r\n }\r\n\r\n /** 高频日志采样(logger.sample.REQ_OTHER = 0.05 表示约 5% 记录) */\r\n function shouldSample(args: any[]): boolean {\r\n const sample = $asai.hostconfig.logger?.sample;\r\n if (!sample || typeof sample !== \"object\") return true;\r\n const typeArg = args.find((a) => typeof a === \"string\");\r\n if (!typeArg || sample[typeArg] == null) return true;\r\n const rate = Number(sample[typeArg]);\r\n if (Number.isNaN(rate) || rate >= 1) return true;\r\n if (rate <= 0) return false;\r\n return Math.random() < rate;\r\n }\r\n\r\n function enqueueServerLog(logType: string, method: string | undefined, url: string | undefined, message: string, dateCur: Date): void {\r\n const filePath = `${$asai.hostconfig.logger.path.server}log-${getNowTime(2, dateCur)}.txt`;\r\n const logstr = formatW3CServerRecord({\r\n date: dateCur,\r\n logType,\r\n method,\r\n url,\r\n message,\r\n });\r\n void (async () => {\r\n try {\r\n await ensureW3CHeader($asai, filePath, dateCur);\r\n await saveLog($asai, filePath, logstr);\r\n } catch (err) {\r\n console.error(\"Log enqueue error:\", err);\r\n }\r\n })();\r\n }\r\n\r\n /** 仅控制台日志(record=false 走此分支) */\r\n function xlog(...args: any[]): void {\r\n clog(...args);\r\n }\r\n\r\n /** 完整日志:控制台 + 异步缓冲写文件(不 await,避免阻塞请求) */\r\n function llog(...args: any[]): void {\r\n if (!shouldSample(args)) return;\r\n\r\n const dateCur = new Date();\r\n const argType = args[0];\r\n\r\n if (argType === 1) {\r\n if ($asai.hostconfig.logger?.path?.client) {\r\n const logMsg = args.slice(1).map(formatArg).join(\"\\n\");\r\n const logstr = formatW3CServerRecord({\r\n date: dateCur,\r\n logType: \"CLIENT\",\r\n message: logMsg,\r\n });\r\n clog(`[${getNowTime(3, dateCur)}]\\n${logMsg}\\n`);\r\n const filePath = `${$asai.hostconfig.logger.path.client}log-${getNowTime(2, dateCur)}.txt`;\r\n void (async () => {\r\n try {\r\n await ensureW3CHeader($asai, filePath, dateCur);\r\n await saveLog($asai, filePath, logstr);\r\n } catch (err) {\r\n console.error(\"Log enqueue error:\", err);\r\n }\r\n })();\r\n }\r\n return;\r\n }\r\n\r\n const logType = typeof argType === \"string\" ? argType : \"LOG\";\r\n const restArgs = typeof argType === \"number\" && argType > 666 ? args.slice(1) : args.slice(1);\r\n const message = restArgs.map(formatArg).join(\"; \").replace(/[\\n\\r]/g, \" \");\r\n let method: string | undefined;\r\n let url: string | undefined;\r\n if (typeof restArgs[0] === \"string\" && typeof restArgs[1] === \"string\") {\r\n method = restArgs[0];\r\n url = restArgs[1];\r\n }\r\n\r\n if (typeof argType === \"number\" && argType > 666) {\r\n if ($asai.hostconfig.logger?.path?.server) {\r\n enqueueServerLog(logType, method, url, message, dateCur);\r\n }\r\n } else if ($asai.hostconfig.logger?.path?.server) {\r\n const consoleLine = `[${getNowTime(3, dateCur)}] ${message}\\n`;\r\n clog(consoleLine);\r\n enqueueServerLog(logType, method, url, message, dateCur);\r\n }\r\n }\r\n\r\n if (\r\n $asai &&\r\n typeof $asai === \"object\" &&\r\n $asai.hostconfig.logger?.lv?.record\r\n ) {\r\n $asai.$log = llog;\r\n } else {\r\n $asai.$log = xlog;\r\n }\r\n}\r\n","/**\r\n * WS 路由前缀索引 — 最长前缀匹配,替代 hostserverwss.find() 线性扫描\r\n */\r\nconst NON_ROUTE_KEYS = new Set(['wsWork', 'commandwork']);\r\n\r\nexport class WsRouteIndex {\r\n\tprivate routes: string[] = [];\r\n\r\n\trebuild(keys: string[]): void {\r\n\t\tthis.routes = keys.filter((k) => k && !NON_ROUTE_KEYS.has(k)).sort((a, b) => b.length - a.length);\r\n\t}\r\n\r\n\tmatchTy(ty: string | undefined): string | undefined {\r\n\t\tif (!ty || typeof ty !== 'string') return undefined;\r\n\t\tfor (const route of this.routes) {\r\n\t\t\tif (ty.startsWith(route)) return route;\r\n\t\t}\r\n\t\treturn undefined;\r\n\t}\r\n\r\n\tmatchString(msg: string): string | undefined {\r\n\t\tif (typeof msg !== 'string') return undefined;\r\n\t\tfor (const route of this.routes) {\r\n\t\t\tif (msg.startsWith(route)) return route;\r\n\t\t}\r\n\t\treturn undefined;\r\n\t}\r\n}\r\n\r\nexport function createWsRouteIndex(keys: string[] = []): WsRouteIndex {\r\n\tconst index = new WsRouteIndex();\r\n\tindex.rebuild(keys);\r\n\treturn index;\r\n}\r\n\r\nexport function isWsRouteKey(key: string): boolean {\r\n\treturn !!key && !NON_ROUTE_KEYS.has(key);\r\n}\r\n","/**\r\n * 统一 API / WS 路由注册 — 同步 $lib 与 hostserver*,避免双写遗漏\r\n */\r\nimport { WsRouteIndex, isWsRouteKey } from '../ws/route-index';\r\n\r\nexport type RouteFactory = ($asai: any) => Record<string, unknown>;\r\n\r\nexport function ensureWsRouteIndex($asai: any): WsRouteIndex {\r\n\tif (!$asai.wsRouteIndex) {\r\n\t\t$asai.wsRouteIndex = new WsRouteIndex();\r\n\t}\r\n\treturn $asai.wsRouteIndex as WsRouteIndex;\r\n}\r\n\r\nexport function syncApiRouteKeys($asai: any): void {\r\n\t$asai.hostserverapis = Object.keys($asai.hostserverapi || {});\r\n}\r\n\r\nexport function syncWsRouteKeys($asai: any): void {\r\n\tconst keys = Object.keys($asai.hostserverws || {}).filter(isWsRouteKey);\r\n\t$asai.hostserverwss = keys;\r\n\tensureWsRouteIndex($asai).rebuild(keys);\r\n}\r\n\r\n/** 注册 API:同时写入 $lib.api 与 hostserverapi(若已初始化) */\r\nexport function registerApi($asai: any, key: string, factory: RouteFactory): void {\r\n\tif (!$asai.$lib) $asai.$lib = {};\r\n\tif (!$asai.$lib.api) $asai.$lib.api = {};\r\n\t$asai.$lib.api[key] = factory;\r\n\tif ($asai.hostserverapi) {\r\n\t\t$asai.hostserverapi[key] = factory;\r\n\t\tsyncApiRouteKeys($asai);\r\n\t}\r\n}\r\n\r\n/** 注册 WS:同时写入 $lib.ws 与 hostserverws(若已初始化) */\r\nexport function registerWs($asai: any, key: string, factory: RouteFactory): void {\r\n\tif (!$asai.$lib) $asai.$lib = {};\r\n\tif (!$asai.$lib.ws) $asai.$lib.ws = {};\r\n\t$asai.$lib.ws[key] = factory;\r\n\tif ($asai.hostserverws) {\r\n\t\t$asai.hostserverws[key] = factory;\r\n\t\tsyncWsRouteKeys($asai);\r\n\t}\r\n}\r\n\r\n/** 初始化 hostserverapi(work 层启动时调用) */\r\nexport function initHostserverApi($asai: any, extra: Record<string, RouteFactory> = {}): void {\r\n\t$asai.hostserverapi = {\r\n\t\t...($asai.$lib?.api || {}),\r\n\t\t...extra,\r\n\t};\r\n\tsyncApiRouteKeys($asai);\r\n}\r\n\r\n/** 初始化 hostserverws(work 层启动时调用) */\r\nexport function initHostserverWs($asai: any, extra: Record<string, RouteFactory> = {}): any {\r\n\tconst commonModule = $asai.$lib?.ServerWs ? $asai.$lib.ServerWs($asai) : {};\r\n\t$asai.hostserverws = {\r\n\t\t...(commonModule || {}),\r\n\t\t...($asai.$lib?.ws || {}),\r\n\t\t...extra,\r\n\t};\r\n\tsyncWsRouteKeys($asai);\r\n\treturn commonModule;\r\n}\r\n\r\n/** 挂载 register* 到 $asai 运行时 */\r\nexport function attachRegistry($asai: any): void {\r\n\t$asai.registerApi = (key: string, factory: RouteFactory) => registerApi($asai, key, factory);\r\n\t$asai.registerWs = (key: string, factory: RouteFactory) => registerWs($asai, key, factory);\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 6.2 — 安全审计事件记录\r\n * 与 GDPR 行为日志分离,专用于鉴权失败、访问拒绝等安全事件。\r\n */\r\nexport type SecurityEventType =\r\n\t| 'AUTH_FAIL'\r\n\t| 'AUTH_MISSING'\r\n\t| 'ACCESS_DENIED'\r\n\t| 'INPUT_REJECTED'\r\n\t| 'RATE_LIMIT'\r\n\t| 'CONFIG_WARN';\r\n\r\nexport interface SecurityAuditEvent {\r\n\ttype: SecurityEventType;\r\n\tpath?: string;\r\n\tmethod?: string;\r\n\tuser?: string;\r\n\tlevel?: string | number;\r\n\tdetail?: string;\r\n\tip?: string;\r\n}\r\n\r\nfunction isAuditEnabled($asai: any): boolean {\r\n\tconst sec = $asai?.hostconfig?.security;\r\n\tif (sec && typeof sec.auditLog === 'number') return sec.auditLog !== 0;\r\n\treturn true;\r\n}\r\n\r\nexport function logSecurityEvent($asai: any, event: SecurityAuditEvent): void {\r\n\tif (!isAuditEnabled($asai)) return;\r\n\tconst ts = new Date().toISOString();\r\n\tconst parts = [\r\n\t\t'[SEC-AUDIT]',\r\n\t\tts,\r\n\t\tevent.type,\r\n\t\tevent.method || '-',\r\n\t\tevent.path || '-',\r\n\t\tevent.user ? `user=${event.user}` : '',\r\n\t\tevent.level != null ? `lv=${event.level}` : '',\r\n\t\tevent.detail || '',\r\n\t\tevent.ip ? `ip=${event.ip}` : '',\r\n\t].filter(Boolean);\r\n\tconst line = parts.join(' ');\r\n\t($asai?.$log || console.warn)('SEC', line);\r\n}\r\n\r\nexport function getClientIp(req: any): string {\r\n\tconst forwarded = req?.headers?.['x-forwarded-for'];\r\n\tif (typeof forwarded === 'string' && forwarded.length > 0) {\r\n\t\treturn forwarded.split(',')[0].trim();\r\n\t}\r\n\treturn req?.socket?.remoteAddress || '-';\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 4.3 — 标准加密算法合规自检\r\n */\r\nexport const APPROVED_ALGORITHMS = ['aes-256-gcm', 'scrypt', 'sha256', 'hmac-sha256'] as const;\r\n\r\nexport function verifyCryptoCompliance($asai: any): string[] {\r\n\tconst warnings: string[] = [];\r\n\tconst aes = $asai?.hostconfig?.aes;\r\n\tconst algo = String(aes?.algorithm || 'aes-256-gcm').toLowerCase();\r\n\tif (!APPROVED_ALGORITHMS.includes(algo as (typeof APPROVED_ALGORITHMS)[number])) {\r\n\t\twarnings.push(`非推荐加密算法: ${algo}(CR 4.3)`);\r\n\t}\r\n\tif (aes?.keylength && Number(aes.keylength) < 256) {\r\n\t\twarnings.push(`AES 密钥长度不足: ${aes.keylength}(建议 ≥256)`);\r\n\t}\r\n\treturn warnings;\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 2.11 RE(1) — NTP 时间偏移检测(启动自检,不阻断服务)\r\n */\r\nimport { execFile } from 'node:child_process';\r\nimport { promisify } from 'node:util';\r\n\r\nconst execFileAsync = promisify(execFile);\r\n\r\nexport async function checkNtpOffset(maxOffsetMs = 5000): Promise<{ ok: boolean; offsetMs?: number; detail: string }> {\r\n\tif (process.platform === 'win32') {\r\n\t\ttry {\r\n\t\t\tconst { stdout } = await execFileAsync('w32tm', ['/query', '/status'], { timeout: 5000 });\r\n\t\t\tif (/Leap Indicator:\\s*0/.test(stdout) || /Source:/.test(stdout)) {\r\n\t\t\t\treturn { ok: true, detail: 'Windows Time service active' };\r\n\t\t\t}\r\n\t\t\treturn { ok: false, detail: 'Windows Time service status unknown' };\r\n\t\t} catch {\r\n\t\t\treturn { ok: false, detail: 'w32tm unavailable' };\r\n\t\t}\r\n\t}\r\n\ttry {\r\n\t\tconst { stdout } = await execFileAsync('timedatectl', ['show', '-p', 'NTPSynchronized', '--value'], { timeout: 3000 });\r\n\t\tif (stdout.trim() === 'yes') return { ok: true, detail: 'NTP synchronized (timedatectl)' };\r\n\t} catch {\r\n\t\t/* fall through */\r\n\t}\r\n\ttry {\r\n\t\tconst { stdout } = await execFileAsync('ntpdate', ['-q', 'pool.ntp.org'], { timeout: 8000 });\r\n\t\tconst m = stdout.match(/offset\\s+([-0-9.]+)\\s+sec/i);\r\n\t\tif (m) {\r\n\t\t\tconst offsetMs = Math.abs(parseFloat(m[1]) * 1000);\r\n\t\t\treturn {\r\n\t\t\t\tok: offsetMs <= maxOffsetMs,\r\n\t\t\t\toffsetMs,\r\n\t\t\t\tdetail: `ntpdate offset ${offsetMs}ms`,\r\n\t\t\t};\r\n\t\t}\r\n\t} catch {\r\n\t\t/* optional tool */\r\n\t}\r\n\treturn { ok: false, detail: 'NTP check skipped (no timedatectl/ntpdate)' };\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 3.4 RE(1) — asaihost.json 完整性 manifest 校验\r\n */\r\nimport { createHash } from 'node:crypto';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\nexport function computeConfigHash(configPath: string): string | null {\r\n\ttry {\r\n\t\tconst raw = fs.readFileSync(configPath);\r\n\t\treturn createHash('sha256').update(raw).digest('hex');\r\n\t} catch {\r\n\t\treturn null;\r\n\t}\r\n}\r\n\r\nexport function verifyConfigManifest(serverRoot: string): { ok: boolean; detail: string } {\r\n\tconst configPath = path.join(serverRoot, 'websys/sys/asaihost.json');\r\n\tconst manifestPath = path.join(serverRoot, 'websys/sys/asaihost.manifest.json');\r\n\tif (!fs.existsSync(manifestPath)) {\r\n\t\treturn { ok: true, detail: 'no manifest (optional)' };\r\n\t}\r\n\ttry {\r\n\t\tconst manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\r\n\t\tconst expected = String(manifest.sha256 || '');\r\n\t\tconst actual = computeConfigHash(configPath);\r\n\t\tif (!actual) return { ok: false, detail: 'config file unreadable' };\r\n\t\tif (expected && expected !== actual) {\r\n\t\t\treturn { ok: false, detail: 'asaihost.json hash mismatch' };\r\n\t\t}\r\n\t\treturn { ok: true, detail: 'manifest verified' };\r\n\t} catch (e: any) {\r\n\t\treturn { ok: false, detail: e?.message || 'manifest parse error' };\r\n\t}\r\n}\r\n\r\nexport function writeConfigManifest(serverRoot: string): string | null {\r\n\tconst configPath = path.join(serverRoot, 'websys/sys/asaihost.json');\r\n\tconst hash = computeConfigHash(configPath);\r\n\tif (!hash) return null;\r\n\tconst manifestPath = path.join(serverRoot, 'websys/sys/asaihost.manifest.json');\r\n\tfs.writeFileSync(\r\n\t\tmanifestPath,\r\n\t\tJSON.stringify({ file: 'asaihost.json', sha256: hash, updatedAt: new Date().toISOString() }, null, 2),\r\n\t\t'utf8',\r\n\t);\r\n\treturn hash;\r\n}\r\n","/** 启动期初始化 — IP、日志、进程守护、AES 插件、路由注册表、IEC 62443 自检 */\r\nimport { getIp, getHostIP } from './network';\r\nimport { getHostCFG } from './host-config';\r\nimport { initProcess, gracefulShutdown } from '../infra/process';\r\nimport { initLog, setAppend, appendAccessLog } from '../infra/logger';\r\nimport { attachRegistry } from '../infra/registry';\r\nimport { isDevDefaultPassword } from '../config/secrets';\r\nimport { logSecurityEvent } from '../infra/security-audit';\r\nimport { verifyCryptoCompliance } from '../infra/crypto-compliance';\r\nimport { checkNtpOffset } from '../infra/ntp-check';\r\nimport { verifyConfigManifest } from '../infra/config-integrity';\r\n\r\nexport function initAsaiHostNodejs($asai: any, _opt: any): void {\r\n\tif (!$asai.hostconfig?.ip) {\r\n\t\t$asai.hostconfig.ip = getIp();\r\n\t}\r\n\t$asai.setAppend = (src: string, logstr: string) => setAppend($asai, src, logstr);\r\n\t$asai.appendAccessLog = (clfLine: string, w3cLine: string) => appendAccessLog($asai, clfLine, w3cLine);\r\n\t$asai.getHost = (hostdir: string) => getHostCFG(hostdir, $asai);\r\n\t$asai.getHostIP = (ip?: string | null) => getHostIP(ip, $asai);\r\n\t$asai.gracefulShutdown = () => gracefulShutdown($asai);\r\n\tattachRegistry($asai);\r\n\r\n\tinitProcess($asai);\r\n\tinitLog($asai);\r\n\r\n\t$asai.hostconfig.asaiport = [];\r\n\t$asai.hostconfig.guardtm = null;\r\n\r\n\tif ($asai.hostconfig?.aes?.lv && !$asai.$lib?.aesfns && typeof $asai.$lib?.AsAES === 'function') {\r\n\t\tconst { reqAES, resAES } = $asai.$lib.AsAES($asai);\r\n\t\t$asai.$lib.aesfns = {\r\n\t\t\tallaes: $asai.hostconfig.aes.lv > 1,\r\n\t\t\treqAES,\r\n\t\t\tresAES,\r\n\t\t};\r\n\t}\r\n\r\n\tif (isDevDefaultPassword($asai.hostconfig?.password || '')) {\r\n\t\tlogSecurityEvent($asai, {\r\n\t\t\ttype: 'CONFIG_WARN',\r\n\t\t\tdetail: 'Using dev-only password; set ASAI_HOST_PASSWORD for production (IEC 62443-4-2 CR 1.7)',\r\n\t\t});\r\n\t\tvoid import('../sysserver/lib/common/intervention-hooks').then(({ logSecurityConfigIntervention }) =>\r\n\t\t\tlogSecurityConfigIntervention($asai, {\r\n\t\t\t\tsection: 'password',\r\n\t\t\t\tdetail: 'dev-default-password detected at startup',\r\n\t\t\t}),\r\n\t\t).catch(() => undefined);\r\n\t}\r\n\r\n\tscheduleLogComplianceCheck($asai);\r\n\r\n\tfor (const w of verifyCryptoCompliance($asai)) {\r\n\t\tlogSecurityEvent($asai, { type: 'CONFIG_WARN', detail: w });\r\n\t}\r\n\tconst root = $asai.serverRoot || process.cwd();\r\n\tconst manifest = verifyConfigManifest(root);\r\n\tif (!manifest.ok) {\r\n\t\tlogSecurityEvent($asai, { type: 'CONFIG_WARN', detail: `Config integrity: ${manifest.detail}` });\r\n\t}\r\n\tvoid checkNtpOffset().then((ntp) => {\r\n\t\tif (!ntp.ok) logSecurityEvent($asai, { type: 'CONFIG_WARN', detail: `NTP: ${ntp.detail}` });\r\n\t});\r\n}\r\n\r\n/** 定时合规巡检(默认 6 小时,链异常/磁盘告警经 WS 广播) */\r\nfunction scheduleLogComplianceCheck($asai: any): void {\r\n\tconst hours = Number($asai?.hostconfig?.logger?.complianceIntervalHours) || 6;\r\n\tif (hours <= 0) return;\r\n\tconst ms = hours * 3600 * 1000;\r\n\tsetInterval(() => {\r\n\t\tvoid import('../sysserver/lib/common/LogStore').then(({ getComplianceReport }) =>\r\n\t\t\tgetComplianceReport($asai, 'prod'),\r\n\t\t).catch(() => undefined);\r\n\t}, ms);\r\n}\r\n","/**\n * http-server.ts — HTTP/HTTPS 静态资源与 API 路由服务\n *\n * 请求分发:/sys → sysWork,/api → apiWork,/jsonp → jsonpWork,其余走静态目录。\n * 性能要点:\n * - 处理器在 server 创建时缓存到闭包,避免每请求查 Map\n * - 静态文件查找合并 stat,减少重复磁盘 I/O\n * - Userinfo 直接读 req.headers(Node 已解析)\n */\nimport * as http from 'http';\nimport * as https from 'https';\nimport { getHostCFG, getHostIP, getNowTime } from '../core';\nimport { createWSHost } from '../ws/server';\nimport { getWorkHandler } from '../index';\nimport { StaticPathCache } from './static-path-cache';\nimport { applySecurityHeaders, checkHttpHeader } from './security';\nimport { formatHttpError, logHttp, createSkipChecker } from './log';\nimport { createStaticHandler } from './static';\nimport { setupHttpConnectionMonitor } from './connection';\nimport { releasePort } from '../infra/port-release';\n\nexport { getHttpUserinfo, checkHttpHeader } from './security';\n\nfunction scheduleHttpRetry($asai: any, hostdir: string): void {\n\tif ($asai.hostconfig.guardtm) {\n\t\tclearTimeout($asai.hostconfig.guardtm);\n\t\t$asai.hostconfig.guardtm = null;\n\t}\n\t$asai.hostconfig.guardtm = setTimeout(() => {\n\t\tstartHTTPServer($asai, hostdir);\n\t\tif ($asai.hostconfig.guardtm) {\n\t\t\tclearTimeout($asai.hostconfig.guardtm);\n\t\t\t$asai.hostconfig.guardtm = null;\n\t\t}\n\t}, $asai.hostconfig.tm?.d || 2000);\n}\n\nfunction clearFailedHttpHost($asai: any, hostdir: string, ws?: boolean): void {\n\tdelete $asai.servershttp[hostdir];\n\tif (ws) delete $asai.serversws[hostdir];\n}\n\nexport function getHTTPServer(httptype: string = '', cfg: any, $asai: any): any {\n\ttry {\n\t\tif (httptype.startsWith('https')) {\n\t\t\t// 返回包装对象,避免修改不可扩展的原生模块\n\t\t\treturn {\n\t\t\t\tAsCreateServer: (callback: any) => {\n\t\t\t\t\treturn https.createServer(cfg?.httpscert || $asai.hostconfig.httpscert, callback);\n\t\t\t\t},\n\t\t\t\tAgent: https.Agent,\n\t\t\t\trequest: https.request,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tAsCreateServer: http.createServer,\n\t\t\t\tAgent: http.Agent,\n\t\t\t\trequest: http.request,\n\t\t\t};\n\t\t}\n\t} catch (err) {\n\t\t$asai.$log('HTTP', 'Http server error:', err instanceof Error ? `${err.name}: ${err.message}\\n${err.stack}` : JSON.stringify(err));\n\t\treturn {\n\t\t\tAsCreateServer: http.createServer,\n\t\t\tAgent: http.Agent,\n\t\t\trequest: http.request,\n\t\t};\n\t}\n}\n\nexport function startHTTPServer($asai: any, hostdir: string): any {\n\tconst hostcfg = getHostCFG(hostdir, $asai);\n\tif (!hostcfg || hostcfg.close) return;\n\n\ttry {\n\t\tif (!$asai.servershttp[hostdir]) {\n\t\t\tif (hostcfg.mimetypes !== undefined) {\n\t\t\t\thostcfg.mimetypes = { ...($asai.hostconfig.mimetypes || {}), ...(hostcfg.mimetypes || {}) };\n\t\t\t} else {\n\t\t\t\thostcfg.mimetypes = { ...($asai.hostconfig.mimetypes || {}) };\n\t\t\t}\n\n\t\t\tconst httpLib = getHTTPServer(hostcfg.httptype, hostcfg, $asai);\n\t\t\tconst indexFile = $asai.hostconfig.index || 'index.html';\n\t\t\tconst staticPathCache = new StaticPathCache(2000, 30_000);\n\t\t\tconst skipChecker = createSkipChecker($asai);\n\t\t\tconst isHttps = (hostcfg.httptype || '').startsWith('https');\n\t\t\t// 处理器缓存在闭包内,热路径零查找\n\t\t\tconst apiWorkHost = getWorkHandler('apiWorkHost');\n\t\t\tconst sysWork = getWorkHandler('sysWork');\n\t\t\tconst apiWork = getWorkHandler('apiWork');\n\t\t\tconst jsonpWork = getWorkHandler('jsonpWork');\n\t\t\tconst handleStatic = createStaticHandler({ hostcfg, hostdir, indexFile, $asai, staticPathCache });\n\n\t\t\tconst server = (httpLib as any).AsCreateServer((req: any, res: any) => {\n\t\t\t\ttry {\n\t\t\t\t\tif (!checkHttpHeader(req, $asai)) {\n\t\t\t\t\t\tlogHttp($asai, 'HTTP', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\tres.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' });\n\t\t\t\t\t\tres.end('502');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tapplySecurityHeaders(res, isHttps, $asai.hostconfig);\n\n\t\t\t\t\tif (req.url?.startsWith('/sys') && sysWork) {\n\t\t\t\t\t\tlogHttp($asai, 'SYS', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\tsysWork(req, res, hostdir);\n\t\t\t\t\t} else if (req.url?.startsWith('/api') && apiWork) {\n\t\t\t\t\t\tlogHttp($asai, 'API', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\tapiWork(req, res, hostdir);\n\t\t\t\t\t} else if (req.url?.startsWith('/jsonp') && jsonpWork) {\n\t\t\t\t\t\tlogHttp($asai, 'JSONP', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\tjsonpWork(req, res, hostdir);\n\t\t\t\t\t} else if (handleStatic) {\n\t\t\t\t\t\tlogHttp($asai, 'REQ_OTHER', req.method, req.url, skipChecker, req, res);\n\t\t\t\t\t\thandleStatic(req, res, req.url!);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$asai.$log('HTTP', req.method, req.url);\n\t\t\t\t\t\tres.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });\n\t\t\t\t\t\tres.end('404');\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\t$asai.$log('HTTP', 'HTTP request error:', formatHttpError(err));\n\t\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\n\t\t\t\t\t\tres.end('Internal server error');\n\t\t\t\t\t} else if (!res.writableEnded) {\n\t\t\t\t\t\tres.end();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t$asai.servershttp[hostdir] = server;\n\n\t\t\tif (hostcfg.ws) {\n\t\t\t\tcreateWSHost($asai, hostdir);\n\t\t\t}\n\n\t\t\tserver.on('error', (err: any) => {\n\t\t\t\tif (err.code === 'EADDRINUSE') {\n\t\t\t\t\t$asai.hostconfig.asaiport.push(hostcfg.port);\n\t\t\t\t\t$asai.$log('HTTP', `\\x1B[41mPort ${hostcfg.port} is already start!\\x1B[0m`);\n\t\t\t\t\tclearFailedHttpHost($asai, hostdir, hostcfg.ws);\n\t\t\t\t\tasaiGuard($asai, hostdir);\n\t\t\t\t} else {\n\t\t\t\t\t$asai.$log('HTTP', 'Server error:', err instanceof Error ? `${err.name}: ${err.message}\\n${err.stack}` : err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treleasePort(hostcfg.port, { excludePid: process.pid, label: hostdir });\n\n\t\t\tif ($asai.hostconfig.ip === 'asai' || (!hostcfg.ip && !$asai.hostconfig.ip)) {\n\t\t\t\tserver.listen(hostcfg.port, () => {\n\t\t\t\t\tconsole.log(`[${hostdir}] Start At ${getNowTime()}.`);\n\t\t\t\t\tif (hostcfg.ws) {\n\t\t\t\t\t\tconsole.log(`\\x1B[41;28mWS Server ${hostcfg.wstype || 'ws://'}localhost:${hostcfg.port}\\x1B[0m`);\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log(`\\x1B[42;28mHTTP Server ${hostcfg.httptype}localhost:${hostcfg.port}\\x1B[0m`);\n\t\t\t\t\tconsole.log(`================================================`);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst ipcur: string = getHostIP(hostcfg.ip, $asai);\n\t\t\t\tserver.listen(hostcfg.port, ipcur, () => {\n\t\t\t\t\tconsole.log(`[${hostdir}] Start At ${getNowTime()}.`);\n\t\t\t\t\tif (hostcfg.ws) {\n\t\t\t\t\t\tconsole.log(`\\x1B[41;28mWS Server ${hostcfg.wstype || 'ws://'}${ipcur}:${hostcfg.port}\\x1B[0m`);\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log(`\\x1B[44;28mHTTP Server ${hostcfg.httptype}${ipcur}:${hostcfg.port}\\x1B[0m`);\n\t\t\t\t\tconsole.log(`================================================`);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (hostcfg.ckhttp) {\n\t\t\t\tsetupHttpConnectionMonitor($asai, hostdir, server, hostcfg);\n\t\t\t}\n\t\t}\n\t} catch (err) {\n\t\t$asai.$log('HTTP', 'Http server error:', err instanceof Error ? `${err.name}: ${err.message}\\n${err.stack}` : JSON.stringify(err));\n\t}\n\n\treturn $asai.servershttp[hostdir];\n}\n\nfunction findSameProcessPortOwner($asai: any, port: number, excludeHostdir: string): string | null {\n\tfor (const hostdir of Object.keys($asai.servershttp || {})) {\n\t\tif (hostdir === excludeHostdir) continue;\n\t\tconst cfg = getHostCFG(hostdir, $asai);\n\t\tif (cfg?.port === port) return hostdir;\n\t}\n\treturn null;\n}\n\nexport function asaiGuard($asai: any, failedHostdir: string = 'asai'): void {\n\tconst conflictPorts: number[] = $asai.hostconfig.asaiport || [];\n\tconst hostcfg = getHostCFG(failedHostdir, $asai);\n\tconst port = hostcfg?.port;\n\tif (!port || !conflictPorts.includes(port)) {\n\t\tscheduleHttpRetry($asai, failedHostdir);\n\t\treturn;\n\t}\n\n\tconst sameProcessOwner = findSameProcessPortOwner($asai, port, failedHostdir);\n\tif (sameProcessOwner) {\n\t\tconsole.error(\n\t\t\t`[AsaiHostNodejs] 端口 ${port} 已被同进程站点 [${sameProcessOwner}] 占用,[${failedHostdir}] 停止重试(请检查 asaihost.json 是否重复配置 port)`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst released = releasePort(port, { excludePid: process.pid, label: failedHostdir });\n\t$asai.hostconfig.asaiport = conflictPorts.filter((p: number) => p !== port);\n\tif (released) {\n\t\tconsole.warn(`[AsaiHostNodejs] 端口 ${port} 已释放,正在重新启动 [${failedHostdir}]`);\n\t\tscheduleHttpRetry($asai, failedHostdir);\n\t\treturn;\n\t}\n\n\tconsole.error(`[AsaiHostNodejs] 端口 ${port} 无法释放,启动失败(netstat -ano | findstr :${port})`);\n\tprocess.exit(1);\n}\n","/** WebSocket 服务 — 挂载在 HTTP server 上,鉴权 + 消息转发 */\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { getHostCFG } from '../core';\nimport { getWorkHandler } from '../index';\nimport { getWsUserinfo, isOkWs, loginWs } from './auth';\nimport { attachWssHelpers, clearWsServerTasks } from './message';\nimport { acquireWsSlot, countActiveWsConnections, getMaxWebConnections, releaseWsSlot } from '../infra/connection-quota';\nimport { getClientIp, logSecurityEvent } from '../infra/security-audit';\n\nexport { clearWsServerTasks } from './message';\nexport { getWsUserinfo } from './auth';\n\nexport function createWSHost($asai: any, hostdir: string): void {\n\tconst hostcfg = getHostCFG(hostdir, $asai);\n\tconst wsWorkHandler = getWorkHandler('wsWork');\n\tconst logWsMessage = !!$asai.hostconfig.logger?.lv?.view;\n\n\ttry {\n\t\tif ($asai.serversws[hostdir]) return;\n\n\t\tif (hostcfg.ckws && !$asai.connectionsws[hostdir]) {\n\t\t\t$asai.connectionsws[hostdir] = {};\n\t\t}\n\t\tif (!$asai.tasksws[hostdir]) $asai.tasksws[hostdir] = {};\n\n\t\tconst wss = new WebSocketServer({ server: $asai.servershttp[hostdir], perMessageDeflate: false });\n\t\tattachWssHelpers(wss, $asai);\n\n\t\twss.on('error', (err: Error) => {\n\t\t\tclearWsServerTasks($asai, hostdir);\n\t\t\t$asai.$log('WS', 'WS Server error!', err);\n\t\t\twss.close?.(() => {\n\t\t\t\t$asai.$log('WS', 'WS Server closed');\n\t\t\t\tdelete $asai.serversws[hostdir];\n\t\t\t});\n\t\t});\n\n\t\twss.on('close', (code: number, reason: Buffer) => {\n\t\t\ttry {\n\t\t\t\t$asai.$log('WS', `WebSocket closed, server ${hostdir}, code: ${code}, reason: ${reason?.toString()}`);\n\t\t\t\tclearWsServerTasks($asai, hostdir);\n\t\t\t} catch (err) {\n\t\t\t\t$asai.$log('WS', 'WS close handler error:', err);\n\t\t\t}\n\t\t});\n\n\t\twss.on('connection', (ws: any, req: any) => {\n\t\t\tconst clientIp = getClientIp(req);\n\t\t\tif (!acquireWsSlot($asai, hostdir, clientIp)) {\n\t\t\t\tconst wsmsg = JSON.stringify({\n\t\t\t\t\tty: 'publish/web',\n\t\t\t\t\tdb: { exit: 1, type: 'err', lang: 'maxws', langpm: 'ip', con: 'WS IP quota exceeded' },\n\t\t\t\t});\n\t\t\t\tws.send(wsmsg, () => ws.close(1013, 'Server busy'));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tws.once('close', () => releaseWsSlot(hostdir, clientIp));\n\n\t\t\treq.Userinfo = getWsUserinfo(req, $asai) || [];\n\t\t\tws.Userinfo = req.Userinfo;\n\n\t\t\tconst maxWs = getMaxWebConnections($asai, hostcfg);\n\t\t\tconst currentWsConnections = countActiveWsConnections(wss, ws, $asai, hostdir, hostcfg, req.Userinfo);\n\n\t\t\tif (currentWsConnections >= maxWs) {\n\t\t\t\t$asai.$log('WS', `WS Connection MAX rejected (${currentWsConnections}/${maxWs})`);\n\t\t\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/ws', detail: 'maxWebConnections', ip: clientIp });\n\t\t\t\tconst wsmsg = JSON.stringify({\n\t\t\t\t\tty: 'publish/web',\n\t\t\t\t\tdb: { exit: 1, type: 'err', lang: 'maxws', langpm: `${maxWs}`, con: `connection limit ${maxWs} exceeded` },\n\t\t\t\t});\n\t\t\t\tws.send(wsmsg, () => ws.close(1013, 'Server busy'));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst isOpen = !hostcfg.ckws || isOkWs($asai, hostdir, ws, req, hostcfg);\n\t\t\tif (isOpen) {\n\t\t\t\tloginWs($asai, hostdir, ws, req, hostcfg, wsWorkHandler, logWsMessage);\n\t\t\t} else {\n\t\t\t\tws.close();\n\t\t\t}\n\t\t});\n\n\t\t$asai.serversws[hostdir] = wss;\n\t} catch (err) {\n\t\t$asai.$log('WS', 'ws server:', JSON.stringify(err));\n\t}\n}\n","/** WebSocket 连接鉴权、登录态管理与消息回调 */\nimport { WebSocket } from 'ws';\nimport { deUserInfoWithAsai } from '../utils/userinfo';\nimport { createUserStore } from '../sysserver/api/login/store/user-store';\n\nexport function getWsUserinfo(req: any, $asai: any): any {\n\ttry {\n\t\tconst raw = req.headers?.['sec-websocket-protocol'];\n\t\tif (!raw) return null;\n\t\treturn deUserInfoWithAsai(raw.split('##'), $asai);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** 列出当前 WS 在线用户名(去重;仅 OPEN/CONNECTING) */\nexport function listOnlineWsUsers($asai: any, hostdir?: string): string[] {\n\tconst users: string[] = [];\n\tconst map = $asai.connectionsws || {};\n\tconst dirs = hostdir ? [hostdir] : Object.keys(map);\n\tfor (const dir of dirs) {\n\t\tfor (const [us, ws] of Object.entries(map[dir] || {})) {\n\t\t\tif (!us || us === 'asai') continue;\n\t\t\tif (isWsStillActive(ws)) {\n\t\t\t\tusers.push(us);\n\t\t\t} else if (map[dir]?.[us] === ws) {\n\t\t\t\tdelete map[dir][us];\n\t\t\t}\n\t\t}\n\t}\n\treturn [...new Set(users)];\n}\n\n/** 用户是否已在 WS 在线表(ckws 单点登录判定;仅计仍 OPEN/CONNECTING 的连接) */\nexport function isUserOnlineOnWs($asai: any, us: string, hostdir?: string): boolean {\n\tif (!us || us === 'asai') return false;\n\tconst map = $asai.connectionsws || {};\n\tconst dirs = hostdir ? [hostdir] : Object.keys(map);\n\tfor (const dir of dirs) {\n\t\tconst ws = map[dir]?.[us];\n\t\tif (!ws) continue;\n\t\tif (isWsStillActive(ws)) return true;\n\t\t// 僵尸条目:连接已关闭但未从在线表移除,会误拦 HTTP 登录\n\t\tif (map[dir]?.[us] === ws) delete map[dir][us];\n\t}\n\treturn false;\n}\n\n/** 关闭并移除指定用户的 WS 在线位(凭密码重新登录时接管) */\nexport function kickUserWs($asai: any, us: string, hostdir?: string): void {\n\tif (!us || us === 'asai') return;\n\tconst map = $asai.connectionsws || {};\n\tconst dirs = hostdir ? [hostdir] : Object.keys(map);\n\tfor (const dir of dirs) {\n\t\tconst ws = map[dir]?.[us];\n\t\tif (!ws) continue;\n\t\ttry {\n\t\t\tws.close();\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t\tif (map[dir]?.[us] === ws) delete map[dir][us];\n\t}\n}\n\n/** WS 断开后移除对应会话(用户已完全离线时) */\nasync function removeSessionOnWsClose($asai: any, us: string, token: string) {\n\ttry {\n\t\tconst store = createUserStore($asai);\n\t\tconst sessions = await store.getSessions();\n\t\tconst match = sessions.find((s) => s.us === us && s.pub === token);\n\t\tif (match) await store.removeSession(match.id);\n\t} catch {\n\t\t/* optional */\n\t}\n}\n\n/** 连接仍有效(非刷新替换场景) */\nfunction isWsStillActive(ws: any): boolean {\n\tif (!ws) return false;\n\tconst state = ws.readyState;\n\treturn state === WebSocket.CONNECTING || state === WebSocket.OPEN;\n}\n\n/** 仅拒绝后来连接,不打扰已在线用户 */\nfunction rejectIncomingWs(ws: any, db: Record<string, unknown>): void {\n\tconst payload = JSON.stringify({ ty: 'publish/web', db: { exit: 1, type: 'err', ...db } });\n\ttry {\n\t\tws.send(payload, () => {\n\t\t\ttry {\n\t\t\t\tws.close();\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t});\n\t} catch {\n\t\ttry {\n\t\t\tws.close();\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t}\n}\n\nexport function isOkWs($asai: any, hostdir: string, ws: any, _req: any, hostcfg: any): boolean {\n\tconst [us, , tk] = ws.Userinfo || [];\n\n\tif (!us) {\n\t\tws.close();\n\t\treturn false;\n\t}\n\n\tif (us !== 'asai' && $asai.connectionsws[hostdir]?.[us]) {\n\t\tconst existingWs = $asai.connectionsws[hostdir][us];\n\t\tif (existingWs?.Userinfo?.[2] === tk) {\n\t\t\t// 同账号同 token:已有页面在运行则拒绝后来连接;旧连接已关闭/关闭中(刷新)才允许接管\n\t\t\tif (isWsStillActive(existingWs)) {\n\t\t\t\trejectIncomingWs(ws, {\n\t\t\t\t\tlang: 'pageworking',\n\t\t\t\t\tlangpm: `${us}`,\n\t\t\t\t\tcon: `${us} page already running`,\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\texistingWs.close();\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t\tdelete $asai.connectionsws[hostdir][us];\n\t\t\treturn true;\n\t\t}\n\t\t// 不同 token 的同账号:先登录者占据在线位,仅拒绝新连接\n\t\trejectIncomingWs(ws, {\n\t\t\tlang: 'logged',\n\t\t\tlangpm: `${us}`,\n\t\t\tcon: `${us} logged in!`,\n\t\t});\n\t\treturn false;\n\t}\n\n\tif (us !== 'asai') {\n\t\tconst connections = $asai.connectionsws[hostdir] || {};\n\t\t// 相同 token 已被其他账号占用:先占用者优先,仅拒绝新连接\n\t\tconst sameTkWs: any = Object.values(connections).find(\n\t\t\t(item: any) => item.Userinfo?.[2] === tk && item.Userinfo?.[0] !== us,\n\t\t);\n\t\tconst maxOnline = hostcfg.maxonline || 100;\n\n\t\tif (sameTkWs) {\n\t\t\trejectIncomingWs(ws, {\n\t\t\t\tlang: 'loggedsametk',\n\t\t\t\tlangpm: `${us}(${sameTkWs.Userinfo[0]})`,\n\t\t\t\tcon: `${us}(${sameTkWs.Userinfo[0]}) logged in!`,\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t\tif (Object.keys(connections).length >= maxOnline) {\n\t\t\trejectIncomingWs(ws, {\n\t\t\t\tlang: 'maxlogged',\n\t\t\t\tlangpm: `${maxOnline}`,\n\t\t\t\tcon: `max ${maxOnline} users online!`,\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport function loginWs(\n\t$asai: any, hostdir: string, ws: any, req: any, hostcfg: any,\n\twsWorkHandler: Function | undefined, logWsMessage: boolean,\n): void {\n\tconst [us] = ws.Userinfo || [];\n\tif (!$asai.connectionsws[hostdir]) {\n\t\t$asai.connectionsws[hostdir] = {};\n\t}\n\t// 始终登记 WS 在线位(管理端「在线用户」与 ckws 登录互斥共用同一张表)\n\tif (us && us !== 'asai') {\n\t\tif (hostcfg.ckws && !ws.tasksws) ws.tasksws = {};\n\t\t$asai.connectionsws[hostdir][us] = ws;\n\t}\n\n\tws.on('message', (msg: Buffer) => {\n\t\tif (logWsMessage) $asai.$log('WS', 'message', msg.toString());\n\t\twsWorkHandler?.(msg, ws, hostdir, req);\n\t});\n\n\tws.on('close', () => {\n\t\tconst token = ws.Userinfo?.[2];\n\t\tif (hostcfg.ckws && ws.tasksws) {\n\t\t\tObject.values(ws.tasksws).forEach((el: any) => el && clearInterval(el));\n\t\t\tws.tasksws = undefined;\n\t\t}\n\t\t// 仅当在线表里存的仍是「自己」时才删除;快速刷新时旧连接的 close 晚于新连接登记,\n\t\t// 若无条件删除会把刚登记的新连接误删,导致账号校验判定为未登录而触发退出\n\t\tif (us && $asai.connectionsws[hostdir]?.[us] === ws) delete $asai.connectionsws[hostdir][us];\n\t\tif (us && token && !isUserOnlineOnWs($asai, us, hostdir)) {\n\t\t\tvoid removeSessionOnWsClose($asai, us, String(token));\n\t\t}\n\t\tif (ws.readyState !== WebSocket.CLOSED && ws.readyState !== WebSocket.CLOSING) ws.close();\n\t});\n}\n","/** HTTP/WS Userinfo 解密(us##lv##tk,依赖 AsCode + asaisn) */\r\nexport function deUserInfoWithAsai(userinfo: string[] | null | undefined, $asai: any): string[] | null {\r\n\tif (!Array.isArray(userinfo) || userinfo.length < 3) {\r\n\t\treturn userinfo as any;\r\n\t}\r\n\tif (userinfo[2]) {\r\n\t\tconst sn = $asai?.hostconfig?.asaisn;\r\n\t\tif (!sn) {\r\n\t\t\t$asai.$log('USER', 'User info decode error: ASAI_ASAISN not configured');\r\n\t\t\treturn userinfo;\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tuserinfo[2] = $asai.$lib.AsCode.asdecode(userinfo[2], sn);\r\n\t\t\tuserinfo[0] = $asai.$lib.AsCode.asdecode(userinfo[0], userinfo[2]);\r\n\t\t\tuserinfo[1] = $asai.$lib.AsCode.asdecode(userinfo[1], userinfo[2]);\r\n\t\t} catch (err) {\r\n\t\t\t$asai.$log('USER', 'User info decode error:', err);\r\n\t\t}\r\n\t}\r\n\treturn userinfo;\r\n}\r\n","/** WS 出站消息序列化与定时任务清理 */\r\nimport { WebSocket } from 'ws';\r\n\r\nexport function clearWsServerTasks($asai: any, hostdir: string): void {\r\n\tconst tasks = $asai.tasksws[hostdir];\r\n\tif (tasks && typeof tasks === 'object') {\r\n\t\tObject.values(tasks).forEach((el: any) => {\r\n\t\t\tif (el) clearInterval(el as NodeJS.Timeout);\r\n\t\t});\r\n\t\t$asai.tasksws[hostdir] = {};\r\n\t}\r\n}\r\n\r\n/** ping/pong 原样返回,对象走 JSON,可选 AES 加密 db 字段 */\r\nexport function resWsMsg(msg: any, $asai: any): any {\r\n\tif (msg === 'ping' || msg === 'pong') return msg;\r\n\tif (typeof msg !== 'object' || msg === null) return msg;\r\n\tif ((msg?.aes || $asai.$lib.aesfns?.allaes) && msg?.db && $asai.$lib?.aesfns?.resAES) {\r\n\t\tmsg.db = $asai.$lib.aesfns.resAES(msg.db);\r\n\t}\r\n\treturn JSON.stringify(msg);\r\n}\r\n\r\nexport function attachWssHelpers(wss: any, $asai: any): void {\r\n\twss.sendws = (msg: any, type: number, curws: any) => {\r\n\t\tconst data = resWsMsg(msg, $asai);\r\n\t\tif (type) {\r\n\t\t\twss.clients.forEach((client: any) => {\r\n\t\t\t\tif ((type === 2 || client !== curws) && client.readyState === WebSocket.OPEN) {\r\n\t\t\t\t\tclient.send(data);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t} else {\r\n\t\t\tcurws.send(data);\r\n\t\t}\r\n\t};\r\n\twss.broadws = (msg: any) => {\r\n\t\tconst data = resWsMsg(msg, $asai);\r\n\t\twss.clients.forEach((client: any) => {\r\n\t\t\tif (client?.readyState === WebSocket.OPEN) client.send(data);\r\n\t\t});\r\n\t};\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 7 — API/WS/登录配额统一服务\r\n */\r\nimport type { WebSocket, WebSocketServer } from 'ws';\r\nimport { WebSocket as WsConst } from 'ws';\r\nimport { logSecurityEvent } from './security-audit';\r\n\r\ntype SlotMap = Map<string, number>;\r\ntype RateMap = Map<string, { count: number; resetAt: number }>;\r\n\r\nconst apiGlobal = new Map<string, number>();\r\nconst apiPerIp = new Map<string, SlotMap>();\r\nconst apiRatePerIp = new Map<string, RateMap>();\r\nconst wsPerIp = new Map<string, SlotMap>();\r\n\r\nfunction getQuota($asai: any) {\r\n\treturn $asai?.hostconfig?.security?.quota || {};\r\n}\r\n\r\nfunction isEnabled($asai: any): boolean {\r\n\tconst q = getQuota($asai);\r\n\treturn q.enabled === 1 || q.enabled === true;\r\n}\r\n\r\nfunction hostKey(hostdir: string): string {\r\n\treturn hostdir || 'default';\r\n}\r\n\r\nexport function acquireApiSlot($asai: any, hostdir: string, ip: string): { ok: boolean; code?: number; message?: string } {\r\n\tif (!isEnabled($asai)) return { ok: true };\r\n\tconst q = getQuota($asai);\r\n\tconst hk = hostKey(hostdir);\r\n\r\n\tconst maxGlobal = q.maxApiConcurrent ?? 500;\r\n\tconst curGlobal = apiGlobal.get(hk) || 0;\r\n\tif (curGlobal >= maxGlobal) {\r\n\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/api', detail: 'maxApiConcurrent', ip });\r\n\t\treturn { ok: false, code: 503, message: 'API quota exceeded' };\r\n\t}\r\n\r\n\tconst maxPerIp = q.maxApiPerIp ?? 30;\r\n\tconst ipMap = apiPerIp.get(hk) || new Map();\r\n\tconst curIp = ipMap.get(ip) || 0;\r\n\tif (curIp >= maxPerIp) {\r\n\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/api', detail: 'maxApiPerIp', ip });\r\n\t\treturn { ok: false, code: 429, message: 'Too many requests' };\r\n\t}\r\n\r\n\tconst maxPerMin = q.maxApiPerIpPerMin ?? 120;\r\n\tconst now = Date.now();\r\n\tlet rateHost = apiRatePerIp.get(hk);\r\n\tif (!rateHost) {\r\n\t\trateHost = new Map();\r\n\t\tapiRatePerIp.set(hk, rateHost);\r\n\t}\r\n\tlet bucket = rateHost.get(ip);\r\n\tif (!bucket || bucket.resetAt < now) {\r\n\t\tbucket = { count: 0, resetAt: now + 60000 };\r\n\t\trateHost.set(ip, bucket);\r\n\t}\r\n\tbucket.count += 1;\r\n\tif (bucket.count > maxPerMin) {\r\n\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/api', detail: 'maxApiPerIpPerMin', ip });\r\n\t\treturn { ok: false, code: 429, message: 'Rate limit exceeded' };\r\n\t}\r\n\r\n\tapiGlobal.set(hk, curGlobal + 1);\r\n\tipMap.set(ip, curIp + 1);\r\n\tapiPerIp.set(hk, ipMap);\r\n\treturn { ok: true };\r\n}\r\n\r\nexport function releaseApiSlot(hostdir: string, ip: string): void {\r\n\tconst hk = hostKey(hostdir);\r\n\tconst g = apiGlobal.get(hk) || 0;\r\n\tif (g > 0) apiGlobal.set(hk, g - 1);\r\n\tconst ipMap = apiPerIp.get(hk);\r\n\tif (ipMap) {\r\n\t\tconst c = ipMap.get(ip) || 0;\r\n\t\tif (c > 0) ipMap.set(ip, c - 1);\r\n\t}\r\n}\r\n\r\nexport function acquireWsSlot($asai: any, hostdir: string, ip: string): boolean {\r\n\tif (!isEnabled($asai)) return true;\r\n\tconst maxPerIp = getQuota($asai).maxWsPerIp ?? 5;\r\n\tconst hk = hostKey(hostdir);\r\n\tconst ipMap = wsPerIp.get(hk) || new Map();\r\n\tconst cur = ipMap.get(ip) || 0;\r\n\tif (cur >= maxPerIp) {\r\n\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: '/ws', detail: 'maxWsPerIp', ip });\r\n\t\treturn false;\r\n\t}\r\n\tipMap.set(ip, cur + 1);\r\n\twsPerIp.set(hk, ipMap);\r\n\treturn true;\r\n}\r\n\r\nexport function releaseWsSlot(hostdir: string, ip: string): void {\r\n\tconst hk = hostKey(hostdir);\r\n\tconst ipMap = wsPerIp.get(hk);\r\n\tif (!ipMap) return;\r\n\tconst c = ipMap.get(ip) || 0;\r\n\tif (c > 0) ipMap.set(ip, c - 1);\r\n}\r\n\r\n/** WEB 平台最大并发连接数:quota.maxWebConnections 优先,否则 hosts.*.maxws */\r\nexport function getMaxWebConnections($asai: any, hostcfg: any): number {\r\n\tconst q = getQuota($asai);\r\n\tconst fromQuota = Number(q.maxWebConnections);\r\n\tif (fromQuota > 0) return fromQuota;\r\n\treturn Number(hostcfg?.maxws) > 0 ? Number(hostcfg.maxws) : 100;\r\n}\r\n\r\n/**\r\n * 统计当前有效 WS 连接数(不含 incoming;同 token 刷新/重连时排除将被替换的旧连接)\r\n */\r\nexport function countActiveWsConnections(\r\n\twss: WebSocketServer,\r\n\tincoming: WebSocket,\r\n\t$asai: any,\r\n\thostdir: string,\r\n\thostcfg: any,\r\n\tuserinfo: unknown[],\r\n): number {\r\n\tconst [us, , tk] = (userinfo || []) as [string?, unknown?, string?];\r\n\tlet count = 0;\r\n\tfor (const client of wss.clients) {\r\n\t\tif (client === incoming) continue;\r\n\t\tif (client.readyState === WsConst.CLOSED || client.readyState === WsConst.CLOSING) continue;\r\n\t\tconst cInfo = (client as WebSocket & { Userinfo?: unknown[] }).Userinfo;\r\n\t\tconst cUs = cInfo?.[0] as string | undefined;\r\n\t\tconst cTk = cInfo?.[2] as string | undefined;\r\n\t\t// 同账号同 token 重连:旧连接即将被替换,不计入占用\r\n\t\tif (us && tk && cUs === us && cTk === tk) continue;\r\n\t\tif (hostcfg?.ckws && us && tk) {\r\n\t\t\tconst existing = $asai?.connectionsws?.[hostdir]?.[us];\r\n\t\t\tif (existing === client && existing?.Userinfo?.[2] === tk) continue;\r\n\t\t}\r\n\t\tcount += 1;\r\n\t}\r\n\treturn count;\r\n}\r\n\r\nexport function getQuotaSnapshot($asai: any, hostdir: string) {\r\n\tconst hk = hostKey(hostdir);\r\n\treturn {\r\n\t\tenabled: isEnabled($asai),\r\n\t\tapiGlobal: apiGlobal.get(hk) || 0,\r\n\t\tapiPerIp: Object.fromEntries(apiPerIp.get(hk) || []),\r\n\t\twsPerIp: Object.fromEntries(wsPerIp.get(hk) || []),\r\n\t\tconfig: getQuota($asai),\r\n\t};\r\n}\r\n","/**\r\n * 静态文件路径 LRU 缓存 — Map 插入序 O(1) 淘汰,命中后 stat 校验 mtime\r\n */\r\nimport * as fs from 'fs';\r\n\r\ninterface CacheEntry {\r\n\tfilePath: string;\r\n\tmtimeMs: number;\r\n\tis404?: boolean;\r\n\tcachedAt: number;\r\n}\r\n\r\nexport class StaticPathCache {\r\n\tprivate cache = new Map<string, CacheEntry>();\r\n\r\n\tconstructor(\r\n\t\tprivate readonly maxSize = 2000,\r\n\t\tprivate readonly notFoundTtlMs = 30_000,\r\n\t) {}\r\n\r\n\tprivate touch(key: string, entry: CacheEntry): void {\r\n\t\tif (this.cache.has(key)) this.cache.delete(key);\r\n\t\tthis.cache.set(key, entry);\r\n\t\twhile (this.cache.size > this.maxSize) {\r\n\t\t\tconst oldest = this.cache.keys().next().value;\r\n\t\t\tif (!oldest) break;\r\n\t\t\tthis.cache.delete(oldest);\r\n\t\t}\r\n\t}\r\n\r\n\tget(key: string): CacheEntry | null {\r\n\t\tconst entry = this.cache.get(key);\r\n\t\tif (!entry) return null;\r\n\t\tif (entry.is404 && Date.now() - entry.cachedAt > this.notFoundTtlMs) {\r\n\t\t\tthis.cache.delete(key);\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\tthis.cache.delete(key);\r\n\t\tthis.cache.set(key, entry);\r\n\t\treturn entry;\r\n\t}\r\n\r\n\tsetHit(key: string, filePath: string, mtimeMs: number): void {\r\n\t\tthis.touch(key, { filePath, mtimeMs, cachedAt: Date.now() });\r\n\t}\r\n\r\n\tsetMiss(key: string): void {\r\n\t\tthis.touch(key, { filePath: '', mtimeMs: 0, is404: true, cachedAt: Date.now() });\r\n\t}\r\n\r\n\tverify(entry: CacheEntry): fs.Stats | null {\r\n\t\tif (entry.is404 || !entry.filePath) return null;\r\n\t\ttry {\r\n\t\t\tconst stat = fs.statSync(entry.filePath);\r\n\t\t\tif (!stat.isFile() || stat.mtimeMs !== entry.mtimeMs) return null;\r\n\t\t\treturn stat;\r\n\t\t} catch {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t}\r\n}\r\n","/**\r\n * http-security.ts — OWASP / IEC 62443-4-2 响应头与用户鉴权信息解析\r\n */\r\nimport { deUserInfoWithAsai } from '../utils/userinfo';\r\n\r\n/** 默认 CSP:兼容现有 inline 脚本;security.csp=1 时启用 */\r\nconst DEFAULT_CSP =\r\n\t\"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self' ws: wss:; font-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'\";\r\n\r\nexport function applySecurityHeaders(res: any, isHttps = false, hostconfig?: any): void {\r\n\tres.setHeader('X-Content-Type-Options', 'nosniff');\r\n\tres.setHeader('X-Frame-Options', 'SAMEORIGIN');\r\n\tres.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');\r\n\tres.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');\r\n\tres.setHeader('X-XSS-Protection', '0');\r\n\tres.setHeader('Cross-Origin-Opener-Policy', 'same-origin');\r\n\tres.setHeader('Cross-Origin-Resource-Policy', 'same-origin');\r\n\tif (isHttps) {\r\n\t\tres.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');\r\n\t}\r\n\tconst sec = hostconfig?.security;\r\n\tif (sec?.csp) {\r\n\t\tconst csp = typeof sec.cspPolicy === 'string' && sec.cspPolicy.length > 0 ? sec.cspPolicy : DEFAULT_CSP;\r\n\t\tres.setHeader('Content-Security-Policy', csp);\r\n\t}\r\n}\r\n\r\nexport function getHttpUserinfo(req: any, $asai: any): any {\r\n\ttry {\r\n\t\tconst userinfo = req.headers?.['userinfo']?.split('##');\r\n\t\treturn deUserInfoWithAsai(userinfo, $asai);\r\n\t} catch {\r\n\t\treturn '';\r\n\t}\r\n}\r\n\r\nexport function checkHttpHeader(req: any, $asai: any): boolean {\r\n\treq.Userinfo = getHttpUserinfo(req, $asai);\r\n\treturn true;\r\n}\r\n","/**\r\n * http-log.ts — HTTP 请求日志过滤(启动期编译 skip 规则,热路径 O(1))\r\n * IEC 62443-4-2:响应完成时双写 CLF + W3C Extended 访问日志\r\n */\r\nimport { buildAccessEntry, formatCLF, formatW3CAccessRecord } from '../sysserver/lib/common/log-formats';\r\n\r\nexport function formatHttpError(err: unknown): string {\r\n\treturn err instanceof Error ? `${err.name}: ${err.message}` : String(err);\r\n}\r\n\r\nexport function shouldLogRequest(method: string | undefined): boolean {\r\n\treturn method !== 'OPTIONS';\r\n}\r\n\r\nexport function normalizeRequestPath(url: string | undefined): string {\r\n\tif (!url) return '';\r\n\tconst q = url.indexOf('?');\r\n\tconst h = url.indexOf('#');\r\n\tlet end = url.length;\r\n\tif (q >= 0) end = Math.min(end, q);\r\n\tif (h >= 0) end = Math.min(end, h);\r\n\treturn url.slice(0, end);\r\n}\r\n\r\nexport type SkipChecker = (url: string | undefined) => boolean;\r\n\r\n/** 启动时编译 logger.skip,避免每请求遍历规则数组 */\r\nexport function createSkipChecker($asai: any): SkipChecker {\r\n\tconst skip = $asai.hostconfig?.logger?.skip;\r\n\tif (!Array.isArray(skip) || skip.length === 0) return () => false;\r\n\r\n\tconst exact = new Set<string>();\r\n\tconst prefixes: string[] = [];\r\n\tfor (const rule of skip) {\r\n\t\tif (typeof rule !== 'string' || !rule) continue;\r\n\t\tif (rule.endsWith('*')) prefixes.push(rule.slice(0, -1));\r\n\t\telse exact.add(rule);\r\n\t}\r\n\tif (exact.size === 0 && prefixes.length === 0) return () => false;\r\n\r\n\treturn (url: string | undefined) => {\r\n\t\tconst path = normalizeRequestPath(url);\r\n\t\tif (!path) return false;\r\n\t\tif (exact.has(path)) return true;\r\n\t\tfor (let i = 0; i < prefixes.length; i++) {\r\n\t\t\tif (path.startsWith(prefixes[i])) return true;\r\n\t\t}\r\n\t\treturn false;\r\n\t};\r\n}\r\n\r\nexport function logHttp(\r\n\t$asai: any,\r\n\ttype: string,\r\n\tmethod: string | undefined,\r\n\turl: string | undefined,\r\n\tskipChecker: SkipChecker,\r\n\treq?: any,\r\n\tres?: any,\r\n): void {\r\n\tif (!shouldLogRequest(method) || skipChecker(url)) return;\r\n\t$asai.$log(type, method, url);\r\n\tif (req && res && typeof $asai.appendAccessLog === 'function') {\r\n\t\tattachAccessLog($asai, req, res, type);\r\n\t}\r\n}\r\n\r\n/** 响应完成后写入 CLF + W3C 访问日志(需 status/bytes) */\r\nexport function attachAccessLog($asai: any, req: any, res: any, logType: string): void {\r\n\tif (res.__asaiAccessLogged) return;\r\n\tres.__asaiAccessLogged = true;\r\n\tconst onFinish = () => {\r\n\t\ttry {\r\n\t\t\tconst entry = buildAccessEntry(req, res, logType);\r\n\t\t\tvoid $asai.appendAccessLog(formatCLF(entry), formatW3CAccessRecord(entry));\r\n\t\t} catch {\r\n\t\t\t/* 访问日志写入失败不影响请求 */\r\n\t\t}\r\n\t};\r\n\tif (res.writableEnded || res.finished) onFinish();\r\n\telse res.once('finish', onFinish);\r\n}\r\n","/**\r\n * http/static.ts — 静态文件查找、缓存与响应(safe-path 防穿越 + ETag / SPA)\r\n */\r\nimport * as fs from 'fs';\r\nimport * as nodePath from 'path';\r\nimport { formatHttpError } from './log';\r\nimport { StaticPathCache } from './static-path-cache';\r\nimport { findExistingFileUnderRoots } from '../infra/safe-path';\r\nimport { buildStaticRoots, buildStaticSearchDirs } from './server-paths';\r\n\r\nconst STATIC_READ_MAX = 8 * 1024 * 1024;\r\n\r\nexport function parseUrlPath(requrl: string): string {\r\n try {\r\n if (!requrl) return '/';\r\n const safeUrl = requrl.startsWith('http') ? requrl : encodeURI(requrl);\r\n return new URL(safeUrl, 'http://localhost').pathname;\r\n } catch {\r\n return requrl;\r\n }\r\n}\r\n\r\nconst STATIC_ASSET_PREFIXES = ['/assets/', '/webmodel/', '/assets/entry/', '/assets/chunk/'];\r\n\r\nfunction isStaticAssetPath(urlPath: string, indexFile: string): boolean {\r\n const p = parseUrlPath(urlPath);\r\n const base = p.split('/').pop() || '';\r\n if (base === indexFile) return false;\r\n\r\n if (STATIC_ASSET_PREFIXES.some((prefix) => p.startsWith(prefix))) return true;\r\n return /\\.(css|js|mjs|cjs|json|png|jpe?g|gif|svg|ico|woff2?|ttf|map|wasm|zip)(\\?|$)/i.test(p);\r\n}\r\n\r\nfunction sendStaticBuffer(req: any, res: any, data: Buffer, mimeType: string, mtimeMs: number, $asai: any): void {\r\n const etag = `\"${data.length}-${mtimeMs}\"`;\r\n if (req.headers['if-none-match'] === etag) {\r\n res.writeHead(304);\r\n res.end();\r\n return;\r\n }\r\n try {\r\n res.writeHead(200, {\r\n 'Content-Type': mimeType,\r\n 'Content-Length': data.length,\r\n 'Cache-Control': 'public, max-age=3600',\r\n ETag: etag,\r\n 'Last-Modified': new Date(mtimeMs).toUTCString(),\r\n });\r\n res.end(data);\r\n } catch (err) {\r\n $asai.$log('HTTP', 'Static file response error:', formatHttpError(err));\r\n if (!res.headersSent) {\r\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Internal Server Error');\r\n }\r\n }\r\n}\r\n\r\nexport function serveStaticFile(req: any, res: any, foundPath: string, mimeType: string, stat: fs.Stats, $asai: any): void {\r\n if (stat.size <= STATIC_READ_MAX) {\r\n fs.readFile(foundPath, (err, data) => {\r\n if (err) {\r\n $asai.$log('HTTP', 'Static file read error:', formatHttpError(err));\r\n if (!res.headersSent) {\r\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Internal Server Error');\r\n }\r\n return;\r\n }\r\n sendStaticBuffer(req, res, data, mimeType, stat.mtimeMs, $asai);\r\n });\r\n return;\r\n }\r\n\r\n const readStream = fs.createReadStream(foundPath);\r\n const etag = `\"${stat.size}-${stat.mtimeMs}\"`;\r\n if (req.headers['if-none-match'] === etag) {\r\n readStream.destroy();\r\n res.writeHead(304);\r\n res.end();\r\n return;\r\n }\r\n\r\n readStream.on('error', (err) => {\r\n $asai.$log('STREAM', 'Stream error:', formatHttpError(err));\r\n if (!res.headersSent) {\r\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Internal Server Error');\r\n } else if (!res.writableEnded) res.destroy();\r\n });\r\n\r\n req.on('aborted', () => {\r\n if (!readStream.destroyed) readStream.destroy();\r\n });\r\n\r\n try {\r\n res.writeHead(200, {\r\n 'Content-Type': mimeType,\r\n 'Cache-Control': 'public, max-age=3600',\r\n ETag: etag,\r\n 'Last-Modified': stat.mtime.toUTCString(),\r\n });\r\n readStream.pipe(res);\r\n } catch (err) {\r\n $asai.$log('HTTP', 'Static file response error:', formatHttpError(err));\r\n if (!readStream.destroyed) readStream.destroy();\r\n if (!res.headersSent) {\r\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Internal Server Error');\r\n }\r\n }\r\n}\r\n\r\nexport interface StaticServeContext {\r\n hostcfg: any;\r\n hostdir: string;\r\n indexFile: string;\r\n $asai: any;\r\n staticPathCache: StaticPathCache;\r\n}\r\n\r\nexport function createStaticHandler(ctx: StaticServeContext): (req: any, res: any, url: string) => void {\r\n const { hostcfg, hostdir, indexFile, $asai, staticPathCache } = ctx;\r\n const hasRewrite = !!(hostcfg.weburls?.rewrite && hostcfg.weburls?.webdir && hostcfg.weburls?.keys?.length);\r\n const rewriteKeys: string[] = hasRewrite ? hostcfg.weburls?.keys || [] : [];\r\n\r\n const checkWebUrls = (rurl: string): boolean => {\r\n if (!hasRewrite || !rurl) return false;\r\n for (let i = 0; i < rewriteKeys.length; i++) {\r\n if (rurl.startsWith(rewriteKeys[i])) return true;\r\n }\r\n return false;\r\n };\r\n\r\n const showHostDirs = (\r\n req: any,\r\n res: any,\r\n rhostdirs: string[],\r\n rurl: string,\r\n primaryDirs: string[],\r\n rtm: number = 0,\r\n ): void => {\r\n const cleanUrl = parseUrlPath(rurl);\r\n const processedUrl = cleanUrl.endsWith('/') ? cleanUrl + indexFile : cleanUrl;\r\n const cacheKey = `${hostdir}:${rhostdirs.join('|')}:${processedUrl}`;\r\n const roots = rhostdirs.join('|') === primaryDirs.join('|')\r\n ? buildStaticRoots(primaryDirs, $asai)\r\n : buildStaticRoots(rhostdirs, $asai);\r\n\r\n const findValidFile = (urlPath: string): { filePath: string; stat: fs.Stats } | null => {\r\n const hit = staticPathCache.get(cacheKey);\r\n if (hit?.is404) return null;\r\n if (hit && !hit.is404) {\r\n const verified = staticPathCache.verify(hit);\r\n if (verified) return { filePath: hit.filePath, stat: verified };\r\n }\r\n\r\n const rel = urlPath.startsWith('/') ? urlPath.slice(1) : urlPath;\r\n const located = findExistingFileUnderRoots(rel, roots);\r\n if (located) {\r\n staticPathCache.setHit(cacheKey, located.filePath, located.stat.mtimeMs);\r\n return located;\r\n }\r\n\r\n staticPathCache.setMiss(cacheKey);\r\n return null;\r\n };\r\n\r\n const found = findValidFile(processedUrl);\r\n if (!found) {\r\n if (rtm > 0 || !hasRewrite || isStaticAssetPath(processedUrl, indexFile)) {\r\n res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('File not found!');\r\n return;\r\n }\r\n showHostDirs(req, res, [hostcfg.weburls!.webdir!], '/' + indexFile, primaryDirs, rtm + 1);\r\n return;\r\n }\r\n\r\n const mimeType = hostcfg.mimetypes?.[nodePath.extname(found.filePath)] || 'application/octet-stream';\r\n serveStaticFile(req, res, found.filePath, mimeType, found.stat, $asai);\r\n };\r\n\r\n return (req: any, res: any, url: string) => {\r\n res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');\r\n res.setHeader('Cross-Origin-Opener-Policy', 'cross-origin');\r\n\r\n const dirPath = buildStaticSearchDirs(hostcfg, $asai);\r\n if (!dirPath.length) {\r\n res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n res.end('Static root not configured');\r\n return;\r\n }\r\n\r\n if (checkWebUrls(url)) {\r\n showHostDirs(req, res, [hostcfg.weburls!.webdir!], '/' + indexFile, dirPath);\r\n } else {\r\n showHostDirs(req, res, dirPath, url, dirPath);\r\n }\r\n };\r\n}\r\n","/**\r\n * 路径安全 — 禁止目录穿越,仅允许落在白名单根目录内(OWASP Path Traversal)\r\n */\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\nexport function resolvePathUnderRoots(requestedPath: string, allowedRoots: string[]): string {\r\n\tif (!requestedPath || typeof requestedPath !== 'string') {\r\n\t\tthrow new Error('Invalid path');\r\n\t}\r\n\tif (requestedPath.includes('\\0')) {\r\n\t\tthrow new Error('Invalid path');\r\n\t}\r\n\r\n\tconst cleaned = requestedPath.replace(/\\\\/g, '/').trim();\r\n\tif (/^[a-zA-Z]:/.test(cleaned) || cleaned.startsWith('//')) {\r\n\t\tthrow new Error('Absolute paths are not allowed');\r\n\t}\r\n\r\n\tconst normalized = path.normalize(cleaned.replace(/^\\/+/, ''));\r\n\r\n\tfor (const root of allowedRoots) {\r\n\t\tif (!root) continue;\r\n\t\tconst absRoot = path.resolve(root);\r\n\t\tconst absTarget = path.resolve(absRoot, normalized);\r\n\t\tconst rel = path.relative(absRoot, absTarget);\r\n\t\tif (rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel))) {\r\n\t\t\treturn absTarget;\r\n\t\t}\r\n\t}\r\n\r\n\tthrow new Error('Path not allowed');\r\n}\r\n\r\n/** 在多个根目录中查找首个存在的文件(静态资源需遍历全部 hostdir) */\r\nexport function findExistingFileUnderRoots(\r\n\trequestedPath: string,\r\n\tallowedRoots: string[],\r\n): { filePath: string; stat: fs.Stats } | null {\r\n\tif (!requestedPath || typeof requestedPath !== 'string' || requestedPath.includes('\\0')) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst cleaned = requestedPath.replace(/\\\\/g, '/').trim();\r\n\tif (/^[a-zA-Z]:/.test(cleaned) || cleaned.startsWith('//')) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst normalized = path.normalize(cleaned.replace(/^\\/+/, ''));\r\n\r\n\tfor (const root of allowedRoots) {\r\n\t\tif (!root) continue;\r\n\t\ttry {\r\n\t\t\tconst absRoot = path.resolve(root);\r\n\t\t\tconst absTarget = path.resolve(absRoot, normalized);\r\n\t\t\tconst rel = path.relative(absRoot, absTarget);\r\n\t\t\tif (rel.startsWith('..') || path.isAbsolute(rel)) continue;\r\n\t\t\tconst stat = fs.statSync(absTarget);\r\n\t\t\tif (stat.isFile()) {\r\n\t\t\t\treturn { filePath: absTarget, stat };\r\n\t\t\t}\r\n\t\t} catch {\r\n\t\t\t/* try next root */\r\n\t\t}\r\n\t}\r\n\r\n\treturn null;\r\n}\r\n\r\n/** 从 hostconfig 推导允许读写的根目录 */\r\nexport function getHostAllowedRoots(hostconfig: any): string[] {\r\n\tconst roots = new Set<string>();\r\n\tconst push = (dir: unknown) => {\r\n\t\tif (typeof dir !== 'string' || !dir.trim()) return;\r\n\t\ttry {\r\n\t\t\tconst abs = path.resolve('./' + dir.replace(/\\\\/g, '/'));\r\n\t\t\tif (fs.existsSync(abs)) roots.add(abs);\r\n\t\t} catch {\r\n\t\t\t// skip invalid\r\n\t\t}\r\n\t};\r\n\tfor (const dir of hostconfig?.hostdirs || []) push(dir);\r\n\tpush('webdata');\r\n\tpush('websys');\r\n\tif (hostconfig?.weburls?.webdir) push(hostconfig.weburls.webdir);\r\n\tconst result: string[] = [];\r\n\troots.forEach((r) => result.push(r));\r\n\treturn result;\r\n}\r\n","/**\r\n * 静态资源根目录解析 — 兼容 pkg exe 嵌入资源 + exe/cwd 外挂目录\r\n * 基路径由 app.ts 注入 $asai.runtimeBaseDirs(见 src/utils/runtime-paths.ts)\r\n */\r\nimport * as fs from 'fs';\r\nimport * as nodePath from 'path';\r\n\r\n/** 静态 hostdirs 查找所用的全部基路径 */\r\nexport function getStaticBaseDirs($asai: any): string[] {\r\n const bases: string[] = [];\r\n const seen = new Set<string>();\r\n const add = (p: string | undefined) => {\r\n if (!p) return;\r\n const abs = nodePath.resolve(p);\r\n if (!seen.has(abs)) {\r\n seen.add(abs);\r\n bases.push(abs);\r\n }\r\n };\r\n\r\n if (Array.isArray($asai.runtimeBaseDirs)) {\r\n for (const b of $asai.runtimeBaseDirs) add(b);\r\n }\r\n if ($asai.serverRoot) add($asai.serverRoot);\r\n if ($asai.pkgSnapshotDir) add($asai.pkgSnapshotDir);\r\n\r\n return bases;\r\n}\r\n\r\n/** pkg 部署时 webclient 可能仅存在于 snapshot,不能依赖磁盘 stat */\r\nfunction shouldForceHostdirs($asai: any): boolean {\r\n if ($asai.pkgSnapshotDir) return true;\r\n return $asai.hostconfig?.pkg?.type === 1;\r\n}\r\n\r\nexport function buildStaticSearchDirs(hostcfg: any, $asai: any): string[] {\r\n const bases = getStaticBaseDirs($asai);\r\n const ordered: string[] = [];\r\n const seen = new Set<string>();\r\n\r\n const pushDir = (dir: string) => {\r\n if (!dir || seen.has(dir)) return;\r\n if (shouldForceHostdirs($asai)) {\r\n seen.add(dir);\r\n ordered.push(dir);\r\n return;\r\n }\r\n for (const base of bases) {\r\n try {\r\n if (fs.statSync(nodePath.resolve(base, dir)).isDirectory()) {\r\n seen.add(dir);\r\n ordered.push(dir);\r\n return;\r\n }\r\n } catch {\r\n /* try next base */\r\n }\r\n }\r\n };\r\n\r\n for (const dir of hostcfg.hostdirs || []) pushDir(dir);\r\n if (hostcfg.weburls?.webdir) pushDir(hostcfg.weburls.webdir);\r\n return ordered;\r\n}\r\n\r\nexport function buildStaticRoots(dirs: string[], $asai: any): string[] {\r\n const bases = getStaticBaseDirs($asai);\r\n const roots: string[] = [];\r\n const seen = new Set<string>();\r\n for (const base of bases) {\r\n for (const d of dirs) {\r\n const abs = nodePath.resolve(base, d);\r\n if (!seen.has(abs)) {\r\n seen.add(abs);\r\n roots.push(abs);\r\n }\r\n }\r\n }\r\n return roots;\r\n}\r\n","/**\n * http-connection.ts — HTTP 连接数监控与限流(ckhttp=1 时启用,与 v1 一致)\n */\n\n/** 注册连接监控:超 80% 告警、超 95% 清理空闲连接、达 maxhttp 上限拒绝新连接 */\nexport function setupHttpConnectionMonitor($asai: any, hostdir: string, server: any, hostcfg: any): void {\n\tconst maxHttp = hostcfg.maxhttp || 100;\n\tconst monitorInterval = setInterval(() => {\n\t\tconst connCount = $asai.connectionshttp[hostdir]?.size || 0;\n\t\tif (connCount > maxHttp * 0.8) {\n\t\t\t$asai.$log('HTTP', `HTTP Connection HIGH (${connCount}/${maxHttp})`);\n\t\t}\n\t\tif (connCount > maxHttp * 0.95) {\n\t\t\t$asai.$log('HTTP', 'HTTP Connection CRITICAL! Forcing cleanup');\n\t\t\tif ($asai.connectionshttp[hostdir]) {\n\t\t\t\t$asai.connectionshttp[hostdir].forEach((conn: any) => {\n\t\t\t\t\tif (conn._idleTime && Date.now() - conn._idleTime > 300000) {\n\t\t\t\t\t\tconn.destroy();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}, 300000);\n\n\tif (!$asai.tasksws[hostdir]) $asai.tasksws[hostdir] = {};\n\t$asai.tasksws[hostdir].httpMonitor = monitorInterval;\n\n\tserver.on('connection', (connection: any) => {\n\t\tif (!$asai.connectionshttp[hostdir]) {\n\t\t\t$asai.connectionshttp[hostdir] = new Set();\n\t\t}\n\t\tconst connCount = $asai.connectionshttp[hostdir].size;\n\t\tif (connCount >= maxHttp) {\n\t\t\ttry {\n\t\t\t\t$asai.$log('HTTP', `HTTP Connection MAX rejected (${connCount}/${maxHttp})`);\n\t\t\t\tconnection.destroy();\n\t\t\t} catch (err) {\n\t\t\t\t$asai.$log('HTTP', 'Close connection error:', err);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t$asai.connectionshttp[hostdir].add(connection);\n\t\tconnection.on('close', () => {\n\t\t\t$asai.connectionshttp[hostdir].delete(connection);\n\t\t});\n\t\tconnection.setTimeout(300000);\n\t});\n}\n","/**\r\n * port-release.ts — 启动前/冲突时释放占用端口(调试与部署均生效)\r\n */\r\nimport { execSync } from 'node:child_process';\r\nimport process from 'node:process';\r\nimport { validateHostdir, getHostCFG, getProxyHostCFG } from '../core/host-config';\r\n\r\nconst OWN_PID = process.pid;\r\n\r\nfunction sleepMs(ms: number): void {\r\n\tconst deadline = Date.now() + ms;\r\n\twhile (Date.now() < deadline) {\r\n\t\t/* 等待 OS 释放端口 */\r\n\t}\r\n}\r\n\r\n/** 查找监听指定端口的进程 PID(不含当前进程) */\r\nexport function findListeningPids(port: number): number[] {\r\n\tif (!Number.isInteger(port) || port < 1 || port > 65535) return [];\r\n\ttry {\r\n\t\tif (process.platform === 'win32') {\r\n\t\t\tconst out = execSync(`netstat -ano | findstr /R /C:\":${port} \"`, {\r\n\t\t\t\tencoding: 'utf8',\r\n\t\t\t\tstdio: ['pipe', 'pipe', 'ignore'],\r\n\t\t\t});\r\n\t\t\tconst pids = new Set<number>();\r\n\t\t\tfor (const line of out.split(/\\r?\\n/)) {\r\n\t\t\t\tconst parts = line.trim().split(/\\s+/);\r\n\t\t\t\tif (parts.length < 5 || parts[3] !== 'LISTENING') continue;\r\n\t\t\t\tconst localAddr = parts[1] || '';\r\n\t\t\t\tconst portMatch = localAddr.match(/:(\\d+)$/);\r\n\t\t\t\tconst pid = parseInt(parts[parts.length - 1]!, 10);\r\n\t\t\t\tif (portMatch && parseInt(portMatch[1]!, 10) === port && pid > 0) {\r\n\t\t\t\t\tpids.add(pid);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn [...pids];\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tconst out = execSync(`lsof -nP -iTCP:${port} -sTCP:LISTEN -t`, {\r\n\t\t\t\tencoding: 'utf8',\r\n\t\t\t\tstdio: ['pipe', 'pipe', 'ignore'],\r\n\t\t\t});\r\n\t\t\treturn out\r\n\t\t\t\t.split(/\\r?\\n/)\r\n\t\t\t\t.map((s) => parseInt(s.trim(), 10))\r\n\t\t\t\t.filter((n) => n > 0);\r\n\t\t} catch {\r\n\t\t\treturn [];\r\n\t\t}\r\n\t} catch {\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\nfunction killPid(pid: number): boolean {\r\n\tif (!pid || pid === OWN_PID || pid <= 4) return false;\r\n\ttry {\r\n\t\tif (process.platform === 'win32') {\r\n\t\t\texecSync(`taskkill /PID ${pid} /F`, { stdio: 'ignore' });\r\n\t\t} else {\r\n\t\t\texecSync(`kill -9 ${pid}`, { stdio: 'ignore' });\r\n\t\t}\r\n\t\treturn true;\r\n\t} catch {\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/** 结束占用端口的进程;成功释放或原本空闲则返回 true */\r\nexport function releasePort(\r\n\tport: number,\r\n\topts?: { excludePid?: number; label?: string },\r\n): boolean {\r\n\tconst exclude = opts?.excludePid ?? OWN_PID;\r\n\tconst occupants = findListeningPids(port).filter((p) => p !== exclude && p !== OWN_PID);\r\n\tif (!occupants.length) return true;\r\n\r\n\tconst label = opts?.label ? `[${opts.label}] ` : '';\r\n\tconsole.warn(`[AsaiHostNodejs] ${label}端口 ${port} 被占用,正在结束进程: ${occupants.join(', ')}`);\r\n\tfor (const pid of occupants) {\r\n\t\tkillPid(pid);\r\n\t}\r\n\tsleepMs(500);\r\n\r\n\tconst remaining = findListeningPids(port).filter((p) => p !== exclude && p !== OWN_PID);\r\n\treturn remaining.length === 0;\r\n}\r\n\r\n/** 收集本次启动将监听的端口 */\r\nexport function collectStartupPorts($asai: any): number[] {\r\n\tconst ports = new Set<number>();\r\n\tconst hosts = $asai.hostconfig?.hosts;\r\n\tif (hosts) {\r\n\t\tfor (const el of Object.keys(hosts)) {\r\n\t\t\tif (el === 'default') continue;\r\n\t\t\tif (el !== 'asai' && !validateHostdir(el)) continue;\r\n\t\t\tconst cfg = getHostCFG(el, $asai);\r\n\t\t\tif (cfg?.close) continue;\r\n\t\t\tif (cfg?.port) ports.add(Number(cfg.port));\r\n\t\t}\r\n\t\t// default 仅作模板,不单独监听;端口由合并后的具名站点承担\r\n\t}\r\n\tconst proxyhosts = $asai.hostconfig?.proxyhosts;\r\n\tif (proxyhosts) {\r\n\t\tfor (const el of Object.keys(proxyhosts)) {\r\n\t\t\tif (el === 'default') continue;\r\n\t\t\tif (!validateHostdir(el)) continue;\r\n\t\t\tconst cfg = getProxyHostCFG(el, $asai);\r\n\t\t\tif (cfg?.proxyport) ports.add(Number(cfg.proxyport));\r\n\t\t}\r\n\t}\r\n\treturn [...ports];\r\n}\r\n\r\n/** 启动前批量释放配置端口上的残留进程 */\r\nexport function releaseConfiguredPorts($asai: any): void {\r\n\tfor (const port of collectStartupPorts($asai)) {\r\n\t\treleasePort(port, { excludePid: process.pid });\r\n\t}\r\n}\r\n","/**\r\n * proxy-server.ts — 反向代理服务\r\n *\r\n * 将外部请求转发到 proxyhosts 配置的目标地址。\r\n * 性能:Agent 按 proxyhostdir 复用,避免每请求 new Agent 导致连接无法 keepAlive。\r\n */\r\nimport { getProxyHostCFG, getHostIP, getNowTime } from '../core';\r\nimport { getHTTPServer, getHttpUserinfo } from '../http/server';\r\nimport { releasePort } from '../infra/port-release';\r\n\r\n/** 代理响应中需跳过的 hop-by-hop 头 */\r\nconst PROXY_SKIP_HEADERS = new Set([\r\n 'transfer-encoding', 'connection', 'keep-alive',\r\n 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'upgrade',\r\n]);\r\n\r\nexport function startProxyServer($asai: any, proxyhostdir: string): void {\r\n const proxycfg = getProxyHostCFG(proxyhostdir, $asai);\r\n if (!proxycfg.url) return;\r\n if ($asai.serversproxy?.[proxyhostdir]) return;\r\n\r\n try {\r\n const httpServer = getHTTPServer(proxycfg.proxyhttptype, proxycfg, $asai);\r\n const targetHttp = getHTTPServer(proxycfg.url!, proxycfg, $asai);\r\n // 目标地址只解析一次,每请求仅拼接 path\r\n const targetBaseUrl = new URL(proxycfg.url!);\r\n const isHttpsTarget = targetBaseUrl.protocol === 'https:';\r\n const defaultTargetPort = isHttpsTarget ? 443 : 80;\r\n\r\n // Agent 复用:同一代理实例共享连接池\r\n const sharedAgent = new targetHttp.Agent({\r\n keepAlive: proxycfg.keepAlive ?? true,\r\n timeout: proxycfg.timeout ?? 60000,\r\n keepAliveMsecs: proxycfg.keepAliveMsecs ?? 30000,\r\n maxSockets: proxycfg.maxSockets ?? 1000,\r\n maxFreeSockets: proxycfg.maxFreeSockets ?? 100,\r\n rejectUnauthorized: proxycfg.rejectUnauthorized ?? false,\r\n secureProtocol: proxycfg.secureProtocol ?? 'TLS_method',\r\n });\r\n\r\n const proxyServer = (httpServer as any).AsCreateServer((req: any, res: any) => {\r\n if (proxycfg.redirect) {\r\n res.writeHead(301, {\r\n Location: proxycfg.url + req.url,\r\n 'Strict-Transport-Security': 'max-age=31536000',\r\n });\r\n res.end();\r\n return;\r\n }\r\n\r\n const targetUrl = new URL(req.url || '/', targetBaseUrl);\r\n\r\n // [安全] 转发前剥离 hop-by-hop 头(RFC 7230),仅传递端到端头,\r\n // 避免连接复用异常与请求走私风险\r\n const forwardHeaders: Record<string, any> = {};\r\n for (const key of Object.keys(req.headers)) {\r\n if (!PROXY_SKIP_HEADERS.has(key.toLowerCase())) {\r\n forwardHeaders[key] = req.headers[key];\r\n }\r\n }\r\n\r\n const reqParams: any = {\r\n agent: sharedAgent,\r\n method: req.method,\r\n hostname: targetUrl.hostname,\r\n port: targetUrl.port || defaultTargetPort,\r\n path: targetUrl.pathname + targetUrl.search,\r\n headers: forwardHeaders,\r\n };\r\n if (isHttpsTarget) {\r\n reqParams.servername = targetUrl.hostname;\r\n }\r\n\r\n // [优化] 增加 passUserInfo 配置开关(默认关闭),避免透传用户信息给第三方服务\r\n const passUserInfo = proxycfg.passUserInfo ?? false;\r\n\r\n const forwardRequest = targetHttp.request(reqParams, (forwardRes: any) => {\r\n Object.keys(forwardRes.headers).forEach((key) => {\r\n if (!PROXY_SKIP_HEADERS.has(key.toLowerCase())) {\r\n res.setHeader(key, forwardRes.headers[key]!);\r\n }\r\n });\r\n res.statusCode = forwardRes.statusCode!;\r\n if (passUserInfo) {\r\n const userinfo = getHttpUserinfo(req, $asai);\r\n if (userinfo) res.setHeader('Userinfo', Array.isArray(userinfo) ? userinfo.join('##') : userinfo);\r\n }\r\n forwardRes.pipe(res, { end: true });\r\n });\r\n\r\n req.pipe(forwardRequest, { end: true });\r\n\r\n req.on('error', (err: any) => {\r\n $asai.$log('PROXY', 'Client request error:', err);\r\n forwardRequest.destroy();\r\n });\r\n\r\n forwardRequest.on('error', (err: Error) => {\r\n $asai.$log('PROXY', 'Forward request error:', err);\r\n $asai.$log('PROXY', `Target: ${targetUrl.href}, HTTPS: ${isHttpsTarget}`);\r\n if (!res.headersSent) {\r\n res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n }\r\n res.end('Bad Gateway: ' + err.message);\r\n });\r\n\r\n forwardRequest.setTimeout(120000, () => {\r\n $asai.$log('PROXY', 'Forward request timeout');\r\n forwardRequest.destroy();\r\n if (!res.headersSent) {\r\n res.writeHead(504, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n }\r\n res.end('Gateway Timeout');\r\n });\r\n });\r\n\r\n proxyServer.on('error', (err: any) => {\r\n if (err.code === 'EADDRINUSE') {\r\n $asai.$log('PROXY', `\\x1B[41mPort ${proxycfg.proxyport} is already start!\\x1B[0m`);\r\n delete $asai.serversproxy?.[proxyhostdir];\r\n const released = releasePort(proxycfg.proxyport, {\r\n excludePid: process.pid,\r\n label: proxyhostdir,\r\n });\r\n if (released) {\r\n console.warn(`[AsaiHostNodejs] 代理端口 ${proxycfg.proxyport} 已释放,正在重新启动 [${proxyhostdir}]`);\r\n setTimeout(() => startProxyServer($asai, proxyhostdir), $asai.hostconfig.tm?.d || 2000);\r\n }\r\n } else {\r\n $asai.$log('PROXY', 'Proxy server error:', err);\r\n }\r\n });\r\n\r\n if (!$asai.serversproxy) $asai.serversproxy = {};\r\n $asai.serversproxy[proxyhostdir] = proxyServer;\r\n\r\n releasePort(proxycfg.proxyport, { excludePid: process.pid, label: proxyhostdir });\r\n\r\n const listenIp = getHostIP(proxycfg.proxyip, $asai);\r\n const listenCallback = () => {\r\n console.log(`[${proxyhostdir}] Start At ${getNowTime()}.`);\r\n console.log(`\\x1B[45;28mProxy Server ${proxycfg.proxyhttptype}${listenIp || 'localhost'}:${proxycfg.proxyport}\\x1B[0m`);\r\n console.log(`\\x1B[46;28mTarget Server ${proxycfg.url}\\x1B[0m`);\r\n console.log(`================================================`);\r\n };\r\n\r\n if (listenIp) {\r\n proxyServer.listen(proxycfg.proxyport, listenIp, listenCallback);\r\n } else {\r\n proxyServer.listen(proxycfg.proxyport, listenCallback);\r\n }\r\n } catch (err) {\r\n $asai.$log('PROXY', 'Proxy server error:', JSON.stringify(err));\r\n }\r\n}\r\n","export { deUserInfoWithAsai } from './userinfo';\r\nexport { wsMock } from './ws-mock';\r\n","/** WebSocket Mock — api 单次响应 / listen 定时推送 */\r\nexport function wsMock($asai: any) {\r\n\tfunction getKeyByData(reqdata: any, hostdir?: string) {\r\n\t\treturn '_wstask_' + (hostdir || '') + '_' + (reqdata?.id || reqdata?.ty + '.' + reqdata?.ac);\r\n\t}\r\n\r\n\tfunction getMockDb(workopt: any) {\r\n\t\tconst { reqdata, mockdata } = workopt;\r\n\t\tconst wsfn = mockdata?.fn ? $asai.asaimock.fn?.[mockdata.fn] : null;\r\n\t\tif (wsfn) return wsfn({ workopt, $asai, mockName: mockdata.fn });\r\n\t\treturn { ...reqdata, ...(mockdata || {}) };\r\n\t}\r\n\r\n\tfunction wsWorkApi(workopt: any) {\r\n\t\t$asai.serversws[workopt.hostdir]?.sendws?.(workopt.reqdataisobj ? getMockDb(workopt) : workopt.reqdata, 0, workopt.ws);\r\n\t}\r\n\r\n\tfunction wsWorkListen(workopt: any, reqkey: any) {\r\n\t\tif (workopt.reqdata?.off) {\r\n\t\t\tif ($asai.tasksws[workopt.hostdir][reqkey]) {\r\n\t\t\t\tclearInterval($asai.tasksws[workopt.hostdir][reqkey]);\r\n\t\t\t\t$asai.tasksws[workopt.hostdir][reqkey] = null;\r\n\t\t\t}\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif ($asai.tasksws[workopt.hostdir][reqkey]) return;\r\n\r\n\t\tconst newDataMock = getMockDb(workopt);\r\n\t\t$asai.tasksws[workopt.hostdir][reqkey] = setInterval(() => {\r\n\t\t\tconst newData = { ...getMockDb(workopt), tm: Date.now() };\r\n\t\t\t$asai.serversws[workopt.hostdir].sendws(newData, newData.pb || 2, workopt.ws);\r\n\t\t\tif (!$asai.tasksws[workopt.hostdir][reqkey]) {\r\n\t\t\t\tclearInterval($asai.tasksws[workopt.hostdir][reqkey]);\r\n\t\t\t}\r\n\t\t}, newDataMock?.tc || 2000);\r\n\r\n\t\tworkopt.ws?.once?.('close', () => {\r\n\t\t\tif ($asai.tasksws[workopt.hostdir]?.[reqkey]) {\r\n\t\t\t\tclearInterval($asai.tasksws[workopt.hostdir][reqkey]);\r\n\t\t\t\tdelete $asai.tasksws[workopt.hostdir][reqkey];\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tfunction wsWorkMock(workopt: any) {\r\n\t\tworkopt.mockdata = (workopt.reqdataisobj && $asai.asaimock?.db?.[workopt.hostdir]?.[workopt.reqdata?.ty]) || {};\r\n\t\tif (workopt.mockdata?.wc) {\r\n\t\t\twsWorkListen(workopt, getKeyByData(workopt.reqdata, workopt.hostdir));\r\n\t\t} else {\r\n\t\t\twsWorkApi(workopt);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { getKeyByData, wsWorkApi, wsWorkMock, wsWorkListen, getMockDb };\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 1 / CR 2 — 服务端权威用户等级(禁止信任客户端 Userinfo 中的 lv)\r\n */\r\nexport interface ServerUserSnapshot {\r\n\tus: string;\r\n\tlv: number;\r\n\tstatus: string;\r\n}\r\n\r\n/** 从 userStore 加载真实 lv/status,覆盖客户端可伪造的 Userinfo[1] */\r\nexport async function attachServerUserLevel(req: any, $asai: any): Promise<void> {\r\n\tconst userinfo = req?.Userinfo;\r\n\tif (!Array.isArray(userinfo) || !userinfo[0]) return;\r\n\tconst us = String(userinfo[0]);\r\n\ttry {\r\n\t\tconst { createUserStore } = await import('../sysserver/api/login/store/user-store');\r\n\t\tconst user = await createUserStore($asai).findByUsername(us);\r\n\t\tif (user && user.status === 'active') {\r\n\t\t\treq._serverUser = { us: user.us, lv: user.lv, status: user.status } satisfies ServerUserSnapshot;\r\n\t\t\treq.Userinfo[1] = String(user.lv);\r\n\t\t} else {\r\n\t\t\treq._serverUser = null;\r\n\t\t}\r\n\t} catch {\r\n\t\treq._serverUser = null;\r\n\t}\r\n}\r\n\r\nexport function getRequestUserLevel(req: any): number {\r\n\tif (req?._serverUser?.lv != null) return Number(req._serverUser.lv);\r\n\tconst n = Number(req?.Userinfo?.[1] ?? -1);\r\n\treturn Number.isFinite(n) ? n : -1;\r\n}\r\n\r\nexport function getRequestUsername(req: any): string | undefined {\r\n\tif (req?._serverUser?.us) return String(req._serverUser.us);\r\n\tconst us = req?.Userinfo?.[0];\r\n\treturn us ? String(us) : undefined;\r\n}\r\n","/**\r\n * IEC 62443-4-2 CR 1 / CR 2 — 可选 HTTP 鉴权与访问控制\r\n * 默认关闭(requireAuth=0),不影响现有未鉴权 API 行为。\r\n */\r\nimport { logSecurityEvent, getClientIp } from './security-audit';\r\nimport { attachServerUserLevel, getRequestUserLevel } from './user-auth';\r\n\r\nexport interface AuthCheckResult {\r\n\tok: boolean;\r\n\tcode?: number;\r\n\tmessage?: string;\r\n}\r\n\r\nfunction getSecurityConfig($asai: any): Record<string, unknown> {\r\n\treturn ($asai?.hostconfig?.security as Record<string, unknown>) || {};\r\n}\r\n\r\nfunction pathMatchesPattern(path: string, pattern: string): boolean {\r\n\tif (pattern.endsWith('*')) {\r\n\t\treturn path.startsWith(pattern.slice(0, -1));\r\n\t}\r\n\treturn path === pattern;\r\n}\r\n\r\n/** 路径是否在 authSkipPaths 白名单内 */\r\nexport function isAuthSkipped($asai: any, pathname: string): boolean {\r\n\tconst sec = getSecurityConfig($asai);\r\n\tconst skipPaths = (sec.authSkipPaths as string[]) || [\r\n\t\t'/api/asailog/*',\r\n\t\t'/api/sys/errorcodes/*',\r\n\t\t'/api/user/login/auth/*',\r\n\t\t'/api/user/login/register/*',\r\n\t\t'/sys/info/*',\r\n\t\t'/jsonp/*',\r\n\t];\r\n\treturn skipPaths.some((p) => pathMatchesPattern(pathname, p));\r\n}\r\n\r\nexport function isAuthRequired($asai: any, pathname: string): boolean {\r\n\tconst sec = getSecurityConfig($asai);\r\n\tif (!sec.requireAuth) return false;\r\n\tif (isAuthSkipped($asai, pathname)) return false;\r\n\treturn true;\r\n}\r\n\r\nfunction parseUserLevel(level: unknown): number {\r\n\tconst n = Number(level);\r\n\treturn Number.isFinite(n) ? n : -1;\r\n}\r\n\r\n/** 校验 Userinfo 头(us##lv##tk),仅在 requireAuth=1 时由路由层调用 */\r\nexport function validateHttpAuth(req: any, $asai: any, pathname: string): AuthCheckResult {\r\n\tif (!isAuthRequired($asai, pathname)) {\r\n\t\treturn { ok: true };\r\n\t}\r\n\r\n\tconst userinfo = req?.Userinfo;\r\n\tconst ip = getClientIp(req);\r\n\r\n\tif (!Array.isArray(userinfo) || userinfo.length < 3 || !userinfo[0]) {\r\n\t\tlogSecurityEvent($asai, {\r\n\t\t\ttype: 'AUTH_MISSING',\r\n\t\t\tpath: pathname,\r\n\t\t\tmethod: req?.method,\r\n\t\t\tip,\r\n\t\t\tdetail: 'Userinfo header missing or invalid',\r\n\t\t});\r\n\t\treturn { ok: false, code: 401, message: 'Authentication required' };\r\n\t}\r\n\r\n\tconst [us] = userinfo;\r\n\tconst sec = getSecurityConfig($asai);\r\n\tconst minLevel = typeof sec.minUserLevel === 'number' ? sec.minUserLevel : 0;\r\n\tconst userLevel = getRequestUserLevel(req);\r\n\r\n\tif (userLevel < minLevel) {\r\n\t\tlogSecurityEvent($asai, {\r\n\t\t\ttype: 'ACCESS_DENIED',\r\n\t\t\tpath: pathname,\r\n\t\t\tmethod: req?.method,\r\n\t\t\tuser: String(us),\r\n\t\t\tlevel: userLevel,\r\n\t\t\tip,\r\n\t\t\tdetail: `minLevel=${minLevel}`,\r\n\t\t});\r\n\t\treturn { ok: false, code: 403, message: 'Insufficient privileges' };\r\n\t}\r\n\r\n\treturn { ok: true };\r\n}\r\n\r\n/** 鉴权前附加服务端权威 lv(CR 2.1) */\r\nexport async function validateHttpAuthAsync(req: any, $asai: any, pathname: string): Promise<AuthCheckResult> {\r\n\tif (Array.isArray(req?.Userinfo) && req.Userinfo[0]) {\r\n\t\tawait attachServerUserLevel(req, $asai);\r\n\t\tif (!req._serverUser && isAuthRequired($asai, pathname)) {\r\n\t\t\tlogSecurityEvent($asai, {\r\n\t\t\t\ttype: 'ACCESS_DENIED',\r\n\t\t\t\tpath: pathname,\r\n\t\t\t\tmethod: req?.method,\r\n\t\t\t\tuser: String(req.Userinfo[0]),\r\n\t\t\t\tip: getClientIp(req),\r\n\t\t\t\tdetail: 'User not found or inactive',\r\n\t\t\t});\r\n\t\t\treturn { ok: false, code: 403, message: 'Invalid user session' };\r\n\t\t}\r\n\t}\r\n\treturn validateHttpAuth(req, $asai, pathname);\r\n}\r\n\r\nexport function sendAuthError(res: any, result: AuthCheckResult): void {\r\n\tres.writeHead(result.code || 401, { 'Content-Type': 'application/json; charset=utf-8' });\r\n\tres.end(JSON.stringify({ error: result.message || 'Unauthorized' }));\r\n}\r\n","/**\n * hosts.default / hosts.<site> 连接与 CORS 参数解析\n * 对应 asaihost.json: ws, ckhttp, ckws, close, maxhttp, maxws, maxonline, oncors\n */\n\nexport interface HostSiteLimits {\n\tclose: boolean;\n\tws: boolean;\n\tckhttp: boolean;\n\tckws: boolean;\n\toncors: boolean;\n\tmaxhttp: number;\n\tmaxws: number;\n\tmaxonline: number;\n}\n\nexport function flagOn(value: unknown): boolean {\n\treturn value === 1 || value === true;\n}\n\n/** 解析合并后的站点配置(getHostCFG 结果) */\nexport function resolveHostSiteLimits(hostcfg: Record<string, unknown> | null | undefined): HostSiteLimits {\n\tconst cfg = hostcfg || {};\n\treturn {\n\t\tclose: flagOn(cfg.close),\n\t\tws: flagOn(cfg.ws),\n\t\tckhttp: flagOn(cfg.ckhttp),\n\t\tckws: flagOn(cfg.ckws),\n\t\toncors: flagOn(cfg.oncors),\n\t\tmaxhttp: positiveInt(cfg.maxhttp, 2000),\n\t\tmaxws: positiveInt(cfg.maxws, 2000),\n\t\tmaxonline: positiveInt(cfg.maxonline, 100),\n\t};\n}\n\nfunction positiveInt(value: unknown, fallback: number): number {\n\tconst n = Number(value);\n\treturn Number.isInteger(n) && n > 0 ? n : fallback;\n}\n\n/** 启动前为 hosts.default 填充缺省值 */\nexport function normalizeHostSiteDefaults(host: Record<string, unknown>): void {\n\tif (host.close == null) host.close = 0;\n\tif (host.ws == null) host.ws = 0;\n\tif (host.ckhttp == null) host.ckhttp = 0;\n\tif (host.ckws == null) host.ckws = 0;\n\tif (host.oncors == null) host.oncors = 0;\n\tif (host.maxhttp == null) host.maxhttp = 2000;\n\tif (host.maxws == null) host.maxws = 2000;\n\tif (host.maxonline == null) host.maxonline = 100;\n\tif (!Array.isArray(host.cors)) host.cors = [];\n}\n\n/** 严格 CORS:oncors=1 时校验 cors 白名单 */\nexport function resolveApiCorsOrigin(\n\treq: { headers?: Record<string, string | string[] | undefined> },\n\thostcfg: Record<string, unknown> | null | undefined,\n\tgetHeader: (req: unknown, key: string) => string,\n): string | null {\n\tconst limits = resolveHostSiteLimits(hostcfg);\n\tif (!limits.oncors) return '*';\n\n\tlet origin = getHeader(req, 'Origin');\n\tif (!origin) {\n\t\tconst referer = getHeader(req, 'Referer');\n\t\tif (referer) {\n\t\t\ttry {\n\t\t\t\torigin = new URL(referer).origin;\n\t\t\t} catch {\n\t\t\t\tconst parts = referer.split('/');\n\t\t\t\tif (parts.length >= 3) origin = `${parts[0]}//${parts[2]}`;\n\t\t\t}\n\t\t}\n\t}\n\treturn origin || null;\n}\n\nexport function isApiCorsAllowed(\n\torigin: string | null,\n\thostcfg: Record<string, unknown> | null | undefined,\n\thostHeader: string,\n): boolean {\n\tif (!origin) return false;\n\tif (origin === '*') return true;\n\tconst corsList = hostcfg?.cors;\n\tif (!Array.isArray(corsList) || !corsList.length) return true;\n\tif (corsList.includes(origin)) return true;\n\tif (hostHeader && origin.includes(hostHeader)) return true;\n\treturn false;\n}\n","/**\n * Api.ts — HTTP API 路由分发\n * /api/* 请求经 CORS 校验后,按 hostserverapis 前缀匹配到对应插件处理器。\n */\nimport { validateHttpAuthAsync, sendAuthError } from '../../infra/access-control';\nimport { acquireApiSlot, releaseApiSlot } from '../../infra/connection-quota';\nimport { isApiCorsAllowed, resolveApiCorsOrigin } from '../../infra/host-limits';\nimport { getClientIp } from '../../infra/security-audit';\n\n/** 同步挂载 data/end 监听,避免 await 鉴权期间请求体被丢弃 */\nfunction readRequestBody(req: any, maxBody: number): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let received = 0;\n let settled = false;\n const finish = (err: Error | null, data?: string) => {\n if (settled) return;\n settled = true;\n if (err) reject(err);\n else resolve(data ?? '');\n };\n req.on('data', (chunk: Buffer) => {\n if (settled) return;\n received += chunk.length;\n if (received > maxBody) {\n req.destroy();\n finish(new Error('PAYLOAD_TOO_LARGE'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => finish(null, Buffer.concat(chunks).toString('utf8')));\n req.on('error', (err: Error) => finish(err));\n });\n}\n\nfunction processPostPayload($asai: any, req: any, postdata: string, pm: string): { postdata: any; pm: string; isAes: boolean } {\n let isAes = false;\n let out = postdata;\n if ($asai.$lib.aesfns && out?.startsWith?.('{\"aes\":')) {\n isAes = true;\n const aesData: any = JSON.parse(out);\n out = $asai.$lib.aesfns.reqAES({ data: aesData });\n if (aesData?.aes === 2 && typeof out === 'string') {\n try {\n out = JSON.parse(out);\n } catch {\n /* keep string */\n }\n }\n }\n const plainJson = typeof out === 'string' && out.trimStart().startsWith('{');\n if (req?.Userinfo?.[2] && !plainJson) {\n pm = req.Userinfo[2];\n out = $asai.$lib.AsCode.asdecode(out, pm);\n }\n return { postdata: out, pm, isAes };\n}\n\nexport default ($asai: any, opt: any = {}) => {\n opt?.fn?.($asai);\n\n // 统一头信息获取\n function getHeader(req: any, key: string): string {\n return req.headers[key.toLowerCase()] || '';\n }\n /** API 路由表缓存(hostserverapis 启动后不变) */\n let apiRouteCache: { key: string; path: string }[] | null = null;\n let apiRouteCacheLen = -1;\n\n function findApiHandler($asai: any, pathname: string) {\n const apis = $asai.hostserverapis;\n if (!apis?.length) return undefined;\n if (!apiRouteCache || apiRouteCacheLen !== apis.length) {\n apiRouteCache = apis.map((elp: string) => ({ key: elp, path: `/api/${elp}` }));\n apiRouteCacheLen = apis.length;\n }\n if (!apiRouteCache) return undefined;\n for (let i = 0; i < apiRouteCache.length; i++) {\n const route = apiRouteCache[i];\n if (pathname === route.path || pathname.startsWith(route.path)) {\n return route.key;\n }\n }\n return undefined;\n }\n // 统一错误响应\n function sendError(res: any, code: number, message: string) {\n res.writeHead(code, {\n 'Content-Type': 'application/json; charset=utf-8',\n });\n res.end(JSON.stringify({ error: message }));\n }\n function apiWork(req: any, res: any, hostdir: string) {\n const hostcfg: any = $asai.getHost(hostdir);\n const origin = resolveApiCorsOrigin(req, hostcfg, getHeader);\n const host: any = getHeader(req, 'Host');\n if (isApiCorsAllowed(origin, hostcfg, host)) {\n res.setHeader('Access-Control-Allow-Origin', origin === '*' ? '*' : origin!);\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type,userinfo,authorization,x-file-name');\n\n // 处理预检请求\n if (req.method === 'OPTIONS') {\n res.statusCode = 204;\n return res.end();\n }\n let pm: string = '';\n let isAes: boolean = false;\n let urlParse: any, pathname: string, query: any;\n // try {\n // urlParse = url.parse(req.url, true);\n // pathname = urlParse.pathname;\n // query = urlParse.query;\n // } catch (err) {\n urlParse = new URL(req.url, `http://${getHeader(req, 'Host')}`);\n pathname = urlParse.pathname;\n if ($asai.$lib.aesfns && urlParse.search.startsWith('?aes=')) {\n isAes = true;\n urlParse.search = $asai.$lib.aesfns.reqAES({ data: JSON.parse(decodeURIComponent(urlParse.search.substring(5))) });\n }\n if (urlParse.search.startsWith('?pm=')) {\n query = {\n pm: decodeURIComponent(urlParse.search.substring(4)),\n };\n if (req.url.indexOf('binary') === -1) {\n // pm是路由上面解密\n if (req?.Userinfo && req?.Userinfo[2] && query?.pm) {\n pm = req.Userinfo[2];\n // 解密get加密的请求\n query = $asai.$lib.AsCode.asdecode(query?.pm, pm);\n query = Object.fromEntries(new URLSearchParams('?' + query).entries());\n }\n }\n } else {\n query = Object.fromEntries(new URLSearchParams(urlParse.search).entries());\n }\n // }\n // $asai.hostconfig.logger?.lv?.view && console.log(`\\x1B[45m${pathname}\\x1B[0m`, query);\n\n const apiHandlerKey = findApiHandler($asai, pathname);\n if (!apiHandlerKey) {\n return sendError(res, 404, 'Not Found');\n }\n const clientIp = getClientIp(req);\n const apiSlot = acquireApiSlot($asai, hostdir, clientIp);\n if (!apiSlot.ok) {\n return sendError(res, apiSlot.code || 429, apiSlot.message || 'Quota exceeded');\n }\n const releaseSlot = () => releaseApiSlot(hostdir, clientIp);\n res.once('finish', releaseSlot);\n res.once('close', releaseSlot);\n\n const maxBody = $asai.hostconfig?.maxbody || 100 * 1024 * 1024;\n const isTextPost = req.method === 'POST' && req.url.indexOf('binary') === -1;\n const bodyPromise = isTextPost ? readRequestBody(req, maxBody) : null;\n\n void (async () => {\n let authResult: { ok: boolean };\n let rawBody = '';\n try {\n [authResult, rawBody] = await Promise.all([\n validateHttpAuthAsync(req, $asai, pathname),\n bodyPromise ?? Promise.resolve(''),\n ]);\n } catch (err: any) {\n releaseSlot();\n if (err?.message === 'PAYLOAD_TOO_LARGE') {\n return sendError(res, 413, 'Payload Too Large');\n }\n return sendError(res, 400, err?.message || 'Bad Request');\n }\n if (!authResult.ok) {\n releaseSlot();\n return sendAuthError(res, authResult);\n }\n // 获取处理器\n let apiFn: any = $asai.hostserverapi[apiHandlerKey]?.($asai, query);\n if (!apiFn) {\n return sendError(res, 501, 'Not Implemented');\n }\n // 设置通用响应头\n res.setHeader('Content-Type', 'application/json; charset=utf-8');\n\n $asai.$log('API', req.method, urlParse.pathname, query);\n // 处理地址栏上带的数据qrdata\n let qrdata: any;\n let postdata: any;\n if (req.url.indexOf('binary') === -1) {\n qrdata = query;\n if (req.method === 'POST') {\n try {\n const processed = processPostPayload($asai, req, rawBody, pm);\n postdata = processed.postdata;\n pm = processed.pm;\n isAes = processed.isAes;\n } catch {\n return sendError(res, 400, 'AES decrypt failed');\n }\n if (apiFn?.post && typeof apiFn?.post === 'function') {\n const optTmp: any = { qrdata, data: postdata, pm };\n if (isAes || $asai.$lib.aesfns?.allaes) {\n optTmp.resAES = $asai.$lib.aesfns?.resAES;\n }\n apiFn.post(req, res, hostdir, optTmp);\n } else {\n res.end(typeof postdata === 'string' ? postdata : JSON.stringify(postdata ?? ''));\n }\n } else if (req.method === 'GET') {\n // GET请求分发阶段\n if (apiFn?.get && typeof apiFn?.get === 'function') {\n // 保持有qrdata\n const optTmp: any = { qrdata, data: qrdata, pm };\n // ----aes----0061\n if (isAes || $asai.$lib.aesfns?.allaes) {\n optTmp.resAES = $asai.$lib.aesfns?.resAES;\n }\n // ----aes----0062\n apiFn.get(req, res, hostdir, optTmp);\n } else {\n res.end(JSON.stringify(qrdata));\n }\n }\n } else {\n // 二进制接口\n if (Object.keys(query)?.length) {\n qrdata = query;\n }\n if (req.method === 'POST') {\n $asai.$lib.AsNodeTool.upBinary(req)\n .then((postdata: any) => {\n // POST请求分发阶段\n if (apiFn?.post && typeof apiFn?.post === 'function') {\n apiFn.post(req, res, hostdir, {\n qrdata,\n data: postdata,\n });\n } else {\n res.end(postdata);\n }\n })\n .catch((err: any) => {\n return sendError(res, 400, 'Invalid content type');\n });\n }\n }\n })();\n } else {\n $asai.$log('API', req.method, req.url);\n }\n }\n\n return { apiWork };\n};","/**\r\n * Ws.ts — WebSocket 消息路由\r\n * 按 reqdata.ty 前缀匹配 hostserverwss 中的处理器;ping 快速回复 pong。\r\n */\r\nimport { ensureWsRouteIndex } from '../../infra/registry';\r\n\r\nexport default ($asai: any, opt: any = {}) => {\r\n opt?.fn?.($asai);\r\n\r\n /** WS 处理器实例缓存(插件注册后不变,避免每条消息重复 factory 调用) */\r\n const wsHandlerCache = new Map<string, any>();\r\n const routeIndex = ensureWsRouteIndex($asai);\r\n\r\n function getWsHandler(handlerKey: string) {\r\n if (!wsHandlerCache.has(handlerKey)) {\r\n wsHandlerCache.set(handlerKey, $asai.hostserverws[handlerKey]?.($asai));\r\n }\r\n return wsHandlerCache.get(handlerKey);\r\n }\r\n\r\n // 消息解析逻辑抽离为独立函数\r\n function parseMessage(msg: any) {\r\n if (Buffer.isBuffer(msg)) {\r\n msg = msg.toString();\r\n }\r\n if (msg === 'ping') {\r\n } else if (typeof msg === 'string') {\r\n try {\r\n msg = JSON.parse(msg);\r\n } catch (err) {}\r\n }\r\n return _getMessage(msg);\r\n }\r\n\r\n // WebSocket 消息处理器\r\n function wsWork(msg: any, ws: any, hostdir: string, req: any) {\r\n try {\r\n let reqdata = parseMessage(msg);\r\n // console.debug('[WS] Received message', req.Userinfo, reqdata);\r\n let handlerKey: string | undefined;\r\n if (reqdata === 'ping') {\r\n // ping 直接回复 pong,不经过 handlers 处理\r\n ws.send?.('pong');\r\n return;\r\n } else {\r\n const reqdataisobj: boolean = typeof reqdata === 'object' && reqdata !== null;\r\n handlerKey = reqdataisobj\r\n ? routeIndex.matchTy(reqdata?.ty)\r\n : routeIndex.matchString(reqdata);\r\n // 兼容:索引未命中时回退旧逻辑\r\n if (!handlerKey && $asai.hostserverwss?.length) {\r\n handlerKey = $asai.hostserverwss.find((elp: string) => {\r\n if (reqdataisobj) {\r\n return reqdata?.ty?.startsWith(elp);\r\n }\r\n return typeof reqdata === 'string' && reqdata.startsWith(elp);\r\n });\r\n }\r\n // mock数据处理逻辑\r\n if (!handlerKey) {\r\n $asai.asaimock?.wsWorkMock({\r\n msg,\r\n ws,\r\n hostdir,\r\n req,\r\n reqdataisobj,\r\n reqdata,\r\n });\r\n return;\r\n }\r\n }\r\n if (!handlerKey) return;\r\n getWsHandler(handlerKey)?.work?.(reqdata, ws, hostdir, req);\r\n } catch (err) {\r\n ($asai.$log || console.error)?.('WS', 'handler error', err instanceof Error ? err.message : err);\r\n }\r\n }\r\n function _getMessage(msg: any) {\r\n if (msg?.db?.aes && $asai.$lib?.aesfns?.reqAES) {\r\n msg.db = $asai.$lib.aesfns.reqAES({ data: msg.db });\r\n }\r\n return msg;\r\n }\r\n\r\n // command 方法 - 初始化通信命令配置\r\n function commandwork($asai: any) {\r\n // 初始化 command 配置\r\n if (!$asai.command) {\r\n $asai.command = {\r\n commandconfig: {\r\n clientws: {},\r\n },\r\n };\r\n }\r\n return {\r\n commandwork: () => {\r\n // 通信命令工作逻辑(占位)\r\n const log = $asai.$log || console.log;\r\n log('WS', 'Command work initialized');\r\n },\r\n };\r\n }\r\n\r\n return { wsWork, commandwork };\r\n};\r\n","/**\r\n * Sys.ts — /sys/* 系统路由分发\r\n */\r\nimport { validateHttpAuthAsync, sendAuthError } from '../../infra/access-control';\r\n\r\nexport default ($asai: any, opt: any = {}) => {\r\n opt?.fn?.($asai);\r\n\r\n let sysRouteCache: { key: string; route: string }[] | null = null;\r\n let sysRouteCacheLen = -1;\r\n\r\n function findSystemHandler(req: any): any {\r\n const routes = $asai.hostserversyss;\r\n if (!routes?.length) return undefined;\r\n if (!sysRouteCache || sysRouteCacheLen !== routes.length) {\r\n sysRouteCache = routes.map((elp: string) => ({ key: elp, route: `/${elp}` }));\r\n sysRouteCacheLen = routes.length;\r\n }\r\n if (!sysRouteCache) return undefined;\r\n const url = req.url || '';\r\n for (let i = 0; i < sysRouteCache.length; i++) {\r\n const item = sysRouteCache[i];\r\n if (url.startsWith(item.route) && $asai.hostserversys[item.key]) {\r\n return item.key;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n // 统一错误响应\r\n const sendError = (res: any, code: number, message: string) => {\r\n res.writeHead(code, {\r\n 'Content-Type': 'application/json; charset=utf-8',\r\n });\r\n res.end(JSON.stringify({ error: message }));\r\n };\r\n function sysWork(req: any, res: any, hostdir: string) {\r\n // 查找匹配的路由\r\n const handlerKey = findSystemHandler(req);\r\n\r\n if (!handlerKey) {\r\n return sendError(res, 404, 'Not Found');\r\n }\r\n\r\n const urlPath = (req.url || '').split('?')[0];\r\n void (async () => {\r\n const authResult = await validateHttpAuthAsync(req, $asai, urlPath);\r\n if (!authResult.ok) {\r\n return sendAuthError(res, authResult);\r\n }\r\n\r\n // 初始化处理器\r\n const handler = $asai.hostserversys[handlerKey]?.($asai);\r\n if (!handler) {\r\n return sendError(res, 500, 'Handler Initialization Failed');\r\n }\r\n\r\n if (handler?.show && typeof handler?.show === 'function') {\r\n handler.show(req, res, hostdir);\r\n } else {\r\n res.end('postdata');\r\n }\r\n if (!handler) {\r\n res.writeHead(404, {\r\n 'Content-Type': 'application/json; charset=utf-8',\r\n });\r\n res.end(req.url);\r\n } else {\r\n // sysFn = null;// 异步不适用!!\r\n }\r\n })();\r\n }\r\n\r\n return { sysWork };\r\n};","export default ($asai: any, wsname: string) => {\r\n if (!$asai?.clientws) {\r\n $asai.clientws = {};\r\n }\r\n if (!$asai.clientws[wsname]) {\r\n $asai.clientws[wsname] = { tasks: new Map() };\r\n }\r\n function getKeyByData(msgdata: any): string {\r\n return msgdata?.id || msgdata?.ty;\r\n }\r\n function clientwsInit() {\r\n return new Promise((resolve: any, reject: any) => {\r\n $asai.clientws[wsname].socket = new $asai.asaiWs(\r\n $asai.command.commandconfig.clientws[wsname]\r\n );\r\n\r\n $asai.clientws[wsname].socket.onmessage = (event: any) => {\r\n clientwsOnmessage(event.data);\r\n };\r\n\r\n $asai.clientws[wsname].socket.on('error', (err: any) => {\r\n $asai.clientws[wsname].open = 0;\r\n $asai.hostconfig.logger?.lv?.view &&\r\n console.error(\r\n 666.2203,\r\n `${wsname}=${$asai.command.commandconfig.clientws[wsname]} is error.`,\r\n err\r\n );\r\n reject();\r\n });\r\n\r\n $asai.clientws[wsname].socket.on('close', () => {\r\n $asai.clientws[wsname].open = 0;\r\n $asai.hostconfig.logger?.lv?.view &&\r\n console.error(\r\n 666.2205,\r\n `${wsname}=${$asai.command.commandconfig.clientws[wsname]} is close.`\r\n );\r\n reject();\r\n });\r\n\r\n $asai.clientws[wsname].socket.onopen = () => {\r\n $asai.hostconfig.logger?.lv?.view &&\r\n console.log(\r\n 666.2201,\r\n `${wsname}=${$asai.command.commandconfig.clientws[wsname]} is open.`\r\n );\r\n $asai.clientws[wsname].open = 1;\r\n resolve();\r\n };\r\n });\r\n }\r\n\r\n function clientwsSend(message: string) {\r\n if ($asai.clientws[wsname].open) {\r\n $asai.clientws[wsname].socket.send(message);\r\n }\r\n }\r\n function clientwsOnmessage(message: string) {\r\n if ($asai.clientws[wsname].open) {\r\n try {\r\n const messageData: any = JSON.parse(message);\r\n const key: string = getKeyByData(messageData);\r\n const task = $asai.clientws[wsname].tasks.get(key);\r\n if (task) {\r\n task?.callback(messageData);\r\n if (messageData.ty && !messageData.id) {\r\n // watch\r\n } else {\r\n $asai.clientws[wsname].tasks.delete(key);\r\n }\r\n }\r\n } catch (e) {}\r\n }\r\n }\r\n function clientwsApi(messageData: any) {\r\n return new Promise((resolve, reject) => {\r\n if ($asai.clientws[wsname].open) {\r\n try {\r\n const taskOpt: any = {};\r\n taskOpt.timestamp = Date.now();\r\n if (!messageData.id) {\r\n messageData.id = $asai.$lib.As.Uuid('nd');\r\n }\r\n $asai.clientws[wsname].tasks.set(\r\n getKeyByData(messageData),\r\n {\r\n callback: (res: any) => {\r\n resolve(res);\r\n },\r\n ...messageData,\r\n ...taskOpt,\r\n }\r\n );\r\n clientwsSend(JSON.stringify(messageData));\r\n } catch (err) {\r\n reject(err);\r\n }\r\n }\r\n });\r\n }\r\n function clientwsWatch(messageData: any, cb: any) {\r\n if ($asai.clientws[wsname].open) {\r\n try {\r\n $asai.clientws[wsname].tasks.set(getKeyByData(messageData), {\r\n callback: (res: any) => {\r\n cb(res);\r\n },\r\n ...messageData,\r\n });\r\n clientwsSend(JSON.stringify(messageData));\r\n } catch (err) {}\r\n }\r\n }\r\n function clientwsWatchOff(messageData: any) {\r\n if (messageData?.ty === 'clear') {\r\n $asai.clientws[wsname].tasks = new Map();\r\n // $asai.clientws[wsname].tasks.clear();\r\n } else {\r\n const key: string = getKeyByData(messageData);\r\n const task = $asai.clientws[wsname].tasks.get(key);\r\n if (task) {\r\n $asai.clientws[wsname].tasks.delete(key);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n clientwsInit,\r\n clientwsSend,\r\n clientwsApi,\r\n clientwsWatch,\r\n clientwsWatchOff,\r\n };\r\n};","import ServerApi from './server/Api';\r\nimport ServerWs from './server/Ws';\r\nimport ServerSys from './server/Sys';\r\nimport WsClient from './server/WsClient';\r\n\r\nexport default {\r\n ServerApi,\r\n ServerWs,\r\n ServerSys,\r\n WsClient,\r\n};\r\n","export default ($asai: any) => {\r\n function work(msgdata: any, ws: any, hostdir: string, req: any) {\r\n $asai.serversws[hostdir].sendws('pong', 0, ws);\r\n }\r\n return { work };\r\n};\r\n","export default ($asai: any) => {\r\n // 消息广播模式\r\n function chatBoard(msgdata: any, ws: any, hostdir: string, req: any) {\r\n let room: string;\r\n if (msgdata.db?.room && typeof msgdata.db.room === 'string') {\r\n room = msgdata.db.room;\r\n delete msgdata.db.room;\r\n } else {\r\n room = 'asai';\r\n }\r\n if (!$asai.$ws.chat.rooms[room]) {\r\n $asai.$ws.chat.rooms[room] = JSON.parse($asai.$ws.chat.temp);\r\n }\r\n $asai.$ws.chat.rooms[room].db.push(msgdata.db);\r\n $asai.$lib.As.throttle(() => {\r\n msgdata.ty = msgdata.ty.slice(0, -4) + 'broadcast';\r\n msgdata.db = $asai.$ws.chat.rooms[room].db;\r\n delete msgdata.id;\r\n $asai.$log(666.702, 'broadcast', msgdata);\r\n $asai.serversws[hostdir].sendws(msgdata, 2, ws);\r\n $asai.$ws.chat.rooms[room].db = [];\r\n }, $asai.$ws.chat.rooms[room].tm);\r\n }\r\n function work(msgdata: any, ws: any, hostdir: string, req: any) {\r\n if (msgdata.ty.endsWith('send')) {\r\n // 进入消息广播模式\r\n chatBoard(msgdata, ws, hostdir, req);\r\n // 告诉发送者,消息已收到\r\n $asai.serversws[hostdir].sendws(\r\n { id: msgdata.id, db: 1 },\r\n 0,\r\n ws\r\n );\r\n }\r\n $asai.$log('CHAT', 'get send', msgdata);\r\n }\r\n return { work };\r\n};\r\n","import ping from \"./common/ping\";\r\nimport chatWeb from \"./chat/web\";\r\n\r\nexport default {\r\n ping,\r\n \"chat/web\": chatWeb,\r\n};\r\n","import fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { attachServerUserLevel, getRequestUserLevel } from \"../../../infra/user-auth\";\r\nimport { getPermissionThreshold } from \"../login/service/user-level-config\";\r\nimport { isLogStoreEnabled, prefersDiskLogAccess } from \"../../lib/common/log-db\";\r\nimport {\r\n groupsToManageChildren,\r\n listUnifiedGroups,\r\n purgeStoreEntriesForFile,\r\n readWebLogFromStore,\r\n} from \"../../lib/common/LogStore\";\r\n\r\nasync function ensureLv(req: any, $asai: any, min: number): Promise<boolean> {\r\n await attachServerUserLevel(req, $asai);\r\n return getRequestUserLevel(req) >= min;\r\n}\r\n\r\nexport default ($asai: any) => {\r\n const {\r\n ensureFile,\r\n pathExists,\r\n readLogDir,\r\n removeFile,\r\n resolvePathUnderBase,\r\n } = $asai.$lib.AsFs;\r\n const { sendSuccess, sendFail, mnLog } = $asai.$lib?.reqWork?.($asai);\r\n\r\n function mgLog(...arg: any) {\r\n mnLog(\"LOG\", ...arg);\r\n }\r\n\r\n /**\r\n * 获取日志目录路径\r\n */\r\n function getDir(opt: any): string {\r\n let tmpDir: string = opt.qrdata?.dir || opt.data?.dir;\r\n if (tmpDir) {\r\n tmpDir = decodeURIComponent(tmpDir);\r\n } else {\r\n tmpDir = opt.qrdata?.ty || opt.data?.ty;\r\n if (tmpDir) {\r\n tmpDir = decodeURIComponent(tmpDir);\r\n if (tmpDir === \"access-clf\" || tmpDir === \"access-w3c\") {\r\n tmpDir = $asai.hostconfig.logger?.path?.access || \"\";\r\n } else {\r\n tmpDir = $asai.hostconfig.logger?.path?.[tmpDir] || \"\";\r\n }\r\n } else {\r\n tmpDir = $asai.hostconfig.logger?.path?.client || \"\";\r\n }\r\n }\r\n return tmpDir;\r\n }\r\n\r\n /**\r\n * 处理 POST 请求\r\n */\r\n async function post(req: any, res: any, hostdir: string, opt: any) {\r\n const url = req.url;\r\n // ---------- 添加客户端日志 /api/asailog/manage/addclient/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/addclient/\")) {\r\n try {\r\n await $asai.$log(1, opt.data);\r\n sendSuccess(res, \"ok\", opt);\r\n } catch (err) {\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n\r\n // ---------- 添加服务器日志 /api/asailog/manage/add/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/add/\")) {\r\n if (!(await ensureLv(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n mgLog(\"add\", \"server:\", opt.data);\r\n await $asai.$log(\"LOG\", \"ADD\", opt.data);\r\n sendSuccess(res, \"ok\", opt);\r\n } catch (err) {\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n\r\n // ---------- 更新日志文件 /api/asailog/manage/update/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/update/\")) {\r\n if (!(await ensureLv(req, $asai, 3))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const baseDir = getDir(opt);\r\n const relPath = decodeURIComponent(opt.qrdata?.path || opt.data?.path);\r\n const jsonpath = resolvePathUnderBase(baseDir, relPath);\r\n await ensureFile(jsonpath);\r\n mgLog(\"ENSURE\", jsonpath);\r\n const content =\r\n typeof opt.data === \"string\" ? opt.data : String(opt.data ?? \"\");\r\n await fs.writeFile(jsonpath, content, \"utf8\");\r\n mgLog(\"UPDATE\", jsonpath);\r\n sendSuccess(res, jsonpath, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"update\", err);\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n }\r\n\r\n /**\r\n * 处理 GET 请求\r\n */\r\n async function get(req: any, res: any, hostdir: string, opt: any) {\r\n const url = req.url;\r\n\r\n // ---------- 列出日志目录 /api/asailog/manage/selectlist/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/selectlist/\")) {\r\n if (!(await ensureLv(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const ty = decodeURIComponent(opt.qrdata?.ty || opt.data?.ty || \"client\");\r\n if (!prefersDiskLogAccess($asai) && isLogStoreEnabled($asai) && (ty === \"client\" || ty === \"server\" || ty === \"sec\")) {\r\n const kind = ty === \"sec\" ? \"sec\" : \"web\";\r\n const groups = await listUnifiedGroups($asai, { kind: kind as any, source: ty === \"sec\" ? \"sec\" : ty });\r\n const children = groupsToManageChildren(groups);\r\n if (children.length) {\r\n mgLog(\"LIST\", `store:${ty}`, children.length);\r\n return sendSuccess(res, { children, fromStore: true }, opt);\r\n }\r\n }\r\n const dir = path.resolve(getDir(opt));\r\n if (!dir) {\r\n mgLog(\"MISS\", \"dir not configured\");\r\n return sendFail(res, \"no exist!\", opt);\r\n }\r\n mgLog(\"LIST\", dir);\r\n const files = await readLogDir(dir);\r\n mgLog(\"READ\", `${files.children.length} items`);\r\n sendSuccess(res, files, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"selectlist\", err);\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n\r\n // ---------- 读取日志文件 /api/asailog/manage/select/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/select/\")) {\r\n if (!(await ensureLv(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const ty = decodeURIComponent(opt.qrdata?.ty || opt.data?.ty || \"client\");\r\n const relPath = decodeURIComponent(opt.qrdata?.path || opt.data?.path);\r\n if (!prefersDiskLogAccess($asai) && isLogStoreEnabled($asai) && (ty === \"client\" || ty === \"server\" || ty === \"sec\")) {\r\n const data = await readWebLogFromStore($asai, ty, relPath);\r\n if (data) {\r\n mgLog(\"READ\", `store:${ty}/${relPath}`);\r\n return sendSuccess(res, data, opt);\r\n }\r\n }\r\n const baseDir = getDir(opt);\r\n const filepath = resolvePathUnderBase(baseDir, relPath);\r\n const exists = await pathExists(filepath);\r\n if (!exists) {\r\n mgLog(\"MISS\", filepath);\r\n return sendFail(res, \"no exist!\", opt);\r\n }\r\n mgLog(\"READ\", filepath);\r\n const data = await fs.readFile(filepath, \"utf8\");\r\n sendSuccess(res, data, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"select\", err);\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n\r\n // ---------- 删除日志文件 /api/asailog/manage/delete/ ----------\r\n if (url.startsWith(\"/api/asailog/manage/delete/\")) {\r\n if (!(await ensureLv(req, $asai, 3))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const baseDir = getDir(opt);\r\n const relPath = decodeURIComponent(opt.qrdata?.path || opt.data?.path);\r\n const fileName = relPath.split(/[/\\\\]/).pop() || relPath;\r\n if (isLogStoreEnabled($asai)) {\r\n await purgeStoreEntriesForFile($asai, fileName).catch(() => undefined);\r\n }\r\n const filepath = resolvePathUnderBase(baseDir, relPath);\r\n mgLog(\"DELETE\", filepath);\r\n await removeFile(filepath);\r\n mgLog(\"DELETE\", \" completed\");\r\n sendSuccess(res, filepath, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"delete\", err);\r\n sendFail(res, err, opt);\r\n }\r\n return;\r\n }\r\n }\r\n\r\n return { post, get };\r\n};\r\n","/**\r\n * SIEM 只读 Token — 外部 SOC 拉取日志(search/export/compliance),不可删除/归档\r\n */\r\nimport { attachServerUserLevel, getRequestUserLevel } from './user-auth';\r\n\r\nexport function isSiemEnabled($asai: any): boolean {\r\n\tconst cfg = $asai?.hostconfig?.logger?.siem;\r\n\treturn !!(cfg?.enabled && getSiemToken($asai));\r\n}\r\n\r\nexport function getSiemToken($asai: any): string {\r\n\tconst fromEnv = process.env.ASAI_SIEM_TOKEN;\r\n\tif (typeof fromEnv === 'string' && fromEnv.trim()) return fromEnv.trim();\r\n\tconst fromCfg = $asai?.hostconfig?.logger?.siem?.token;\r\n\treturn typeof fromCfg === 'string' ? fromCfg.trim() : '';\r\n}\r\n\r\nexport function isSiemTokenValid($asai: any, req: any): boolean {\r\n\tif (!isSiemEnabled($asai)) return false;\r\n\tconst expected = getSiemToken($asai);\r\n\tif (!expected) return false;\r\n\tconst header = req?.headers?.['x-siem-token'] || req?.headers?.['x-api-key'];\r\n\tif (typeof header === 'string' && header === expected) return true;\r\n\tconst q = req?.query || {};\r\n\tconst qToken = q.siem_token || q.token;\r\n\treturn typeof qToken === 'string' && qToken === expected;\r\n}\r\n\r\nexport type LogAccessMode = 'siem' | 'user' | false;\r\n\r\n/** 读操作:SIEM Token 等效 lv≥2;写/删操作禁止 SIEM */\r\nexport async function ensureLogReadAccess(req: any, $asai: any, minLv = 2): Promise<LogAccessMode> {\r\n\tif (isSiemTokenValid($asai, req)) return 'siem';\r\n\tawait attachServerUserLevel(req, $asai);\r\n\treturn getRequestUserLevel(req) >= minLv ? 'user' : false;\r\n}\r\n\r\nexport async function ensureLogWriteAccess(req: any, $asai: any, minLv: number): Promise<boolean> {\r\n\tif (isSiemTokenValid($asai, req)) return false;\r\n\tawait attachServerUserLevel(req, $asai);\r\n\treturn getRequestUserLevel(req) >= minLv;\r\n}\r\n","/**\r\n * IEC 62443-4-2 干预日志管理 API — asailog/intervention\r\n * 只读查询对 lv>=2 开放,删除操作对 lv>=3 开放并强制留存期校验(见 InterventionLog.deleteInterventionFile)。\r\n * 不提供\"任意写入\"接口:日志只能由业务代码在真实干预发生时通过 $asai.$lib.InterventionLog.logIntervention 自动写入。\r\n *\r\n * ns 参数(可选,默认 'prod'):切换查看命名空间。'prod' 为受5年留存保护的生产日志(默认,\r\n * 保持既有行为不变);'test' 为 testkdd/testlog 等演示/自动化测试触发动作的隔离存储,\r\n * 用于在不触碰生产留存证据的前提下验证日志引擎全部功能(列表/查看/链校验/删除留存策略)。\r\n */\r\nimport { attachServerUserLevel, getRequestUserLevel, getRequestUsername } from '../../../infra/user-auth';\r\nimport { ensureLogReadAccess, ensureLogWriteAccess } from '../../../infra/siem-auth';\r\nimport { getPermissionThreshold } from '../login/service/user-level-config';\r\nimport { isLogStoreEnabled, prefersDiskLogAccess } from '../../lib/common/log-db';\r\nimport { groupsToInterventionFiles, listUnifiedGroups } from '../../lib/common/LogStore';\r\n\r\nfunction getNs(raw: any): \"prod\" | \"test\" {\r\n return raw === \"test\" ? \"test\" : \"prod\";\r\n}\r\n\r\nasync function ensureServerUser(req: any, $asai: any): Promise<void> {\r\n if (Array.isArray(req?.Userinfo) && req.Userinfo[0]) {\r\n await attachServerUserLevel(req, $asai);\r\n }\r\n}\r\n\r\nexport default ($asai: any) => {\r\n const { sendSuccess, sendFail } = $asai.$lib?.reqWork?.($asai) || {};\r\n const IL = $asai.$lib.InterventionLog;\r\n\r\n async function get(req: any, res: any, hostdir: string, opt: any) {\r\n const url = req.url || \"\";\r\n\r\n if (url.startsWith(\"/api/asailog/intervention/selectlist/\")) {\r\n if (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const ns = getNs(opt.qrdata?.ns || opt.data?.ns);\r\n let list = await IL.listInterventionFiles($asai, ns);\r\n if (isLogStoreEnabled($asai) && !prefersDiskLogAccess($asai)) {\r\n const groups = await listUnifiedGroups($asai, { kind: 'intervention', ns });\r\n const fromStore = groupsToInterventionFiles(groups, ns);\r\n const names = new Set(list.map((f: any) => f.name));\r\n for (const f of fromStore) {\r\n if (!names.has(f.name)) list.push(f);\r\n }\r\n }\r\n return sendSuccess(res, { ns, files: list }, opt);\r\n } catch (err: any) {\r\n return sendFail(res, err?.message || err, opt);\r\n }\r\n }\r\n\r\n if (url.startsWith(\"/api/asailog/intervention/select/\")) {\r\n if (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n const name = decodeURIComponent(opt.qrdata?.name || opt.data?.name || \"\");\r\n const ns = getNs(opt.qrdata?.ns || opt.data?.ns);\r\n if (!name) return sendFail(res, \"name required\", opt);\r\n const content = await IL.readInterventionFile($asai, name, ns);\r\n return sendSuccess(res, { ns, ...content }, opt);\r\n } catch (err: any) {\r\n return sendFail(res, err?.message || err, opt);\r\n }\r\n }\r\n\r\n if (url.startsWith(\"/api/asailog/intervention/types/\")) {\r\n if (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, \"Forbidden\", opt);\r\n try {\r\n return sendSuccess(res, IL.getInterventionTaxonomy($asai), opt);\r\n } catch (err: any) {\r\n return sendFail(res, err?.message || err, opt);\r\n }\r\n }\r\n }\r\n\r\n async function post(req: any, res: any, hostdir: string, opt: any) {\r\n const url = req.url || \"\";\r\n\r\n if (url.startsWith(\"/api/asailog/intervention/delete/\")) {\r\n if (!(await ensureLogWriteAccess(req, $asai, getPermissionThreshold($asai, 'adminWrite')))) return sendFail(res, \"Forbidden\", opt);\r\n await ensureServerUser(req, $asai);\r\n const lv = getRequestUserLevel(req);\r\n const us = getRequestUsername(req);\r\n try {\r\n const body = typeof opt.data === \"string\" ? JSON.parse(opt.data || \"{}\") : opt.data || {};\r\n const name = String(body.name || \"\");\r\n const ns = getNs(body.ns);\r\n if (!name) return sendFail(res, \"name required\", opt);\r\n const result = await IL.deleteInterventionFile(\r\n $asai,\r\n name,\r\n {\r\n us: us ? String(us) : undefined,\r\n lv,\r\n reason: body.reason ? String(body.reason).slice(0, 256) : undefined,\r\n force: !!body.force,\r\n },\r\n ns,\r\n );\r\n return sendSuccess(res, { ns, ...result }, opt);\r\n } catch (err: any) {\r\n return sendFail(res, err?.message || err, opt);\r\n }\r\n }\r\n }\r\n\r\n return { get, post };\r\n};\r\n","/**\r\n * IEC 62443-4-2 统一日志 API — /api/asailog/store/*\r\n */\r\nimport { ensureLogReadAccess, ensureLogWriteAccess } from '../../../infra/siem-auth';\r\nimport { getPermissionThreshold } from '../login/service/user-level-config';\r\nimport { getRequestUsername } from '../../../infra/user-auth';\r\nimport {\r\n\tgetUnifiedEntry,\r\n\tgetUnifiedStats,\r\n\tlistUnifiedGroups,\r\n\tqueryUnifiedLogs,\r\n\treadWebLogFromStore,\r\n\tgroupsToInterventionFiles,\r\n\tgroupsToManageChildren,\r\n\tsearchUnifiedLogs,\r\n\texportLogContent,\r\n\tgetComplianceReport,\r\n\tarchiveInterventionYear,\r\n} from '../../lib/common/LogStore';\r\nimport { getLogStoreConfig, getLogStoreMeta, getEffectiveStoreType, isLogStoreEnabled } from '../../lib/common/log-db';\r\nimport type { LogKind } from '../../lib/common/log-db';\r\n\r\nfunction parseQuery(opt: any): Record<string, string> {\r\n\tconst q = opt.qrdata || opt.data || {};\r\n\tconst out: Record<string, string> = {};\r\n\tfor (const [k, v] of Object.entries(q)) {\r\n\t\tif (v != null && v !== '') out[k] = String(v);\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nfunction parseBody(opt: any): Record<string, unknown> {\r\n\tif (!opt?.data) return {};\r\n\tif (typeof opt.data === 'string') {\r\n\t\ttry { return JSON.parse(opt.data); } catch { return {}; }\r\n\t}\r\n\treturn typeof opt.data === 'object' ? opt.data : {};\r\n}\r\n\r\nexport default ($asai: any) => {\r\n\tconst { sendSuccess, sendFail } = $asai.$lib?.reqWork?.($asai) || {};\r\n\tconst IL = $asai.$lib.InterventionLog;\r\n\r\n\tasync function get(req: any, res: any, hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tconst q = parseQuery(opt);\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/config/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\treturn sendSuccess(res, getLogStoreMeta($asai), opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/stats/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\tif (!isLogStoreEnabled($asai)) {\r\n\t\t\t\treturn sendSuccess(res, { store: 'disabled', message: 'logger.store not configured', config: getLogStoreMeta($asai) }, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst storeType = getEffectiveStoreType($asai);\r\n\t\t\t\tconst stats = await getUnifiedStats($asai);\r\n\t\t\t\treturn sendSuccess(res, { store: storeType, stats, config: getLogStoreMeta($asai) }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/compliance/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst ns = q.ns === 'test' ? 'test' : 'prod';\r\n\t\t\t\tconst report = await getComplianceReport($asai, ns);\r\n\t\t\t\treturn sendSuccess(res, report, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/search/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\tif (!isLogStoreEnabled($asai)) return sendFail(res, 'Log store not enabled', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst result = await searchUnifiedLogs($asai, {\r\n\t\t\t\t\tkind: q.kind ? (q.kind as LogKind) : undefined,\r\n\t\t\t\t\tns: q.ns ? (q.ns as 'prod' | 'test' | '') : undefined,\r\n\t\t\t\t\tsource: q.source || q.ty || undefined,\r\n\t\t\t\t\tkeyword: q.keyword || q.q || undefined,\r\n\t\t\t\t\tevent_type: q.event_type || undefined,\r\n\t\t\t\t\tseverity_min: q.severity_min != null ? Number(q.severity_min) : undefined,\r\n\t\t\t\t\tdate_from: q.date_from || undefined,\r\n\t\t\t\t\tdate_to: q.date_to || undefined,\r\n\t\t\t\t\toutcome: q.outcome || undefined,\r\n\t\t\t\t\tlimit: q.limit != null ? Number(q.limit) : 200,\r\n\t\t\t\t\toffset: q.offset != null ? Number(q.offset) : 0,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, result, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/export/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst kind = (q.kind || 'intervention') as LogKind | 'intervention';\r\n\t\t\t\tconst format = (q.format || 'raw') as 'cef' | 'raw' | 'json';\r\n\t\t\t\tconst fileName = decodeURIComponent(q.name || q.path || '');\r\n\t\t\t\tconst ns = q.ns === 'test' ? 'test' : 'prod';\r\n\t\t\t\tconst source = q.source || q.ty || 'server';\r\n\t\t\t\tif (!fileName && kind === 'intervention') return sendFail(res, 'name required', opt);\r\n\t\t\t\tconst payload = await exportLogContent($asai, {\r\n\t\t\t\t\tkind,\r\n\t\t\t\t\tns: kind === 'intervention' ? ns : undefined,\r\n\t\t\t\t\tfileName: fileName || undefined,\r\n\t\t\t\t\tsource,\r\n\t\t\t\t\tformat,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, payload, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/taxonomy/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\treturn sendSuccess(res, IL.getInterventionTaxonomy($asai), opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/formats/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst { getLogFormatTaxonomy } = await import('../../lib/common/log-formats');\r\n\t\t\t\treturn sendSuccess(res, getLogFormatTaxonomy($asai), opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/selectlist/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\tif (!isLogStoreEnabled($asai)) return sendFail(res, 'Log store not enabled', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst kind = q.kind ? String(q.kind) : undefined;\r\n\t\t\t\tconst ns = q.ns ? String(q.ns) : undefined;\r\n\t\t\t\tconst source = q.source || q.ty ? String(q.source || q.ty) : undefined;\r\n\t\t\t\tconst groups = await listUnifiedGroups($asai, { kind: kind as any, ns, source });\r\n\t\t\t\tif (kind === 'intervention' || ns) {\r\n\t\t\t\t\treturn sendSuccess(res, { files: groupsToInterventionFiles(groups, ns || 'prod'), ns: ns || 'prod' }, opt);\r\n\t\t\t\t}\r\n\t\t\t\tif (kind === 'web' || kind === 'sec' || kind === 'access' || source) {\r\n\t\t\t\t\tconst children = kind === 'access'\r\n\t\t\t\t\t\t? groups.filter((g) => g.kind === 'access').map((g) => ({\r\n\t\t\t\t\t\t\tname: g.file_name,\r\n\t\t\t\t\t\t\tpath: g.file_name,\r\n\t\t\t\t\t\t\tsize: g.entryCount,\r\n\t\t\t\t\t\t\tentryCount: g.entryCount,\r\n\t\t\t\t\t\t\tsource: g.source,\r\n\t\t\t\t\t\t\tfromStore: true,\r\n\t\t\t\t\t\t}))\r\n\t\t\t\t\t\t: groupsToManageChildren(groups);\r\n\t\t\t\t\treturn sendSuccess(res, { children, source }, opt);\r\n\t\t\t\t}\r\n\t\t\t\treturn sendSuccess(res, { groups }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/asailog/store/select/')) {\r\n\t\t\tif (!(await ensureLogReadAccess(req, $asai, getPermissionThreshold($asai, 'logRead')))) return sendFail(res, 'Forbidden', opt);\r\n\t\t\tif (!isLogStoreEnabled($asai)) return sendFail(res, 'Log store not enabled', opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst id = q.id;\r\n\t\t\t\tif (id != null) {\r\n\t\t\t\t\tconst row = await getUnifiedEntry($asai, id);\r\n\t\t\t\t\tif (!row) return sendFail(res, 'not found', opt);\r\n\t\t\t\t\treturn sendSuccess(res, { entry: row }, opt);\r\n\t\t\t\t}\r\n\t\t\t\tconst kind = String(q.kind || '');\r\n\t\t\t\tconst fileName = decodeURIComponent(q.name || q.path || '');\r\n\t\t\t\tconst ns = q.ns ? String(q.ns) : '';\r\n\t\t\t\tconst source = q.source || q.ty ? String(q.source || q.ty) : 'server';\r\n\r\n\t\t\t\tif (kind === 'web' || kind === 'sec' || (!kind && fileName.startsWith('log-'))) {\r\n\t\t\t\t\tconst content = await readWebLogFromStore($asai, source, fileName);\r\n\t\t\t\t\treturn sendSuccess(res, content, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (kind === 'intervention' || fileName.includes('.cef.log')) {\r\n\t\t\t\t\tconst content = await IL.readInterventionFile($asai, fileName, ns === 'test' ? 'test' : 'prod');\r\n\t\t\t\t\treturn sendSuccess(res, { ns: ns || 'prod', ...content, fromStore: true }, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst rows = await queryUnifiedLogs($asai, {\r\n\t\t\t\t\tkind: kind as any,\r\n\t\t\t\t\tns: ns as any,\r\n\t\t\t\t\tsource,\r\n\t\t\t\t\tfile_name: fileName,\r\n\t\t\t\t\tlimit: Number(q.limit) || 200,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, { entries: rows }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tasync function post(req: any, res: any, hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tif (!url.startsWith('/api/asailog/store/archive/')) return;\r\n\t\tif (!(await ensureLogWriteAccess(req, $asai, getPermissionThreshold($asai, 'adminWrite')))) return sendFail(res, 'Forbidden', opt);\r\n\t\ttry {\r\n\t\t\tconst body = parseBody(opt);\r\n\t\t\tconst year = Number(body.year);\r\n\t\t\tif (!year || year < 2000 || year > 2100) return sendFail(res, 'invalid year', opt);\r\n\t\t\tconst ns = body.ns === 'test' ? 'test' : 'prod';\r\n\t\t\tconst result = await archiveInterventionYear($asai, {\r\n\t\t\t\tyear,\r\n\t\t\t\tns,\r\n\t\t\t\tdryRun: !!body.dryRun,\r\n\t\t\t\toperator: getRequestUsername(req),\r\n\t\t\t});\r\n\t\t\treturn sendSuccess(res, result, opt);\r\n\t\t} catch (err: any) {\r\n\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { get, post };\r\n};\r\n","import * as fs from 'node:fs';\r\nimport * as nodePath from 'node:path';\r\n\r\nexport type ErrorCodeEntry = {\r\n id?: string;\r\n lg?: string;\r\n detail?: string;\r\n category?: string;\r\n level?: string;\r\n wsLang?: string;\r\n};\r\n\r\nexport type ErrorCodesFile = {\r\n version?: string;\r\n description?: string;\r\n errors?: Record<string, ErrorCodeEntry>;\r\n};\r\n\r\nlet registry: ErrorCodesFile | null = null;\r\n\r\nfunction resolveFilePath($asai: any): string {\r\n const root = $asai?.serverRoot || process.cwd();\r\n return nodePath.join(root, 'websys/sys/errorcodes.json');\r\n}\r\n\r\nexport function loadErrorCodes($asai: any): ErrorCodesFile {\r\n if (registry) return registry;\r\n const filePath = resolveFilePath($asai);\r\n try {\r\n const raw = fs.readFileSync(filePath, 'utf8');\r\n registry = JSON.parse(raw) as ErrorCodesFile;\r\n } catch {\r\n registry = { version: '0', errors: {} };\r\n }\r\n if ($asai) $asai.errorcodes = registry;\r\n return registry;\r\n}\r\n\r\nexport function getError(ec: string): ErrorCodeEntry | null {\r\n return registry?.errors?.[ec] || null;\r\n}\r\n\r\nexport function hasError(ec: string): boolean {\r\n return !!getError(ec);\r\n}\r\n\r\nexport function logError($asai: any, ec: string, params?: string[]): void {\r\n const entry = getError(ec);\r\n const logFn = $asai?.$log || console.warn;\r\n if (entry) {\r\n logFn(`[EC:${ec}]`, entry.id || '', entry.detail || '', params?.length ? params : '');\r\n } else {\r\n logFn(`[EC:${ec}]`, '(unregistered)', params?.length ? params : '');\r\n }\r\n}\r\n\r\nexport function normalizeErrPayload(err: unknown): { ec?: string; pm?: string[]; raw?: unknown } {\r\n if (err && typeof err === 'object') {\r\n const o = err as Record<string, unknown>;\r\n if (typeof o.ec === 'string') {\r\n const pm = Array.isArray(o.pm)\r\n ? o.pm.map(String)\r\n : o.pm != null\r\n ? [String(o.pm)]\r\n : undefined;\r\n return { ec: o.ec, pm };\r\n }\r\n }\r\n if (typeof err === 'string' && hasError(err)) {\r\n return { ec: err };\r\n }\r\n return { raw: err };\r\n}\r\n\r\nexport default {\r\n loadErrorCodes,\r\n getError,\r\n hasError,\r\n logError,\r\n normalizeErrPayload,\r\n};\r\n","import { loadErrorCodes } from '../../lib/common/ErrorCode';\r\n\r\n/** 公开 GET — 供前端 initerrcodes 拉取 websys/sys/errorcodes.json(开发环境跨域走 API CORS) */\r\nexport default ($asai: any) => {\r\n\tconst { sendSuccess, sendFail } = $asai.$lib?.reqWork?.($asai) || {};\r\n\r\n\tfunction get(req: any, res: any, _hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tif (url.startsWith('/api/sys/errorcodes/')) {\r\n\t\t\ttry {\r\n\t\t\t\treturn sendSuccess(res, loadErrorCodes($asai), opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn { get };\r\n};\r\n","export default ($asai: any) => {\r\n const { sendSuccess, sendFail, mnLog } = $asai?.$lib?.reqWork?.($asai) || {};\r\n function mgLog(...arg: any[]) {\r\n mnLog?.(\"SQLite\", ...arg);\r\n }\r\n\r\n return $asai.$lib.AsDb($asai, {\r\n type: \"sqlite\",\r\n opt: {\r\n database: \"./webdata/webdb/testkdd/sqlite/asaisqlitetest.db\",\r\n create: 1,\r\n },\r\n field: {\r\n key: \"ai_sn\",\r\n class: \"ai_fl\",\r\n data: [\"ai_sn\", \"ai_fl\", \"ai_bt\", \"ai_nr\", \"ai_tm\", \"ai_t1\", \"ai_dj\", \"ai_xy\", \"ai_hi\", \"ai_xi\", \"ai_xo\"],\r\n },\r\n post: async (req: any, res: any, hostdir: string, opt: any, _DataServer: any) => {\r\n if (req.url.startsWith(\"/api/asaisqlite/manage/post\")) {\r\n try {\r\n mgLog(\"POST\", \"custom handler triggered\");\r\n sendSuccess?.(res, { data: \"post\" }, opt);\r\n } catch (err) {\r\n mgLog(\"ERROR\", \"post handler\", err);\r\n }\r\n return \"ok\";\r\n }\r\n },\r\n get: async (req: any, res: any, hostdir: string, opt: any, DataServer: any) => {\r\n if (req.url.startsWith(\"/api/asaisqlite/manage/get\")) {\r\n try {\r\n const dataObj: any = opt.data;\r\n mgLog(\"SELECT\", dataObj.table);\r\n const resdb = await DataServer.sqlDb({\r\n type: \"select\",\r\n table: dataObj.table,\r\n });\r\n mgLog(\"SELECT\", \"completed\");\r\n sendSuccess?.(res, resdb, opt);\r\n } catch (errdb) {\r\n mgLog(\"ERROR\", \"select\", errdb);\r\n sendFail?.(res, errdb, opt);\r\n }\r\n return \"ok\";\r\n }\r\n },\r\n });\r\n};\r\n","/**\r\n * IEC 62443-4-2 CR 6.2 — 健康与连续监控指标(Prometheus 文本格式)\r\n */\r\nimport os from 'node:os';\r\n\r\nfunction promLine(name: string, value: number | string, labels?: Record<string, string>): string {\r\n\tconst lbl = labels\r\n\t\t? `{${Object.entries(labels)\r\n\t\t\t\t.map(([k, v]) => `${k}=\"${String(v).replace(/\"/g, '\\\\\"')}\"`)\r\n\t\t\t\t.join(',')}}`\r\n\t\t: '';\r\n\treturn `${name}${lbl} ${value}`;\r\n}\r\n\r\nexport default ($asai: any) => {\r\n\tconst { sendSuccess, sendFail } = $asai.$lib?.reqWork?.($asai) || {};\r\n\r\n\tasync function get(req: any, res: any, _hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\r\n\t\tif (url.startsWith('/api/sys/health/metrics/')) {\r\n\t\t\ttry {\r\n\t\t\t\tconst mem = process.memoryUsage();\r\n\t\t\t\tlet httpTotal = 0;\r\n\t\t\t\tlet wsTotal = 0;\r\n\t\t\t\tfor (const set of Object.values($asai.connectionshttp || {})) {\r\n\t\t\t\t\thttpTotal += (set as Set<unknown>)?.size || 0;\r\n\t\t\t\t}\r\n\t\t\t\tfor (const set of Object.values($asai.connectionsws || {})) {\r\n\t\t\t\t\twsTotal += (set as Set<unknown>)?.size || 0;\r\n\t\t\t\t}\r\n\t\t\t\tconst lines = [\r\n\t\t\t\t\t'# HELP asai_uptime_seconds Process uptime',\r\n\t\t\t\t\t'# TYPE asai_uptime_seconds gauge',\r\n\t\t\t\t\tpromLine('asai_uptime_seconds', Math.floor(process.uptime())),\r\n\t\t\t\t\t'# HELP asai_memory_rss_bytes Resident memory',\r\n\t\t\t\t\t'# TYPE asai_memory_rss_bytes gauge',\r\n\t\t\t\t\tpromLine('asai_memory_rss_bytes', mem.rss),\r\n\t\t\t\t\t'# HELP asai_http_connections Active HTTP connections',\r\n\t\t\t\t\t'# TYPE asai_http_connections gauge',\r\n\t\t\t\t\tpromLine('asai_http_connections', httpTotal),\r\n\t\t\t\t\t'# HELP asai_ws_connections Active WebSocket connections',\r\n\t\t\t\t\t'# TYPE asai_ws_connections gauge',\r\n\t\t\t\t\tpromLine('asai_ws_connections', wsTotal),\r\n\t\t\t\t\t'# HELP asai_loadavg_1m System load average 1m',\r\n\t\t\t\t\t'# TYPE asai_loadavg_1m gauge',\r\n\t\t\t\t\tpromLine('asai_loadavg_1m', os.loadavg()[0] ?? 0),\r\n\t\t\t\t];\r\n\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });\r\n\t\t\t\treturn res.end(lines.join('\\n') + '\\n');\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/sys/health/status/')) {\r\n\t\t\treturn sendSuccess(\r\n\t\t\t\tres,\r\n\t\t\t\t{\r\n\t\t\t\t\tuptime: process.uptime(),\r\n\t\t\t\t\tnode: process.version,\r\n\t\t\t\t\tplatform: process.platform,\r\n\t\t\t\t\tmemory: process.memoryUsage(),\r\n\t\t\t\t\tquota: {\r\n\t\t\t\t\t\thttp: Object.fromEntries(\r\n\t\t\t\t\t\t\tObject.entries($asai.connectionshttp || {}).map(([k, v]) => [k, (v as Set<unknown>)?.size || 0]),\r\n\t\t\t\t\t\t),\r\n\t\t\t\t\t\tws: Object.fromEntries(\r\n\t\t\t\t\t\t\tObject.entries($asai.connectionsws || {}).map(([k, v]) => [k, (v as Set<unknown>)?.size || 0]),\r\n\t\t\t\t\t\t),\r\n\t\t\t\t\t},\r\n\t\t\t\t},\r\n\t\t\t\topt,\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { get };\r\n};\r\n","/**\r\n * IEC 62443-4-2 CR 3.5 / CR 7.6 — 输入校验与消毒\r\n * 供 API/SYS handler 复用,防止注入与异常 payload。\r\n */\r\n\r\nfunction hasControlChars(value: string): boolean {\r\n\tfor (let i = 0; i < value.length; i++) {\r\n\t\tconst c = value.charCodeAt(i);\r\n\t\tif (c === 0x7f) return true;\r\n\t\tif (c <= 0x1f && c !== 0x09 && c !== 0x0a && c !== 0x0d) return true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nexport function rejectControlChars(value: string, field = 'input'): string {\r\n\tif (typeof value !== 'string') return value as unknown as string;\r\n\tif (hasControlChars(value)) {\r\n\t\tthrow new Error(`Invalid ${field}: control characters not allowed`);\r\n\t}\r\n\treturn value;\r\n}\r\n\r\nexport function sanitizeString(value: unknown, maxLen = 4096): string {\r\n\tif (value == null) return '';\r\n\tconst str = String(value);\r\n\trejectControlChars(str);\r\n\treturn str.length > maxLen ? str.slice(0, maxLen) : str;\r\n}\r\n\r\nexport function sanitizePathSegment(segment: unknown): string {\r\n\tconst str = sanitizeString(segment, 256);\r\n\tif (str.includes('..') || str.includes('/') || str.includes('\\\\')) {\r\n\t\tthrow new Error('Invalid path segment');\r\n\t}\r\n\treturn str;\r\n}\r\n\r\nexport function parseJsonSafe(raw: string, maxLen = 1024 * 1024): unknown {\r\n\tif (typeof raw !== 'string') throw new Error('Invalid JSON body');\r\n\tif (raw.length > maxLen) throw new Error('JSON body too large');\r\n\ttry {\r\n\t\treturn JSON.parse(raw);\r\n\t} catch {\r\n\t\tthrow new Error('Invalid JSON');\r\n\t}\r\n}\r\n\r\nexport function assertObject(value: unknown, label = 'payload'): Record<string, unknown> {\r\n\tif (!value || typeof value !== 'object' || Array.isArray(value)) {\r\n\t\tthrow new Error(`${label} must be a plain object`);\r\n\t}\r\n\treturn value as Record<string, unknown>;\r\n}\r\n","import { createHmac, randomInt, randomUUID } from 'node:crypto';\r\nimport type { SessionRecord } from '../store/types';\r\n\r\nexport function getSessionSecret($asai: any): string {\r\n\tconst secret =\r\n\t\tprocess.env.ASAI_SESSION_SECRET ||\r\n\t\t$asai?.hostconfig?.security?.sessionSecret;\r\n\tif (!secret) {\r\n\t\tthrow new Error('[session] ASAI_SESSION_SECRET 未配置');\r\n\t}\r\n\treturn secret;\r\n}\r\n\r\nexport function getSessionTtlMs($asai: any): number {\r\n\tconst hours = $asai?.hostconfig?.security?.sessionTtlHours ?? 24;\r\n\treturn Number(hours) * 3600 * 1000;\r\n}\r\n\r\nconst PRI_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r\n\r\n/**\r\n * 生成会话对称 key(pri)。AsCode.asencode/asdecode 依赖 key 内字符互不重复\r\n * (decode 用 keys.indexOf 定位字符,重复字符会解出错误位置),\r\n * 因此不能用 randomBytes().toString('base64url')(大概率出现重复字符),\r\n * 改为对唯一字符字母表做加密安全洗牌后取前 length 位,天然保证无重复。\r\n */\r\nfunction generatePriKey(length = 32): string {\r\n\tconst arr = PRI_ALPHABET.split('');\r\n\tfor (let i = arr.length - 1; i > 0; i--) {\r\n\t\tconst j = randomInt(i + 1);\r\n\t\t[arr[i], arr[j]] = [arr[j], arr[i]];\r\n\t}\r\n\treturn arr.slice(0, Math.min(length, arr.length)).join('');\r\n}\r\n\r\nexport function createSessionKeys($asai: any): { pri: string; pub: string; sessionId: string } {\r\n\tconst sessionId = randomUUID();\r\n\tconst pri = generatePriKey();\r\n\tconst sn = $asai?.hostconfig?.asaisn;\r\n\tif (!sn) throw new Error('[session] ASAI_ASAISN 未配置');\r\n\t// legacy Userinfo 协议(us##lv##tk)要求 tk 经 asaisn 解密后得到\"和客户端一致\"的对称 key:\r\n\t// 客户端 inittoken() 用 code.pri 加密 us/lv,因此 pub 必须承载 pri(而非 sessionId),\r\n\t// 否则服务端 deUserInfoWithAsai 解出的 key 与客户端不一致,导致所有 lv 鉴权接口恒为 Forbidden。\r\n\tconst pub = $asai.$lib.AsCode.asencode(pri, sn);\r\n\treturn { pri, pub, sessionId };\r\n}\r\n\r\nexport function signSession(sessionId: string, $asai: any): string {\r\n\treturn createHmac('sha256', getSessionSecret($asai)).update(sessionId).digest('hex');\r\n}\r\n\r\nexport function buildSessionRecord($asai: any, us: string, ip: string): SessionRecord {\r\n\tconst { pri, pub, sessionId } = createSessionKeys($asai);\r\n\tconst now = Date.now();\r\n\treturn {\r\n\t\tid: sessionId,\r\n\t\tus,\r\n\t\tip,\r\n\t\tcreatedAt: now,\r\n\t\texpiresAt: now + getSessionTtlMs($asai),\r\n\t\tlastActivityAt: now,\r\n\t\tpri,\r\n\t\tpub,\r\n\t};\r\n}\r\n\r\nexport function isSessionValid(session: SessionRecord): boolean {\r\n\treturn session.expiresAt > Date.now();\r\n}\r\n","import { USER_LV } from './user-levels';\r\nimport { getPermissionThreshold } from './user-level-config';\r\n\r\nconst API_ADMIN_PREFIXES = ['/api/user/login/admin/'];\r\n\r\nexport function getMinLevelForApiPath(pathname: string, $asai?: any): number {\r\n\tif (API_ADMIN_PREFIXES.some((p) => pathname.startsWith(p))) {\r\n\t\tif (\r\n\t\t\tpathname.includes('/admin/update') ||\r\n\t\t\tpathname.includes('/admin/kick') ||\r\n\t\t\tpathname.includes('/admin/delete') ||\r\n\t\t\tpathname.includes('/admin/resetpass')\r\n\t\t) {\r\n\t\t\treturn $asai ? getPermissionThreshold($asai, 'adminWrite') : USER_LV.DEVELOPER;\r\n\t\t}\r\n\t\treturn $asai ? getPermissionThreshold($asai, 'adminRead') : USER_LV.ADMIN;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nexport function hasLevel(userLevel: number, required: number): boolean {\r\n\treturn Number.isFinite(userLevel) && userLevel >= required;\r\n}\r\n","/** 登录/注册 POST 体解析 — 兼容 JSON 字符串、已解析对象、password 字段别名 */\r\nexport function isAesEnvelope(body: Record<string, unknown>): boolean {\r\n\treturn (\r\n\t\ttypeof body.data === 'string' &&\r\n\t\ttypeof body.iv === 'string' &&\r\n\t\ttypeof body.auth === 'string' &&\r\n\t\tbody.aes != null &&\r\n\t\tbody.us == null &&\r\n\t\tbody.pass == null &&\r\n\t\tbody.password == null\r\n\t);\r\n}\r\n\r\nfunction unwrapJsonString(value: unknown): unknown {\r\n\tif (typeof value !== 'string') return value;\r\n\tconst text = value.trim();\r\n\tif (!text.startsWith('{') && !text.startsWith('[')) return value;\r\n\ttry {\r\n\t\treturn JSON.parse(text);\r\n\t} catch {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\nexport function parseAuthBody(opt: { data?: unknown }): Record<string, unknown> {\r\n\tlet raw = opt?.data;\r\n\tif (raw == null || raw === '') return {};\r\n\tif (typeof raw === 'string') {\r\n\t\tconst text = raw.trim();\r\n\t\tif (!text) return {};\r\n\t\ttry {\r\n\t\t\traw = JSON.parse(text);\r\n\t\t} catch {\r\n\t\t\tif (text.includes('=') && !text.startsWith('{') && !text.startsWith('[')) {\r\n\t\t\t\traw = Object.fromEntries(new URLSearchParams(text));\r\n\t\t\t} else {\r\n\t\t\t\treturn {};\r\n\t\t\t}\r\n\t\t}\r\n\t\t// 兼容前端 AES 失败时对已 stringify 的 body 再次 JSON.stringify\r\n\t\traw = unwrapJsonString(raw);\r\n\t}\r\n\tif (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};\r\n\tconst body = raw as Record<string, unknown>;\r\n\tif (isAesEnvelope(body)) return {};\r\n\treturn body;\r\n}\r\n\r\nexport function pickAuthField(body: Record<string, unknown>, ...keys: string[]): string {\r\n\tfor (const key of keys) {\r\n\t\tconst val = body[key];\r\n\t\tif (val != null && String(val).length > 0) return String(val);\r\n\t}\r\n\treturn '';\r\n}\r\n","import type { IUserStore, SessionRecord } from '../store/types';\r\nimport { isUserOnlineOnWs, listOnlineWsUsers } from '../../../../ws/auth';\r\n\r\n/** 管理端:仅返回当前 WS 在线用户对应的会话(每用户一条,取最近活动) */\r\nexport function resolveOnlineSessions(\r\n\t$asai: any,\r\n\thostdir: string,\r\n\tallSessions: SessionRecord[],\r\n): SessionRecord[] {\r\n\tconst onlineUsers = new Set(listOnlineWsUsers($asai, hostdir));\r\n\tif (!onlineUsers.size) return [];\r\n\r\n\tconst byUser = new Map<string, SessionRecord>();\r\n\tfor (const s of allSessions) {\r\n\t\tif (!onlineUsers.has(s.us)) continue;\r\n\t\tconst prev = byUser.get(s.us);\r\n\t\tconst sTime = s.lastActivityAt ?? s.createdAt;\r\n\t\tconst prevTime = prev ? (prev.lastActivityAt ?? prev.createdAt) : 0;\r\n\t\tif (!prev || sTime > prevTime) byUser.set(s.us, s);\r\n\t}\r\n\treturn [...byUser.values()].sort((a, b) => b.createdAt - a.createdAt);\r\n}\r\n\r\nexport function isSessionUserOnline($asai: any, us: string, hostdir: string): boolean {\r\n\tif (!us) return false;\r\n\treturn isUserOnlineOnWs($asai, us, hostdir);\r\n}\r\n\r\n/** 当前 WS 在线会话数(配额统计用) */\r\nexport async function countOnlineSessions(\r\n\t$asai: any,\r\n\thostdir: string,\r\n\tstore: IUserStore,\r\n): Promise<number> {\r\n\tconst all = await store.getSessions();\r\n\treturn resolveOnlineSessions($asai, hostdir, all).length;\r\n}\r\n\r\n/** 单用户当前 WS 在线会话数 */\r\nexport async function countOnlineSessionsByUser(\r\n\t$asai: any,\r\n\thostdir: string,\r\n\tstore: IUserStore,\r\n\tus: string,\r\n): Promise<number> {\r\n\tconst all = await store.getSessions();\r\n\treturn resolveOnlineSessions($asai, hostdir, all).filter((s) => s.us === us).length;\r\n}\r\n\r\n/** 清除已离线用户残留的会话记录(未过期但未连 WS) */\r\nexport async function purgeOfflineSessions(\r\n\t$asai: any,\r\n\thostdir: string,\r\n\tstore: IUserStore,\r\n): Promise<number> {\r\n\tconst onlineUsers = new Set(listOnlineWsUsers($asai, hostdir));\r\n\tconst all = await store.getSessions();\r\n\tlet purged = 0;\r\n\tfor (const s of all) {\r\n\t\tif (onlineUsers.has(s.us)) continue;\r\n\t\tawait store.removeSession(s.id);\r\n\t\tpurged += 1;\r\n\t}\r\n\treturn purged;\r\n}\r\n","import { logSecurityEvent, getClientIp } from '../../../infra/security-audit';\r\nimport {\r\n\tlogAccountPurge,\r\n\tlogSecurityConfigIntervention,\r\n\tlogSessionTerminate,\r\n\tlogUserRbacChange,\r\n} from '../../lib/common/intervention-hooks';\r\nimport { sanitizeString } from '../../../infra/input-sanitize';\r\nimport { attachServerUserLevel, getRequestUserLevel } from '../../../infra/user-auth';\r\nimport {\r\n\tgetPasswordPolicy,\r\n\tgetPublicSecurityConfig,\r\n\tisPasswordExpired,\r\n\tresolveRoleForLevel,\r\n\tvalidatePasswordWithPolicy,\r\n} from '../../../infra/security-policy';\r\nimport { createUserStore, ensureBootstrapAdmin } from './store/user-store';\r\nimport {\r\n\thashPassword,\r\n\tnextPassHistory,\r\n\tvalidatePasswordChange,\r\n\tverifyPassword,\r\n} from './service/password';\r\nimport { buildSessionRecord } from './service/session';\r\nimport { getMinLevelForApiPath, hasLevel } from './service/rbac';\r\nimport {\r\n\tgetPermissionThreshold,\r\n\tgetDefaultResetPassword,\r\n\tgetUserLevelConfigSync,\r\n\tisValidUserLv,\r\n\tloadUserLevelConfig,\r\n\tsaveUserLevelConfig,\r\n} from './service/user-level-config';\r\nimport { isUserOnlineOnWs, kickUserWs } from '../../../ws/auth';\r\nimport { parseAuthBody, pickAuthField } from './service/request-body';\r\nimport {\r\n\tcountOnlineSessions,\r\n\tcountOnlineSessionsByUser,\r\n\tisSessionUserOnline,\r\n\tpurgeOfflineSessions,\r\n\tresolveOnlineSessions,\r\n} from './service/online-sessions';\r\n\r\nfunction getSecurity($asai: any) {\r\n\treturn $asai?.hostconfig?.security || {};\r\n}\r\n\r\nfunction getQuota($asai: any) {\r\n\tconst sec = getSecurity($asai);\r\n\treturn sec.quota || {};\r\n}\r\n\r\nasync function canLogin(\r\n\t$asai: any,\r\n\tus: string,\r\n\thostdir: string,\r\n): Promise<{ ok: boolean; message?: string }> {\r\n\tconst quota = getQuota($asai);\r\n\tif (!quota.enabled) return { ok: true };\r\n\r\n\tconst store = createUserStore($asai);\r\n\tconst total = await countOnlineSessions($asai, hostdir, store);\r\n\tconst maxLogin = quota.maxLoginSessions ?? $asai?.hostconfig?.hosts?.default?.maxonline ?? 100;\r\n\tif (total >= maxLogin) {\r\n\t\treturn { ok: false, message: 'LOGIN_QUOTA_FULL' };\r\n\t}\r\n\r\n\tconst perUser = await countOnlineSessionsByUser($asai, hostdir, store, us);\r\n\tconst maxPerUser = quota.maxSessionsPerUser ?? 3;\r\n\tif (perUser >= maxPerUser) {\r\n\t\treturn { ok: false, message: 'USER_SESSION_LIMIT' };\r\n\t}\r\n\treturn { ok: true };\r\n}\r\n\r\nfunction publicUser($asai: any, user: any) {\r\n\tconst role = user.role || resolveRoleForLevel($asai, user.lv).name;\r\n\treturn {\r\n\t\tus: user.us,\r\n\t\tlv: user.lv,\r\n\t\trole,\r\n\t\temail: user.email,\r\n\t\tstatus: user.status,\r\n\t\tmustChangePassword: !!user.mustChangePassword,\r\n\t};\r\n}\r\n\r\nlet bootstrapPromise: Promise<void> | null = null;\r\n\r\nfunction ensureReady($asai: any): Promise<void> {\r\n\tif (!bootstrapPromise) {\r\n\t\tbootstrapPromise = Promise.all([ensureBootstrapAdmin($asai), loadUserLevelConfig($asai)]).then(() => undefined);\r\n\t}\r\n\treturn bootstrapPromise;\r\n}\r\n\r\nexport default ($asai: any) => {\r\n\tconst { sendSuccess, sendFail, sendErr } = $asai.$lib?.reqWork?.($asai) || {};\r\n\tconst store = createUserStore($asai);\r\n\r\n\tasync function checkAdmin(req: any, pathname: string, minOverride?: number): Promise<boolean> {\r\n\t\tawait attachServerUserLevel(req, $asai);\r\n\t\tconst minLv = minOverride ?? getMinLevelForApiPath(pathname, $asai);\r\n\t\treturn hasLevel(getRequestUserLevel(req), minLv);\r\n\t}\r\n\r\n\tasync function post(req: any, res: any, hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tconst ip = getClientIp(req);\r\n\t\tconst body = parseAuthBody(opt);\r\n\r\n\t\tif (url.startsWith('/api/user/login/changepass/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\ttry {\r\n\t\t\t\tconst us = sanitizeString(pickAuthField(body, 'us', 'username'), 64);\r\n\t\t\t\tconst pass = sanitizeString(pickAuthField(body, 'pass', 'password', 'pwd'), 128);\r\n\t\t\t\tconst newPass = sanitizeString(pickAuthField(body, 'newPass', 'newPassword', 'newpass'), 128);\r\n\t\t\t\tif (!us || !pass || !newPass) return sendErr(res, 'AUTH_CREDENTIALS_REQUIRED', undefined, opt);\r\n\r\n\t\t\t\tconst user = await store.findByUsername(us);\r\n\t\t\t\tif (!user || !verifyPassword(pass, user.passHash, user.passSalt)) {\r\n\t\t\t\t\treturn sendErr(res, 'AUTH_INVALID_CREDENTIALS', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst policy = getPasswordPolicy($asai);\r\n\t\t\t\tconst policyErr = validatePasswordChange(newPass, $asai, user.passHistory);\r\n\t\t\t\tif (policyErr === 'PASSWORD_TOO_SHORT') {\r\n\t\t\t\t\treturn sendErr(res, policyErr, [String(policy.minLength)], opt);\r\n\t\t\t\t}\r\n\t\t\t\tif (policyErr) return sendErr(res, policyErr, undefined, opt);\r\n\r\n\t\t\t\tconst { passHash, passSalt } = hashPassword(newPass);\r\n\t\t\t\tconst passHistory = nextPassHistory(pass, user.passHistory, policy.historyCount);\r\n\t\t\t\tawait store.updateUser(us, {\r\n\t\t\t\t\tpassHash,\r\n\t\t\t\t\tpassSalt,\r\n\t\t\t\t\tmustChangePassword: 0,\r\n\t\t\t\t\tpasswordChangedAt: Date.now(),\r\n\t\t\t\t\tpassHistory,\r\n\t\t\t\t});\r\n\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: us, ip, detail: 'password_changed' });\r\n\t\t\t\treturn sendSuccess(res, { ok: true }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/register/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\tconst sec = getSecurity($asai);\r\n\t\t\tif (sec.allowRegister === 0) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_REG_DISABLED', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst us = sanitizeString(pickAuthField(body, 'us', 'username'), 64);\r\n\t\t\t\tconst pass = sanitizeString(pickAuthField(body, 'pass', 'password', 'pwd'), 128);\r\n\t\t\t\tconst emailRaw = pickAuthField(body, 'email');\r\n\t\t\t\tconst email = emailRaw ? sanitizeString(emailRaw, 128) : undefined;\r\n\t\t\t\tif (!us || !pass) return sendErr(res, 'AUTH_CREDENTIALS_REQUIRED', undefined, opt);\r\n\t\t\t\tconst policyErr = validatePasswordChange(pass, $asai);\r\n\t\t\t\tif (policyErr === 'PASSWORD_TOO_SHORT') {\r\n\t\t\t\t\treturn sendErr(res, policyErr, [String(getPasswordPolicy($asai).minLength)], opt);\r\n\t\t\t\t}\r\n\t\t\t\tif (policyErr) return sendErr(res, policyErr, undefined, opt);\r\n\t\t\t\tconst { passHash, passSalt } = hashPassword(pass);\r\n\t\t\t\tconst user = await store.createUser({\r\n\t\t\t\t\tus,\r\n\t\t\t\t\temail,\r\n\t\t\t\t\tpassHash,\r\n\t\t\t\t\tpassSalt,\r\n\t\t\t\t\tlv: 0,\r\n\t\t\t\t\tpasswordChangedAt: Date.now(),\r\n\t\t\t\t\tpassHistory: '[]',\r\n\t\t\t\t});\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: us, ip, detail: 'register_ok' });\r\n\t\t\t\treturn sendSuccess(res, { user: publicUser($asai, user) }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\tconst msg = err?.message || String(err);\r\n\t\t\t\tif (msg.includes('exists') || msg.includes('已存在')) {\r\n\t\t\t\t\treturn sendErr(res, 'USER_ALREADY_EXISTS', undefined, opt);\r\n\t\t\t\t}\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/auth/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\ttry {\r\n\t\t\t\tconst us = sanitizeString(pickAuthField(body, 'us', 'username'), 64);\r\n\t\t\t\tconst pass = sanitizeString(pickAuthField(body, 'pass', 'password', 'pwd'), 128);\r\n\t\t\t\tif (!us || !pass) return sendErr(res, 'AUTH_CREDENTIALS_REQUIRED', undefined, opt);\r\n\r\n\t\t\t\tconst user = await store.findByUsername(us);\r\n\t\t\t\tif (!user || !verifyPassword(pass, user.passHash, user.passSalt)) {\r\n\t\t\t\t\tif (user) {\r\n\t\t\t\t\t\tconst sec = getSecurity($asai);\r\n\t\t\t\t\t\tconst lockoutMax = sec.lockoutMaxFails ?? 5;\r\n\t\t\t\t\t\tconst lockoutMin = sec.lockoutMinutes ?? 15;\r\n\t\t\t\t\t\tconst failCount = (user.failCount || 0) + 1;\r\n\t\t\t\t\t\tconst patch: any = { failCount };\r\n\t\t\t\t\t\tif (failCount >= lockoutMax) {\r\n\t\t\t\t\t\t\tpatch.status = 'locked';\r\n\t\t\t\t\t\t\tpatch.lockedUntil = Date.now() + lockoutMin * 60 * 1000;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tawait store.updateUser(us, patch);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlogSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: us, ip });\r\n\t\t\t\t\treturn sendErr(res, 'AUTH_INVALID_CREDENTIALS', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (user.status === 'disabled') {\r\n\t\t\t\t\treturn sendErr(res, 'AUTH_ACCOUNT_DISABLED', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (user.status === 'locked' && user.lockedUntil && user.lockedUntil > Date.now()) {\r\n\t\t\t\t\treturn sendErr(res, 'AUTH_ACCOUNT_LOCKED', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst policy = getPasswordPolicy($asai);\r\n\t\t\t\tconst mustChange =\r\n\t\t\t\t\t!!user.mustChangePassword ||\r\n\t\t\t\t\tisPasswordExpired(user.passwordChangedAt, policy.maxAgeDays);\r\n\r\n\t\t\t\tconst hostcfg = $asai.getHost?.(hostdir) || {};\r\n\t\t\t\tif (hostcfg.ckws && isUserOnlineOnWs($asai, us, hostdir)) {\r\n\t\t\t\t\t// 凭密码验证通过后,允许接管本账号残留的 WS 在线位(同浏览器 stale 会话等)\r\n\t\t\t\t\tkickUserWs($asai, us, hostdir);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst quotaCheck = await canLogin($asai, us, hostdir);\r\n\t\t\t\tif (!quotaCheck.ok) {\r\n\t\t\t\t\tlogSecurityEvent($asai, { type: 'RATE_LIMIT', path: url, method: 'POST', user: us, ip, detail: quotaCheck.message });\r\n\t\t\t\t\treturn sendErr(res, quotaCheck.message || 'LOGIN_QUOTA_FULL', undefined, opt);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tawait store.updateUser(us, { failCount: 0, status: 'active', lockedUntil: undefined });\r\n\t\t\t\tconst session = buildSessionRecord($asai, us, ip);\r\n\t\t\t\tsession.lastActivityAt = Date.now();\r\n\t\t\t\tawait store.addSession(session);\r\n\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: us, ip, detail: 'login_ok' });\r\n\r\n\t\t\t\treturn sendSuccess(\r\n\t\t\t\t\tres,\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tuser: { ...publicUser($asai, user), mustChangePassword: mustChange },\r\n\t\t\t\t\t\tcode: mustChange ? null : [session.pri, session.pub],\r\n\t\t\t\t\t\tsessionId: mustChange ? null : session.id,\r\n\t\t\t\t\t\tmustChangePassword: mustChange,\r\n\t\t\t\t\t},\r\n\t\t\t\t\topt,\r\n\t\t\t\t);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/logout/')) {\r\n\t\t\ttry {\r\n\t\t\t\tconst bodySid = body.sessionId ? sanitizeString(body.sessionId, 64) : '';\r\n\t\t\t\tif (bodySid) await store.removeSession(bodySid);\r\n\t\t\t\tconst us = req?.Userinfo?.[0];\r\n\t\t\t\tif (us) logSecurityEvent($asai, { type: 'AUTH_FAIL', path: url, method: 'POST', user: String(us), ip, detail: 'logout' });\r\n\t\t\t\treturn sendSuccess(res, 'ok', opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/kick/')) {\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminWrite')))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst sessionId = sanitizeString(body.sessionId, 64);\r\n\t\t\t\tif (!sessionId) return sendErr(res, 'AUTH_CREDENTIALS_REQUIRED', undefined, opt);\r\n\t\t\t\tconst sessions = await store.getSessions();\r\n\t\t\t\tconst target = sessions.find((s) => s.id === sessionId);\r\n\t\t\t\tif (!target) return sendErr(res, 'AUTH_SESSION_NOT_FOUND', undefined, opt);\r\n\t\t\t\tif (!isSessionUserOnline($asai, target.us, hostdir)) {\r\n\t\t\t\t\treturn sendErr(res, 'SESSION_NOT_ONLINE', undefined, opt);\r\n\t\t\t\t}\r\n\t\t\t\tkickUserWs($asai, target.us, hostdir);\r\n\t\t\t\tawait store.removeSession(sessionId);\r\n\t\t\t\tconst operator = String(req?.Userinfo?.[0] || '');\r\n\t\t\t\tawait logSessionTerminate($asai, {\r\n\t\t\t\t\toperator,\r\n\t\t\t\t\tsessionId,\r\n\t\t\t\t\ttargetUs: target.us,\r\n\t\t\t\t\tip,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, { ok: true }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/delete/')) {\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminWrite')))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst targetUs = sanitizeString(body.us, 64);\r\n\t\t\t\tif (!targetUs || targetUs === 'admin') return sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t\tconst ok = await store.deleteUser(targetUs);\r\n\t\t\t\tif (!ok) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\t\t\t\tconst operator = String(req?.Userinfo?.[0] || '');\r\n\t\t\t\tawait logAccountPurge($asai, { operator, targetUs, ip });\r\n\t\t\t\treturn sendSuccess(res, { ok: true }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/levels/')) {\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminWrite')))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst levels = Array.isArray(body.levels) ? body.levels : undefined;\r\n\t\t\t\tconst thresholds =\r\n\t\t\t\t\tbody.thresholds && typeof body.thresholds === 'object' ? (body.thresholds as Record<string, unknown>) : undefined;\r\n\t\t\t\tconst routeRights = Array.isArray(body.routeRights) ? body.routeRights : undefined;\r\n\t\t\t\tconst defaultResetPassword =\r\n\t\t\t\t\ttypeof body.defaultResetPassword === 'string' ? body.defaultResetPassword : undefined;\r\n\t\t\t\tconst operator = String(req?.Userinfo?.[0] || '');\r\n\t\t\t\tconst cfg = await saveUserLevelConfig(\r\n\t\t\t\t\t$asai,\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tlevels: levels as any,\r\n\t\t\t\t\t\tthresholds: thresholds as any,\r\n\t\t\t\t\t\trouteRights: routeRights as any,\r\n\t\t\t\t\t\tdefaultResetPassword,\r\n\t\t\t\t\t},\r\n\t\t\t\t\toperator,\r\n\t\t\t\t);\r\n\t\t\t\tawait logSecurityConfigIntervention($asai, {\r\n\t\t\t\t\tsection: 'user_levels',\r\n\t\t\t\t\tdetail: JSON.stringify({ levels: levels?.length, thresholds: !!thresholds, routeRights: routeRights?.length }),\r\n\t\t\t\t\toperator,\r\n\t\t\t\t\tip,\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, cfg, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/resetpass/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminWrite')))) {\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'ACCESS_DENIED', path: url, method: 'POST', ip });\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst targetUs = sanitizeString(body.us, 64);\r\n\t\t\t\tif (!targetUs) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\t\t\t\tlet newPass = sanitizeString(pickAuthField(body, 'newPass', 'newPassword', 'newpass'), 128);\r\n\t\t\t\tif (!newPass) newPass = getDefaultResetPassword($asai);\r\n\t\t\t\tconst policy = getPasswordPolicy($asai);\r\n\t\t\t\tconst policyErr = validatePasswordWithPolicy(newPass, policy);\r\n\t\t\t\tif (policyErr === 'PASSWORD_TOO_SHORT') {\r\n\t\t\t\t\treturn sendErr(res, policyErr, [String(policy.minLength)], opt);\r\n\t\t\t\t}\r\n\t\t\t\tif (policyErr) return sendErr(res, policyErr, undefined, opt);\r\n\r\n\t\t\t\tconst user = await store.findByUsername(targetUs);\r\n\t\t\t\tif (!user) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\r\n\t\t\t\tconst { passHash, passSalt } = hashPassword(newPass);\r\n\t\t\t\tconst updated = await store.updateUser(targetUs, {\r\n\t\t\t\t\tpassHash,\r\n\t\t\t\t\tpassSalt,\r\n\t\t\t\t\tmustChangePassword: 1,\r\n\t\t\t\t\tpasswordChangedAt: Date.now(),\r\n\t\t\t\t\tfailCount: 0,\r\n\t\t\t\t\tstatus: 'active',\r\n\t\t\t\t\tlockedUntil: undefined,\r\n\t\t\t\t\tpassHistory: '[]',\r\n\t\t\t\t});\r\n\t\t\t\tif (!updated) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\t\t\t\tconst operator = String(req?.Userinfo?.[0] || '');\r\n\t\t\t\tawait logUserRbacChange($asai, {\r\n\t\t\t\t\toperator,\r\n\t\t\t\t\ttargetUs,\r\n\t\t\t\t\tpatch: { resetPassword: true, mustChangePassword: 1 },\r\n\t\t\t\t\tip,\r\n\t\t\t\t});\r\n\t\t\t\tlogSecurityEvent($asai, {\r\n\t\t\t\t\ttype: 'AUTH_FAIL',\r\n\t\t\t\t\tpath: url,\r\n\t\t\t\t\tmethod: 'POST',\r\n\t\t\t\t\tuser: targetUs,\r\n\t\t\t\t\tip,\r\n\t\t\t\t\tdetail: 'admin_password_reset',\r\n\t\t\t\t});\r\n\t\t\t\treturn sendSuccess(res, { user: publicUser($asai, updated) }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/update/')) {\r\n\t\t\tawait ensureReady($asai);\r\n\t\t\tif (!(await checkAdmin(req, url))) {\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'ACCESS_DENIED', path: url, method: 'POST', ip });\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\ttry {\r\n\t\t\t\tconst targetUs = sanitizeString(body.us, 64);\r\n\t\t\t\tconst patch: any = {};\r\n\t\t\t\tif (body.lv != null) {\r\n\t\t\t\t\tconst newLv = Number(body.lv);\r\n\t\t\t\t\tif (!Number.isFinite(newLv) || !isValidUserLv($asai, newLv)) {\r\n\t\t\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpatch.lv = newLv;\r\n\t\t\t\t\tpatch.role = resolveRoleForLevel($asai, newLv).name;\r\n\t\t\t\t}\r\n\t\t\t\tif (body.status) patch.status = sanitizeString(body.status, 16);\r\n\t\t\t\tif (body.resetLock) {\r\n\t\t\t\t\tpatch.failCount = 0;\r\n\t\t\t\t\tpatch.status = 'active';\r\n\t\t\t\t\tpatch.lockedUntil = undefined;\r\n\t\t\t\t}\r\n\t\t\t\tif (body.mustChangePassword != null) patch.mustChangePassword = body.mustChangePassword ? 1 : 0;\r\n\t\t\t\tconst updated = await store.updateUser(targetUs, patch);\r\n\t\t\t\tif (!updated) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\t\t\t\tif (Object.keys(patch).length) {\r\n\t\t\t\t\tawait logUserRbacChange($asai, {\r\n\t\t\t\t\t\toperator: String(req?.Userinfo?.[0] || ''),\r\n\t\t\t\t\t\ttargetUs,\r\n\t\t\t\t\t\tpatch,\r\n\t\t\t\t\t\tip,\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t\treturn sendSuccess(res, { user: publicUser($asai, updated) }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/profile/')) {\r\n\t\t\tconst us = req?.Userinfo?.[0];\r\n\t\t\tif (!us) return sendErr(res, 'AUTH_UNAUTHORIZED', undefined, opt);\r\n\t\t\ttry {\r\n\t\t\t\tconst user = await store.findByUsername(String(us));\r\n\t\t\t\tif (!user) return sendErr(res, 'AUTH_USER_NOT_FOUND', undefined, opt);\r\n\r\n\t\t\t\tif (pickAuthField(body, 'newPass', 'newPassword', 'newpass')) {\r\n\t\t\t\t\tconst newPass = sanitizeString(pickAuthField(body, 'newPass', 'newPassword', 'newpass'), 128);\r\n\t\t\t\t\tconst policy = getPasswordPolicy($asai);\r\n\t\t\t\t\tconst oldPass = pickAuthField(body, 'pass', 'password', 'pwd');\r\n\r\n\t\t\t\t\tif (oldPass) {\r\n\t\t\t\t\t\tif (!verifyPassword(oldPass, user.passHash, user.passSalt)) {\r\n\t\t\t\t\t\t\treturn sendErr(res, 'AUTH_INVALID_PASSWORD', undefined, opt);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else if (!user.mustChangePassword) {\r\n\t\t\t\t\t\treturn sendErr(res, 'AUTH_INVALID_PASSWORD', undefined, opt);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst policyErr = validatePasswordChange(newPass, $asai, user.passHistory);\r\n\t\t\t\t\tif (policyErr === 'PASSWORD_TOO_SHORT') {\r\n\t\t\t\t\t\treturn sendErr(res, policyErr, [String(policy.minLength)], opt);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (policyErr) return sendErr(res, policyErr, undefined, opt);\r\n\r\n\t\t\t\t\tconst { passHash, passSalt } = hashPassword(newPass);\r\n\t\t\t\t\tconst passHistory = nextPassHistory(oldPass || newPass, user.passHistory, policy.historyCount);\r\n\t\t\t\t\tawait store.updateUser(String(us), {\r\n\t\t\t\t\t\tpassHash,\r\n\t\t\t\t\t\tpassSalt,\r\n\t\t\t\t\t\tmustChangePassword: 0,\r\n\t\t\t\t\t\tpasswordChangedAt: Date.now(),\r\n\t\t\t\t\t\tpassHistory,\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst fresh = await store.findByUsername(String(us));\r\n\t\t\t\treturn sendSuccess(res, { user: fresh ? publicUser($asai, fresh) : null }, opt);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\treturn sendFail(res, err?.message || err, opt);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tasync function get(req: any, res: any, hostdir: string, opt: any) {\r\n\t\tconst url = req.url || '';\r\n\t\tconst ip = getClientIp(req);\r\n\r\n\t\tif (url.startsWith('/api/user/login/config/')) {\r\n\t\t\tconst lang = String(req?.headers?.['accept-language'] || opt?.headers?.['accept-language'] || 'zh-CN').split(',')[0];\r\n\t\t\tawait loadUserLevelConfig($asai);\r\n\t\t\treturn sendSuccess(res, getPublicSecurityConfig($asai, lang), opt);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/levels/')) {\r\n\t\t\tif (!(await checkAdmin(req, url, getPermissionThreshold($asai, 'adminRead')))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\tawait loadUserLevelConfig($asai);\r\n\t\t\treturn sendSuccess(res, getUserLevelConfigSync($asai), opt);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/sessions/')) {\r\n\t\t\tif (!(await checkAdmin(req, url))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\tconst allSessions = await store.getSessions();\r\n\t\t\tconst sessions = resolveOnlineSessions($asai, hostdir, allSessions);\r\n\t\t\treturn sendSuccess(\r\n\t\t\t\tres,\r\n\t\t\t\t{\r\n\t\t\t\t\tsessions: sessions.map((s) => ({\r\n\t\t\t\t\t\tid: s.id,\r\n\t\t\t\t\t\tus: s.us,\r\n\t\t\t\t\t\tip: s.ip,\r\n\t\t\t\t\t\tcreatedAt: s.createdAt,\r\n\t\t\t\t\t\texpiresAt: s.expiresAt,\r\n\t\t\t\t\t\tlastActivityAt: s.lastActivityAt,\r\n\t\t\t\t\t\tonline: true,\r\n\t\t\t\t\t})),\r\n\t\t\t\t},\r\n\t\t\t\topt,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/list/')) {\r\n\t\t\tif (!(await checkAdmin(req, url))) {\r\n\t\t\t\tlogSecurityEvent($asai, { type: 'ACCESS_DENIED', path: url, method: 'GET', ip });\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\tconst users = await store.listUsers();\r\n\t\t\treturn sendSuccess(res, { users: users.map((u) => publicUser($asai, u)) }, opt);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/admin/quota/')) {\r\n\t\t\tif (!(await checkAdmin(req, url))) {\r\n\t\t\t\treturn sendErr(res, 'AUTH_FORBIDDEN', undefined, opt);\r\n\t\t\t}\r\n\t\t\tawait purgeOfflineSessions($asai, hostdir, store);\r\n\t\t\tconst onlineCount = await countOnlineSessions($asai, hostdir, store);\r\n\t\t\tconst quota = getQuota($asai);\r\n\t\t\treturn sendSuccess(\r\n\t\t\t\tres,\r\n\t\t\t\t{\r\n\t\t\t\t\tsessions: onlineCount,\r\n\t\t\t\t\tmaxLoginSessions: quota.maxLoginSessions ?? 100,\r\n\t\t\t\t\tquotaEnabled: !!quota.enabled,\r\n\t\t\t\t\thttp: $asai.connectionshttp,\r\n\t\t\t\t\tws: $asai.connectionsws,\r\n\t\t\t\t},\r\n\t\t\t\topt,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tif (url.startsWith('/api/user/login/profile/')) {\r\n\t\t\tconst us = req?.Userinfo?.[0];\r\n\t\t\tif (!us) return sendErr(res, 'AUTH_UNAUTHORIZED', undefined, opt);\r\n\t\t\tconst user = await store.findByUsername(String(us));\r\n\t\t\treturn sendSuccess(res, { user: user ? publicUser($asai, user) : null }, opt);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { post, get };\r\n};\r\n","import logManage from \"./common/logmanage\";\r\nimport interventionLog from \"./common/interventionlog\";\r\nimport unifiedLog from \"./common/unifiedlog\";\r\nimport errorcodes from \"./common/errorcodes\";\r\nimport sqliteManage from \"./common/sqlitemanage\";\r\nimport health from \"./common/health\";\r\nimport userLogin from \"./login/index\";\r\n\r\nexport default {\r\n \"asailog/manage\": logManage,\r\n \"asailog/intervention\": interventionLog,\r\n \"asailog/store\": unifiedLog,\r\n \"sys/errorcodes\": errorcodes,\r\n \"sys/health\": health,\r\n \"asaisqlite/manage\": sqliteManage,\r\n \"user/login\": userLogin,\r\n};\r\n","export default {\n ctxErr(ec: string, params?: string | string[] | null, _opt: any = null) {\n const pm =\n params == null\n ? undefined\n : Array.isArray(params)\n ? params.map(String)\n : [String(params)];\n return { code: 907, data: { ec, pm } };\n },\n ctxFail(val: any, opt: any = null) {\n if (val && typeof val === 'object' && typeof val.ec === 'string') {\n return { code: 907, data: val };\n }\n if (val instanceof Error) {\n val = val.message || String(val);\n } else if (val && typeof val === 'object' && typeof val.message === 'string') {\n val = val.message;\n }\n return { code: 907, data: val };\n },\n ctxEmpty(val: string, opt: any = null) {\n return { code: 908, data: val };\n },\n ctxSuccess(val: any, opt: any = null) {\n if (typeof opt?.resAES === 'function') {\n val = opt.resAES(val);\n }\n return { code: 909, data: val };\n },\n getPath(str: string = '-') {\n return str?.replace(/[^a-zA-Z0-9.\\-_\\\\\\/]/g, '');\n },\n getName(str: string = '-') {\n return str?.replace(/[^a-zA-Z0-9.\\-_]/g, '');\n },\n\n toDirPath(relativePath: string) {\n const pathArr = relativePath.split('/');\n pathArr.pop();\n const dirPath = pathArr.join('/') + '//';\n return dirPath;\n },\n toAbsolutePath(relativePath: string) {\n relativePath = process.cwd() + relativePath;\n relativePath = relativePath.replace(/\\\\/g, '/');\n return relativePath;\n },\n //创建多层文件夹 同步\n ensureDir(fs: any, relativePath: string) {\n const absPathDir = this.toDirPath(relativePath);\n const absPath = this.toAbsolutePath(relativePath);\n if (!fs.existsSync(absPath)) {\n let pathTmp: string = '';\n absPathDir.split('/').forEach((el: string) => {\n if (el) {\n if (pathTmp) {\n pathTmp += '/';\n }\n pathTmp += el;\n if (!fs.existsSync(pathTmp)) {\n if (!fs.mkdirSync(pathTmp, { recursive: true })) {\n return absPath;\n }\n }\n }\n });\n }\n return absPath;\n },\n makeDir(fs: any, filePaths: string) {\n return new Promise((resolve, reject) => {\n try {\n const newPath = this.ensureDir(fs, filePaths);\n resolve(newPath);\n } catch (err: any) {\n reject(err);\n }\n });\n },\n getFilePath(str: string = '-') {\n let filePath = '';\n let filePaths = '';\n if (str.startsWith('/')) {\n // 这个情况,替换文件,如果需要解析的话,需要自己前端处理\n filePath = this.getPath(str);\n } else if (str.indexOf('/') > -1) {\n // 不安全的!!!\n if (str.startsWith('../')) {\n filePath = this.getPath('/' + str);\n } else {\n filePath = '/webdata/upload/' + this.getPath(str);\n }\n } else {\n filePath = '/webdata/upload/' + this.getName(str);\n }\n filePaths = this.toAbsolutePath(filePath);\n return { filePath, filePaths };\n },\n // 防抖与节流\n // debounce(() => {}, {\n // timeout: null,\n // starttime: 0,\n // endtime: 0,\n // wait: 300,\n // immediate: false,\n // });\n dtImmediate(fn: any, opt: any) {\n if (opt?.immediate) {\n // 立即执行一次\n fn();\n opt.immediate = false;\n }\n },\n dtClearTimeout(opt: any) {\n clearTimeout(opt.timeout);\n opt.timeout = null;\n },\n dtSetTimeout(fn: any, opt: any) {\n return setTimeout(() => {\n fn();\n this.dtClearTimeout(opt);\n }, opt.wait);\n },\n // 防抖:连续触发过程中,仅在数据持续指定长度时间不变时fn一次\n debounce(fn: any, opt: any) {\n this.dtImmediate(fn, opt);\n opt.endtime = new Date().valueOf();\n if (opt.endtime - opt.starttime < opt.wait) {\n this.dtClearTimeout(opt);\n }\n if (!opt?.timeout) {\n opt.starttime = opt.endtime;\n opt.timeout = this.dtSetTimeout(fn, opt);\n }\n },\n // 节流:指定长度时间内有多次触发,只fn最后一次触发\n throttle(fn: any, opt: any) {\n this.dtImmediate(fn, opt);\n if (!opt?.timeout) {\n opt.timeout = this.dtSetTimeout(fn, opt);\n }\n },\n /**\n * 简化版\n * @param startsWord 定义起始字符,如:as\n * @param hex 指定进制,如:10 16 32\n * @returns 12位,前缀字符+时间戳换算+随机数补位,如:eelgullaqnb0\n */\n Uuid(startsWord: string = '', index: number = 0, hex: number = 32): string {\n let ids: string = Date.now().toString(36);\n if (index > 0) {\n ids += index.toString(36);\n }\n ids = ids.slice(-9);\n if (startsWord) {\n ids = startsWord.slice(-3) + ids;\n }\n let strLen: number = ids.length;\n while (strLen < 16) {\n ids += ((Math.random() * hex) | 0).toString(hex).slice(-1);\n strLen++;\n }\n return ids;\n },\n getIp(req: any) {\n const forwarded = req.headers['x-forwarded-for'];\n return forwarded ? forwarded.split(',')[0] : req.connection.remoteAddress;\n },\n};\n","export default {\r\n // 加密\r\n asencode(str: string, keys: string) {\r\n const strlen: number = str?.length || 0;\r\n const keyslen: number = keys?.length || 0;\r\n let newstr: string = '';\r\n for (let i = 0; i < strlen; i++) {\r\n const rnum: number = Math.round(Math.random() * 1000) % keyslen;\r\n const rnumx: number = Number(rnum.toString().slice(-1)) + 1;\r\n const ylen: number = keyslen - rnumx;\r\n let tmpnum = str.codePointAt(i) as number;\r\n const y1: number = tmpnum % ylen;\r\n tmpnum = (tmpnum - y1) / ylen;\r\n const y2: number = tmpnum % ylen;\r\n tmpnum = (tmpnum - y2) / ylen;\r\n newstr +=\r\n keys[(tmpnum % ylen) + rnumx] +\r\n keys[y2 + rnumx] +\r\n keys[y1 + rnumx] +\r\n keys.charAt(rnum);\r\n }\r\n return newstr;\r\n },\r\n\r\n // 解密\r\n asdecode(str: string, keys: string) {\r\n try {\r\n const strlen: number = str.length;\r\n const keyslen: number = keys.length;\r\n let newstr: string = '';\r\n for (let i = 0; i < strlen; i++) {\r\n const rnum: number = keys.indexOf(str[i + 3]);\r\n const rnumx: number = Number(rnum.toString().slice(-1)) + 1;\r\n const ylen: number = keyslen - rnumx;\r\n newstr += String?.fromCodePoint(\r\n (keys.indexOf(str[i++]) - rnumx) * ylen * ylen +\r\n (keys.indexOf(str[i++]) - rnumx) * ylen +\r\n (keys.indexOf(str[i++]) - rnumx)\r\n );\r\n }\r\n return newstr;\r\n } catch (error) {\r\n return '';\r\n }\r\n },\r\n getCodeData(data: any, keys: string) {\r\n try {\r\n data = JSON.parse(data);\r\n return JSON.parse(\r\n this.asdecode(data.data, this.asdecode(data.code, keys))\r\n );\r\n } catch (error) {\r\n return;\r\n }\r\n },\r\n sendCodeData(data: any, keys: string, code: string) {\r\n return {\r\n code: code,\r\n data: this.asencode(\r\n JSON.stringify(data),\r\n this.asdecode(code, keys)\r\n ),\r\n };\r\n },\r\n // 打乱字符\r\n asnewkey(str: string) {\r\n const newarr: string[] = [];\r\n str.split('').forEach((el: string) => {\r\n newarr.splice(Math.round(Math.random() * newarr.length), 0, el);\r\n });\r\n return newarr.join('');\r\n },\r\n};\r\n","import crypto from 'crypto';\r\n\r\nexport default ($asai: any, cfg: any = null) => {\r\n const AES_KEY = Buffer.from($asai.hostconfig.aes.keybase64, 'base64');\r\n const AES_AAD = Buffer.from($asai.hostconfig.aes.aad, 'utf8');\r\n\r\n function safeJsonParse(value: any) {\r\n if (typeof value !== 'string') return value;\r\n try {\r\n return JSON.parse(value);\r\n } catch {\r\n return value;\r\n }\r\n }\r\n\r\n function decodeBase64(value: string): Buffer {\r\n if (typeof value !== 'string') {\r\n throw new TypeError('Expected base64 string.');\r\n }\r\n return Buffer.from(value, 'base64');\r\n }\r\n\r\n function encrypt(plaintext: string) {\r\n const iv = crypto.randomBytes($asai.hostconfig.aes.ivlength);\r\n const cipher = crypto.createCipheriv($asai.hostconfig.aes.algorithm, AES_KEY, iv);\r\n cipher.setAAD(AES_AAD);\r\n const encryptedBuffer = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\r\n return {\r\n data: encryptedBuffer.toString('base64'),\r\n iv: iv.toString('base64'),\r\n auth: cipher.getAuthTag().toString('base64')\r\n };\r\n }\r\n\r\n function decrypt(encrypto: any) {\r\n const iv = decodeBase64(encrypto.iv);\r\n const authTag = decodeBase64(encrypto.auth);\r\n const encrypted = decodeBase64(encrypto.data);\r\n const decipher = crypto.createDecipheriv($asai.hostconfig.aes.algorithm, AES_KEY, iv);\r\n decipher.setAAD(AES_AAD);\r\n decipher.setAuthTag(authTag);\r\n const decryptedBuffer = Buffer.concat([decipher.update(encrypted), decipher.final()]);\r\n return decryptedBuffer.toString('utf8');\r\n }\r\n\r\n function validateFields(payload: any, fields: string[]) {\r\n return fields.every((key) => typeof payload?.[key] === 'string' && payload[key].length > 0);\r\n }\r\n\r\n function reqAES(opt: any, fn: any = (data: any) => data) {\r\n const reqData = safeJsonParse(opt.data);\r\n try {\r\n if (validateFields(reqData, [\"data\", \"iv\", \"auth\"])) {\r\n let aesData: any = decrypt(reqData)\r\n if (reqData?.aes === 2) {\r\n aesData = JSON.parse(aesData);\r\n }\r\n return fn(aesData);\r\n } else {\r\n return fn(reqData);\r\n }\r\n\t\t} catch (error: any) {\r\n\t\t\tif (validateFields(reqData, ['data', 'iv', 'auth'])) {\r\n\t\t\t\tthrow error;\r\n\t\t\t}\r\n\t\t\treturn fn(reqData);\r\n\t\t}\r\n }\r\n function resAES(data: any) {\r\n try {\r\n let aesty: number = 1;\r\n if (data && typeof data === 'object') {\r\n data = JSON.stringify(data);\r\n aesty = 2;\r\n }\r\n return Object.assign({ aes: aesty }, encrypt(data));\r\n } catch (error: any) {\r\n return data;\r\n }\r\n }\r\n\r\n return { encrypt, decrypt, reqAES, resAES };\r\n};","import { getDataServerForAsDb } from \"../../db/data-store\";\r\n\r\nexport default ($asai: any, cfg: any) => {\r\n const DataServer: any = getDataServerForAsDb($asai, {\r\n type: cfg?.type || \"sqlite\",\r\n opt: {\r\n ...(cfg?.opt || {\r\n database: \"./webdata/webdb/sqlite/asaisqlite.db\",\r\n create: 1,\r\n }),\r\n },\r\n storeKey: cfg?.storeKey,\r\n });\r\n\r\n function reqwherestr(str: any) {\r\n if (cfg?.type === \"sqlite\" || cfg?.type === \"mysql\") {\r\n return `'${str}'`;\r\n }\r\n return str;\r\n }\r\n\r\n function reqfield(queryData: any) {\r\n if (queryData?.fd) {\r\n return queryData.fd.split(\"-\");\r\n }\r\n return cfg.field.data;\r\n }\r\n\r\n function reqwhere(queryData: any) {\r\n const wheretmp: any[] = [];\r\n if ((cfg?.type === \"sqlite\" || cfg?.type === \"mysql\") && queryData?.wlv) {\r\n const wlvarr = queryData.wlv.split(\"-\");\r\n wheretmp.push([wlvarr[0], \">\", Number(wlvarr[1] || 0)]);\r\n }\r\n if (queryData?.fl) {\r\n wheretmp.push([cfg.field.class, \"LIKE\", reqwherestr(`${queryData.fl}%`)]);\r\n }\r\n if (queryData?.ss && queryData?.ssty) {\r\n wheretmp.push([queryData.ssty, \"LIKE\", reqwherestr(`%${queryData.ss}%`)]);\r\n }\r\n if (wheretmp.length > 1) {\r\n wheretmp.unshift(\"and\");\r\n }\r\n return wheretmp;\r\n }\r\n\r\n function reqorder(queryData: any) {\r\n const ordertmp: any[] = [];\r\n if (queryData?.sx) {\r\n ordertmp.push([queryData.sx, queryData?.sxty == 1 ? \"DESC\" : \"ASC\"]);\r\n }\r\n return ordertmp;\r\n }\r\n\r\n function reqlimit(queryData: any) {\r\n let limittmp = \"\";\r\n let limitps: number = queryData?.ps;\r\n if (queryData?.pg) {\r\n limitps = limitps || 20;\r\n limittmp = `${(queryData.pg - 1) * limitps},${limitps}`;\r\n } else if (limitps) {\r\n limittmp += limitps;\r\n }\r\n return limittmp;\r\n }\r\n\r\n function decodePathSegment(seg: string): string {\r\n try {\r\n return decodeURIComponent(seg);\r\n } catch {\r\n return seg;\r\n }\r\n }\r\n\r\n function bareFileName(name: string): string {\r\n const base = String(name).replace(/\\.json$/i, \"\");\r\n const slash = base.lastIndexOf(\"/\");\r\n return slash > -1 ? base.substring(slash + 1) : base;\r\n }\r\n\r\n function parseFileBody(raw: unknown): { name?: string; content: unknown } {\r\n let body: any = raw;\r\n if (typeof body === \"string\") {\r\n try {\r\n body = JSON.parse(body);\r\n } catch {\r\n return { content: body };\r\n }\r\n }\r\n if (body && typeof body === \"object\" && !Array.isArray(body)) {\r\n return {\r\n name: body.name != null ? String(body.name) : undefined,\r\n content: body.content !== undefined ? body.content : body,\r\n };\r\n }\r\n return { content: body };\r\n }\r\n\r\n function fileContentString(content: unknown): string {\r\n if (content == null) return \"\";\r\n if (typeof content === \"string\") return content;\r\n return JSON.stringify(content);\r\n }\r\n\r\n function fileKeyFromSegment(seg: string, bodyName?: string): string {\r\n return bareFileName(decodePathSegment(seg || bodyName || \"\"));\r\n }\r\n\r\n function getSqlParamsByUrl(req: any, opt: any) {\r\n let tmpSqlParams: any;\r\n const reqArr: any = req?.url?.split(\"?\")[0]?.split(\"/\") || [];\r\n const table = (opt?.qrdata?.table || opt?.data?.table || reqArr[3]).replaceAll(\"_\", \"/\");\r\n if (!table) return tmpSqlParams;\r\n\r\n tmpSqlParams = {\r\n type: \"select\",\r\n table,\r\n };\r\n\r\n if (reqArr[5]) {\r\n if (reqArr[4] === \"insert\") {\r\n tmpSqlParams.type = reqArr[4];\r\n if (cfg?.type === \"file\") {\r\n const { name: bodyName, content } = parseFileBody(opt.data);\r\n const fileKey = fileKeyFromSegment(reqArr[5], bodyName);\r\n tmpSqlParams.field = cfg.field.data;\r\n tmpSqlParams.value = [[fileKey, fileContentString(content)]];\r\n } else {\r\n tmpSqlParams.field = [];\r\n tmpSqlParams.value = [];\r\n const tmpValue: any[] = [];\r\n const dbData: any = typeof opt.data === \"string\" ? JSON.parse(opt.data) : opt.data;\r\n Object.entries(dbData).forEach((el: any) => {\r\n if (cfg.field.data.includes(el[0])) {\r\n tmpSqlParams.field.push(el[0]);\r\n tmpValue.push(el[1]);\r\n }\r\n });\r\n if (!tmpSqlParams.field.includes(cfg.field.key)) {\r\n tmpSqlParams.field.push(cfg.field.key);\r\n tmpValue.push(reqArr[5]);\r\n }\r\n tmpSqlParams.value.push(tmpValue);\r\n }\r\n } else if (reqArr[4] === \"update\") {\r\n tmpSqlParams.type = reqArr[4];\r\n const rowKey =\r\n cfg?.type === \"file\"\r\n ? fileKeyFromSegment(reqArr[5])\r\n : decodePathSegment(reqArr[5]);\r\n tmpSqlParams.where = [[cfg.field.key, \"=\", reqwherestr(rowKey)]];\r\n if (cfg?.type === \"file\") {\r\n const { content } = parseFileBody(opt.data);\r\n const contentField = cfg.field.data?.[1] || \"content\";\r\n tmpSqlParams.set = [[contentField, fileContentString(content)]];\r\n } else {\r\n tmpSqlParams.set = [];\r\n const dbData: any = typeof opt.data === \"string\" ? JSON.parse(opt.data) : opt.data;\r\n Object.entries(dbData).forEach((el: any) => {\r\n if (cfg.field.data.includes(el[0])) {\r\n if (Array.isArray(el[1])) {\r\n tmpSqlParams.set.push([el[0], ...el[1]]);\r\n } else {\r\n tmpSqlParams.set.push([el[0], el[1]]);\r\n }\r\n }\r\n });\r\n }\r\n } else if (reqArr[4] === \"delete\") {\r\n tmpSqlParams.type = reqArr[4];\r\n const rowKey =\r\n cfg?.type === \"file\"\r\n ? fileKeyFromSegment(reqArr[5])\r\n : decodePathSegment(reqArr[5]);\r\n tmpSqlParams.where = [[cfg.field.key, \"=\", reqwherestr(rowKey)]];\r\n } else {\r\n if (cfg?.as > 1) {\r\n tmpSqlParams.as = +cfg.as - 1;\r\n }\r\n tmpSqlParams.field = cfg.field.data;\r\n const rowKey =\r\n cfg?.type === \"file\"\r\n ? fileKeyFromSegment(reqArr[5])\r\n : decodePathSegment(reqArr[5]);\r\n tmpSqlParams.where = [[cfg.field.key, \"=\", reqwherestr(rowKey)]];\r\n }\r\n } else {\r\n tmpSqlParams.as = cfg?.as;\r\n tmpSqlParams.field = reqfield(opt.data);\r\n tmpSqlParams.where = reqwhere(opt.data);\r\n tmpSqlParams.order = reqorder(opt.data);\r\n tmpSqlParams.limit = reqlimit(opt.data);\r\n }\r\n\r\n return tmpSqlParams;\r\n }\r\n\r\n function dbFresh(req: any, resdb: any) {\r\n if (req?.url?.includes(\"/selectlist/\")) {\r\n const list = Array.isArray(resdb) ? resdb : resdb?.data;\r\n if (Array.isArray(list)) {\r\n const names = list.map((el: any) => {\r\n if (typeof el === \"string\") {\r\n const dot = el.lastIndexOf(\".\");\r\n return dot > -1 ? el.substring(0, dot) : el;\r\n }\r\n const rawName = el.name ?? el.file ?? \"\";\r\n let tmpName: string = String(rawName).substring(String(rawName).lastIndexOf(\"/\") + 1);\r\n const dot = tmpName.lastIndexOf(\".\");\r\n return dot > -1 ? tmpName.substring(0, dot) : tmpName;\r\n });\r\n const children = names.map((name: string) => ({ name, path: name }));\r\n if (Array.isArray(resdb)) return { children };\r\n resdb.data = children;\r\n return resdb;\r\n }\r\n }\r\n return resdb;\r\n }\r\n\r\n function normalizeSelectResult(params: any, resdb: any) {\r\n let data = resdb;\r\n if (params?.where?.length && Array.isArray(data) && data.length === 1) {\r\n data = data[0];\r\n }\r\n if (cfg?.type === \"file\" && data && typeof data === \"object\" && !Array.isArray(data)) {\r\n const nameKey = cfg.field?.data?.[0] || \"name\";\r\n const contentKey = cfg.field?.data?.[1] || \"content\";\r\n if (data[nameKey] != null) {\r\n data[nameKey] = bareFileName(String(data[nameKey]));\r\n }\r\n const raw = data[contentKey];\r\n if (typeof raw === \"string\") {\r\n const text = raw.trim();\r\n if (text.startsWith(\"{\") || text.startsWith(\"[\")) {\r\n try {\r\n data[contentKey] = JSON.parse(text);\r\n } catch {\r\n /* keep string */\r\n }\r\n }\r\n }\r\n }\r\n return data;\r\n }\r\n\r\n function dbCodePm(req: any, resdb: any) {\r\n if (req?.Userinfo && req?.Userinfo[2]) {\r\n resdb.data = $asai.$lib.AsCode.asencode(JSON.stringify(resdb.data), req.Userinfo[2]);\r\n }\r\n return resdb;\r\n }\r\n\r\n function runDefaultPost(req: any, res: any, opt: any) {\r\n const params = getSqlParamsByUrl(req, opt);\r\n if (params) {\r\n DataServer.sqlDb(params)\r\n .then((resdb: any) => {\r\n res.end(JSON.stringify($asai.$lib.As.ctxSuccess(dbCodePm(req, dbFresh(req, resdb)), opt)));\r\n })\r\n .catch((errdb: any) => {\r\n const msg = String(errdb?.message || errdb || \"\");\r\n if (params?.type === \"select\" && msg.includes(\"no such table\")) {\r\n res.end(JSON.stringify($asai.$lib.As.ctxSuccess([], opt)));\r\n return;\r\n }\r\n res.end(JSON.stringify($asai.$lib.As.ctxFail(errdb)));\r\n });\r\n } else {\r\n res.end(JSON.stringify({ code: 901 }));\r\n }\r\n }\r\n\r\n function runDefaultGet(req: any, res: any, opt: any) {\r\n const params = getSqlParamsByUrl(req, opt);\r\n if (params && typeof DataServer.sqlDb === \"function\") {\r\n try {\r\n DataServer.sqlDb(params)\r\n .then((resdb: any) => {\r\n let resData: any = normalizeSelectResult(params, dbFresh(req, resdb));\r\n if (params?.as === 2 && params?.field?.length > 1) {\r\n let limitArr: any[] = [];\r\n if (params.limit?.split(\",\")?.length < 2) {\r\n limitArr = [0, +params.limit?.split(\",\")?.[0]];\r\n } else {\r\n limitArr = params.limit.split(\",\");\r\n limitArr = [+limitArr[0], +limitArr[0] + +limitArr[1]];\r\n }\r\n if (resData.data?.length) {\r\n resData.data = resData.data.slice(+limitArr[0], +limitArr[1]);\r\n }\r\n }\r\n resData = dbCodePm(req, resData);\r\n res.end(JSON.stringify($asai.$lib.As.ctxSuccess(resData, opt)));\r\n })\r\n .catch((errdb: any) => {\r\n const msg = String(errdb?.message || errdb || \"\");\r\n if (params?.type === \"select\" && msg.includes(\"no such table\")) {\r\n res.end(JSON.stringify($asai.$lib.As.ctxSuccess([], opt)));\r\n return;\r\n }\r\n res.end(JSON.stringify($asai.$lib.As.ctxFail(errdb)));\r\n });\r\n } catch {\r\n res.end(JSON.stringify({ code: 901 }));\r\n }\r\n } else {\r\n res.end(JSON.stringify({ code: 901 }));\r\n }\r\n }\r\n\r\n function post(req: any, res: any, hostdir: string, opt: any) {\r\n if (cfg?.post && typeof cfg.post === \"function\") {\r\n Promise.resolve(cfg.post(req, res, hostdir, opt, DataServer))\r\n .then((reqstat) => {\r\n if (!reqstat) runDefaultPost(req, res, opt);\r\n })\r\n .catch((errdb: any) => {\r\n res.end(JSON.stringify($asai.$lib.As.ctxFail(errdb)));\r\n });\r\n return;\r\n }\r\n runDefaultPost(req, res, opt);\r\n }\r\n\r\n function get(req: any, res: any, hostdir: string, opt: any) {\r\n if (cfg?.get && typeof cfg.get === \"function\") {\r\n Promise.resolve(cfg.get(req, res, hostdir, opt, DataServer))\r\n .then((reqstat) => {\r\n if (!reqstat) runDefaultGet(req, res, opt);\r\n })\r\n .catch((errdb: any) => {\r\n res.end(JSON.stringify($asai.$lib.As.ctxFail(errdb)));\r\n });\r\n return;\r\n }\r\n runDefaultGet(req, res, opt);\r\n }\r\n\r\n return { DataServer, post, get };\r\n};\r\n","export default ($asai: any) => {\n /** tsx 下 CJS/ESM 互操作时 default 导出常在 .default 上 */\n function hostDefault<T>(mod: T): T {\n if (mod && typeof mod === \"object\" && \"default\" in (mod as object)) {\n const d = (mod as unknown as { default: T }).default;\n if (d !== undefined) return d;\n }\n return mod;\n }\n /**\n * 从请求选项中提取文件路径\n */\n function getPathFromOpt(opt: any): string {\n const rawPath = opt.qrdata?.path || opt.data?.path;\n return decodeURIComponent(rawPath);\n }\n\n /**\n * 发送成功响应\n */\n function sendSuccess(res: any, data: any, opt: any) {\n const response = $asai.$lib.As.ctxSuccess(data, opt);\n res.end(JSON.stringify(response));\n }\n\n /**\n * 发送结构化错误码响应(data: { ec, pm? })\n */\n function sendErr(res: any, ec: string, params?: string | string[], opt?: any) {\n const ErrorCode = $asai.$lib?.ErrorCode;\n ErrorCode?.loadErrorCodes?.($asai);\n ErrorCode?.logError?.($asai, ec, Array.isArray(params) ? params.map(String) : params != null ? [String(params)] : undefined);\n const response = $asai.$lib.As.ctxErr(ec, params, opt);\n res.end(JSON.stringify(response));\n }\n\n /**\n * 发送失败响应(兼容字符串;已注册错误码自动转为 { ec })\n */\n function sendFail(res: any, err: any, opt?: any) {\n const ErrorCode = $asai.$lib?.ErrorCode;\n ErrorCode?.loadErrorCodes?.($asai);\n const normalized = ErrorCode?.normalizeErrPayload?.(err);\n if (normalized?.ec) {\n return sendErr(res, normalized.ec, normalized.pm, opt);\n }\n const response = $asai.$lib.As.ctxFail(err);\n res.end(JSON.stringify(response));\n }\n\n /**\n * 统一日志输出(前缀 ➦ 标识来自 jsonmanage 模块)\n */\n function mnLog(...arg: any) {\n ($asai?.$log || console.log)(...arg);\n }\n return { hostDefault, getPathFromOpt, sendSuccess, sendFail, sendErr, mnLog };\n};\n","/**\r\n * 原生 fs 工具,供 app / work / host 共用\r\n */\r\nimport fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\n\r\n/** 确保父目录存在;文件不存在时创建空文件 */\r\nexport async function ensureFile(filePath: string): Promise<void> {\r\n const normalized = path.normalize(filePath);\r\n await fs.mkdir(path.dirname(normalized), { recursive: true });\r\n const fh = await fs.open(normalized, \"a\");\r\n await fh.close();\r\n}\r\n\r\nexport async function pathExists(filePath: string): Promise<boolean> {\r\n try {\r\n await fs.access(path.normalize(filePath));\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport async function readJson<T = unknown>(filePath: string): Promise<T> {\r\n const raw = await fs.readFile(path.normalize(filePath), \"utf8\");\r\n return JSON.parse(raw) as T;\r\n}\r\n\r\n/** 将相对路径约束在 baseDir 内,防止目录穿越 */\r\nexport function resolvePathUnderBase(baseDir: string, relPath: string): string {\r\n if (!relPath || typeof relPath !== \"string\") {\r\n throw new Error(\"Invalid path\");\r\n }\r\n if (relPath.includes(\"\\0\")) {\r\n throw new Error(\"Invalid path\");\r\n }\r\n const base = path.resolve(baseDir);\r\n const target = path.resolve(base, relPath.replace(/\\\\/g, \"/\"));\r\n const rel = path.relative(base, target);\r\n if (rel.startsWith(\"..\") || path.isAbsolute(rel)) {\r\n throw new Error(\"Path not allowed\");\r\n }\r\n return target;\r\n}\r\n\r\n/** 单层目录列举 */\r\nexport async function readLogDir(dir: string) {\r\n const resolved = path.resolve(dir);\r\n const stats = await fs.stat(resolved);\r\n if (!stats.isDirectory()) {\r\n throw new Error(\"Not a directory\");\r\n }\r\n const dirName = path.basename(resolved);\r\n const entries = await fs.readdir(resolved, { withFileTypes: true });\r\n const children = await Promise.all(\r\n entries.map(async (entry) => {\r\n const fullPath = path.join(resolved, entry.name);\r\n const st = await fs.stat(fullPath);\r\n const dot = entry.name.lastIndexOf(\".\");\r\n const type = entry.isDirectory()\r\n ? \"dir\"\r\n : dot > -1\r\n ? entry.name.substring(dot)\r\n : \"file\";\r\n return {\r\n name: entry.name,\r\n size: st.size,\r\n time: st.mtime.toISOString(),\r\n path: path.normalize(fullPath),\r\n type,\r\n created: st.birthtime.toISOString(),\r\n permissions: st.mode.toString(8).slice(-3),\r\n };\r\n }),\r\n );\r\n return {\r\n name: dirName,\r\n size: stats.size,\r\n time: stats.mtime.toISOString(),\r\n path: path.normalize(resolved),\r\n type: \"dir\",\r\n created: stats.birthtime.toISOString(),\r\n permissions: stats.mode.toString(8).slice(-3),\r\n children,\r\n };\r\n}\r\n\r\n/** 删除文件;ENOENT 时不抛错 */\r\nexport async function removeFile(filePath: string): Promise<void> {\r\n try {\r\n await fs.unlink(path.normalize(filePath));\r\n } catch (err: unknown) {\r\n if ((err as NodeJS.ErrnoException)?.code !== \"ENOENT\") throw err;\r\n }\r\n}\r\n\r\nexport const remove = removeFile;\r\n\r\n/** 写入文本文件 */\r\nexport async function write(filePath: string, content: string): Promise<void> {\r\n const normalized = path.normalize(filePath);\r\n await fs.mkdir(path.dirname(normalized), { recursive: true });\r\n await fs.writeFile(normalized, content, \"utf8\");\r\n}\r\n\r\n/** 读取文本文件 */\r\nexport async function read(filePath: string): Promise<string> {\r\n return fs.readFile(path.normalize(filePath), \"utf8\");\r\n}\r\n\r\n/** 写入 JSON 文件 */\r\nexport async function writeJson(filePath: string, data: unknown): Promise<void> {\r\n await write(filePath, JSON.stringify(data, null, 2));\r\n}\r\n","/**\r\n * 运行时路径解析 — 不依赖 import.meta.url / __dirname\r\n *\r\n * 兼容两种部署:\r\n * 1. pkg 单文件 exe(process.pkg)— 嵌入资源 + exe 同目录外挂\r\n * 2. 开发 / node index.js — 入口脚本目录 + cwd\r\n */\r\nimport * as fs from 'fs';\r\nimport * as nodePath from 'path';\r\n\r\ntype PkgProcess = NodeJS.Process & {\r\n pkg?: { entrypoint?: string; defaultEntrypoint?: string };\r\n};\r\n\r\n/** 是否 pkg 打包运行 */\r\nexport function isPkgRuntime(): boolean {\r\n return typeof (process as PkgProcess).pkg !== 'undefined';\r\n}\r\n\r\n/**\r\n * pkg snapshot 根目录(嵌入的 webclient/index.html、assets 在此)\r\n * 见 https://yao-pkg.github.io/pkg/guide/snapshot-fs\r\n */\r\nexport function getPkgSnapshotDir(): string | undefined {\r\n if (!isPkgRuntime()) return undefined;\r\n const entry =\r\n (process as PkgProcess).pkg?.entrypoint ??\r\n (process as PkgProcess).pkg?.defaultEntrypoint;\r\n if (!entry) return undefined;\r\n return nodePath.resolve(nodePath.dirname(entry));\r\n}\r\n\r\n/** 进程入口脚本所在目录(tsx / node;pkg 下为 snapshot 内 index.js 目录) */\r\nexport function getEntryDir(): string {\r\n const snapshot = getPkgSnapshotDir();\r\n if (snapshot) return snapshot;\r\n\r\n const entry = process.argv[1];\r\n if (!entry) {\r\n return nodePath.dirname(process.execPath);\r\n }\r\n return nodePath.resolve(nodePath.dirname(entry));\r\n}\r\n\r\n/** exe / node 可执行文件所在目录(外挂 websys/webclient 常在此) */\r\nexport function getExecDir(): string {\r\n return nodePath.dirname(process.execPath);\r\n}\r\n\r\n/**\r\n * 静态/配置查找的全部基路径(去重)\r\n * 按优先级:cwd → exe 旁 → snapshot(pkg 嵌入资源,最后作兜底)\r\n */\r\nexport function getRuntimeBaseDirs(): string[] {\r\n const bases: string[] = [];\r\n const seen = new Set<string>();\r\n const add = (p: string | undefined) => {\r\n if (!p) return;\r\n const abs = nodePath.resolve(p);\r\n if (!seen.has(abs)) {\r\n seen.add(abs);\r\n bases.push(abs);\r\n }\r\n };\r\n\r\n add(process.cwd());\r\n add(getExecDir());\r\n\r\n if (isPkgRuntime()) {\r\n add(getPkgSnapshotDir());\r\n } else {\r\n const entryDir = getEntryDir();\r\n if (entryDir !== getExecDir()) {\r\n add(entryDir);\r\n }\r\n }\r\n\r\n return bases;\r\n}\r\n\r\n/** 首选 webserver 根:优先含 websys 的基路径,否则 exe 旁或入口目录 */\r\nexport function getPrimaryServerRoot(): string {\r\n for (const base of getRuntimeBaseDirs()) {\r\n try {\r\n if (fs.statSync(nodePath.join(base, 'websys')).isDirectory()) {\r\n return base;\r\n }\r\n } catch {\r\n /* try next */\r\n }\r\n }\r\n if (isPkgRuntime()) {\r\n return getExecDir();\r\n }\r\n return getEntryDir();\r\n}\r\n","import As from \"./common/As\";\r\nimport AsCode from \"./common/AsCode\";\r\nimport AsAES from \"./common/AsAES\";\r\nimport AsDb from \"./common/AsDb\";\r\nimport reqWork from \"./common/reqWork\";\r\nimport ErrorCode from \"./common/ErrorCode\";\r\nimport * as AsFs from \"./common/AsFs\";\r\nimport * as AsPath from \"./common/AsPath\";\r\nimport * as InterventionLog from \"./common/InterventionLog\";\r\nimport * as LogStore from \"./common/LogStore\";\r\nimport * as InterventionHooks from \"./common/intervention-hooks\";\r\n\r\nexport default {\r\n As,\r\n AsCode,\r\n AsAES,\r\n AsDb,\r\n AsFs,\r\n AsPath,\r\n reqWork,\r\n ErrorCode,\r\n InterventionLog,\r\n LogStore,\r\n InterventionHooks,\r\n};\r\n","import * as path from 'path';\r\nimport type Idb from './type';\r\n\r\n/** 统一对外接口(各驱动至少实现 sqlDb) */\r\nexport interface DbInstance {\r\n sqlDb(sql: Idb): Promise<unknown>;\r\n}\r\n\r\n/** 支持回调查询的驱动接口 */\r\nexport interface QueryableDb extends DbInstance {\r\n query(sql: Idb, callback: (err: string | null, result: unknown) => void): void;\r\n}\r\n\r\n/** 将 query 回调风格封装为 Promise,并统一空结果处理 */\r\nexport function promisifySqlDb(\r\n query: QueryableDb['query'],\r\n sql: Idb\r\n): Promise<unknown> {\r\n return new Promise((resolve, reject) => {\r\n query(sql, (err, result) => {\r\n if (err) {\r\n reject(err);\r\n return;\r\n }\r\n if (!result || (Array.isArray(result) && result.length === 0)) {\r\n resolve('');\r\n return;\r\n }\r\n resolve(result);\r\n });\r\n });\r\n}\r\n\r\n/** 将 Idb.field 规范为字符串数组 */\r\nexport function toFieldArray(field: Idb['field']): string[] {\r\n if (!field) return [];\r\n return typeof field === 'string' ? field.split(',') : field;\r\n}\r\n\r\n/** 将 Idb.where 规范为 Excel 等值条件 [字段, 值][] */\r\nexport function toWherePairs(where: Idb['where']): [string, unknown][] {\r\n if (!where || !Array.isArray(where)) return [];\r\n const pairs: [string, unknown][] = [];\r\n for (const item of where) {\r\n if (typeof item === 'string') continue;\r\n if (Array.isArray(item) && item.length >= 3) {\r\n pairs.push([item[0], item[2]]);\r\n }\r\n }\r\n return pairs;\r\n}\r\n\r\n/** 将 Idb.set 规范为键值对象 */\r\nexport function toSetObject(set: Idb['set']): Record<string, unknown> {\r\n if (!set) return {};\r\n if (typeof set === 'string') return {};\r\n const obj: Record<string, unknown> = {};\r\n for (const item of set) {\r\n if (typeof item === 'string') continue;\r\n if (Array.isArray(item)) {\r\n if (item.length >= 3 && typeof item[1] === 'string') {\r\n obj[item[0]] = item[2];\r\n } else if (item.length >= 2) {\r\n obj[item[0]] = item[1];\r\n }\r\n }\r\n }\r\n return obj;\r\n}\r\n\r\n/** 将 Idb.value 与 field 组合为插入行对象数组 */\r\nexport function toInsertRows(sql: Idb): Record<string, unknown>[] {\r\n const fields = toFieldArray(sql.field);\r\n const values = sql.value;\r\n if (!fields.length || !Array.isArray(values)) return [];\r\n return (values as unknown[][]).map((row) => {\r\n const rowObj: Record<string, unknown> = {};\r\n fields.forEach((field, index) => {\r\n rowObj[field] = row[index];\r\n });\r\n return rowObj;\r\n });\r\n}\r\n\r\n/**\r\n * 判断目标路径是否在基准目录内(跨平台:Win/Linux/macOS)\r\n * 使用 path.resolve + path.relative,兼容正反斜杠与不同盘符\r\n */\r\nexport function isPathInside(baseDir: string, targetPath: string): boolean {\r\n const base = path.resolve(baseDir);\r\n const target = path.resolve(targetPath);\r\n const relative = path.relative(base, target);\r\n if (!relative) return true;\r\n return !relative.startsWith('..') && !path.isAbsolute(relative);\r\n}\r\n\r\n/**\r\n * 拼接 table 相对路径(始终使用 /,与 API 路由约定一致)\r\n * path.resolve 在 Win/Linux/macOS 上均支持正斜杠\r\n */\r\nexport function joinTablePath(table: string, ...segments: string[]): string {\r\n const parts = [table.replace(/\\\\/g, '/'), ...segments.map((s) => String(s).replace(/\\\\/g, '/'))];\r\n return parts.filter(Boolean).join('/');\r\n}\r\n\r\n/** 判断 field 定义中是否已包含 id 列(兼容字符串 includes 语义) */\r\nexport function fieldHasId(field: Idb['field']): boolean {\r\n if (!field) return false;\r\n if (typeof field === 'string') return field.includes('id');\r\n return field.includes('id');\r\n}\r\n\r\n/** 判断错误是否为「表不存在」类错误 */\r\nexport function isTableMissingError(err: { code?: string; message?: string } | null | undefined): boolean {\r\n if (!err) return false;\r\n const msg = err.message || '';\r\n if (err.code === 'ER_NO_SUCH_TABLE' || err.code === 'SQLITE_ERROR') {\r\n return msg.includes('no such table') || msg.includes(\"doesn't exist\");\r\n }\r\n return msg.includes('no such table') || msg.includes(\"doesn't exist\");\r\n}\r\n","import type Idb from './type';\r\nimport { fieldHasId, toFieldArray } from './common';\r\n\r\ntype JoinType = 'where' | 'order' | 'value' | 'set' | 'field';\r\n\r\n/** 为表名加引号,避免 SQLite 保留字(如 order)导致语法错误 */\r\nfunction quoteTable(table: string): string {\r\n const safe = String(table).replace(/\"/g, '\"\"');\r\n return `\"${safe}\"`;\r\n}\r\n\r\n/** 拼接 WHERE 子句(支持 or/and 链式条件) */\r\nfunction buildWhereClause(where: NonNullable<Idb['where']>): string {\r\n if (!Array.isArray(where) || !where.length) return '';\r\n\r\n const parts: string[] = [];\r\n let connector = 'and';\r\n\r\n for (let i = 0; i < where.length; i++) {\r\n const item = where[i];\r\n if (item === 'or' || item === 'and') {\r\n connector = item;\r\n continue;\r\n }\r\n if (!Array.isArray(item)) continue;\r\n const [field, op, val] = item as [string, string, unknown];\r\n if (!parts.length) {\r\n parts.push(`${field} ${op} ${val}`);\r\n } else {\r\n parts.push(`${connector} ${field} ${op} ${val}`);\r\n }\r\n }\r\n\r\n return parts.length ? ` where ${parts.join(' ')}` : '';\r\n}\r\n\r\n/** 拼接 ORDER BY 子句 */\r\nfunction buildOrderClause(order: NonNullable<Idb['order']>): string {\r\n if (!Array.isArray(order) || !order.length) return '';\r\n const items = order.map((el, i) => {\r\n const prefix = i > 0 ? ',' : '';\r\n return `${prefix} ${el[0]} ${el[1]}`;\r\n });\r\n return ` order by${items.join('')}`;\r\n}\r\n\r\n/** 将单个 INSERT 单元格格式化为 SQL 字面量(兼容 qStr 预加引号与 qNum 裸数字) */\r\nfunction formatInsertCell(value: unknown): string {\r\n if (value == null) return \"''\";\r\n const s = String(value);\r\n if (/^-?\\d+(\\.\\d+)?$/.test(s)) return s;\r\n if (s.startsWith(\"'\") && s.endsWith(\"'\")) return s;\r\n return `'${s.replace(/'/g, \"''\")}'`;\r\n}\r\n\r\n/** 拼接 INSERT VALUES 子句,如 values ('a','1'),('b','2') */\r\nfunction buildValueClause(values: NonNullable<Idb['value']>): string {\r\n if (!Array.isArray(values) || !values.length) return '';\r\n const rows = (values as unknown[][]).map((row) => `(${row.map(formatInsertCell).join(',')})`);\r\n return ` values ${rows.join(',')}`;\r\n}\r\n\r\n/** 拼接 UPDATE SET 子句 */\r\nfunction buildSetClause(sets: NonNullable<Idb['set']>): string {\r\n if (!Array.isArray(sets) || !sets.length) return '';\r\n\r\n const parts = sets.map((item, i) => {\r\n const prefix = i > 0 ? ',' : '';\r\n const el = item as [string, unknown, unknown?];\r\n const [field, opOrVal, val] = el;\r\n\r\n if (typeof val === 'number' && opOrVal) {\r\n return `${prefix}${field}=${field}${opOrVal}${val}`;\r\n }\r\n if (typeof val === 'string' && opOrVal) {\r\n if (opOrVal === 'CONCAT') {\r\n return `${prefix}${field}=${opOrVal}(${field},'${val}')`;\r\n }\r\n return `${prefix}${field}=${field}${opOrVal}'${val}'`;\r\n }\r\n if (typeof opOrVal === 'number') {\r\n return `${prefix}${field}=${opOrVal}`;\r\n }\r\n return `${prefix}${field}='${opOrVal}'`;\r\n });\r\n\r\n return ` set ${parts.join('')}`;\r\n}\r\n\r\n/** 拼接字段列表 (a,b,c) */\r\nfunction buildFieldClause(fields: NonNullable<Idb['field']>): string {\r\n const list = toFieldArray(fields);\r\n return list.length ? ` (${list.join(',')})` : '';\r\n}\r\n\r\nexport default {\r\n /**\r\n * 将 Idb 中的指定片段转为 SQL 字符串片段\r\n */\r\n joinSql(sql: Idb, type: JoinType): string {\r\n const val = sql[type];\r\n if (Array.isArray(val)) {\r\n if (!val.length) return '';\r\n switch (type) {\r\n case 'where':\r\n return buildWhereClause(val as NonNullable<Idb['where']>);\r\n case 'order':\r\n return buildOrderClause(val as NonNullable<Idb['order']>);\r\n case 'value':\r\n return buildValueClause(val as NonNullable<Idb['value']>);\r\n case 'set':\r\n return buildSetClause(val as NonNullable<Idb['set']>);\r\n case 'field':\r\n return buildFieldClause(val as NonNullable<Idb['field']>);\r\n }\r\n }\r\n if (!val) return '';\r\n\r\n const raw = String(val);\r\n switch (type) {\r\n case 'where':\r\n return ` where ${raw}`;\r\n case 'order':\r\n return ` order by ${raw}`;\r\n case 'value':\r\n return ` values (${raw})`;\r\n case 'set':\r\n return ` set ${raw}`;\r\n case 'field':\r\n return ` (${raw})`;\r\n default:\r\n return '';\r\n }\r\n },\r\n\r\n /**\r\n * 将完整 Idb 对象转换为可执行 SQL 字符串\r\n * 注意:值为字符串拼接,调用方需确保输入可信或自行转义\r\n */\r\n makeSql(sql: Idb): string {\r\n const table = quoteTable(sql.table);\r\n const op = sql.type;\r\n switch (op) {\r\n case 'insert':\r\n return `insert into ${table}${this.joinSql(sql, 'field')}${this.joinSql(sql, 'value')}`;\r\n case 'delete':\r\n return `delete from ${table}${this.joinSql(sql, 'where')}`;\r\n case 'update':\r\n return `update ${table}${this.joinSql(sql, 'set')}${this.joinSql(sql, 'where')}`;\r\n case 'select': {\r\n const fields = sql.field ? ` ${sql.field}` : ' *';\r\n const limit = sql.limit ? ` limit ${sql.limit}` : '';\r\n return `select${fields} from ${table}${this.joinSql(sql, 'where')}${this.joinSql(sql, 'order')}${limit}`;\r\n }\r\n default:\r\n return op;\r\n }\r\n },\r\n\r\n /**\r\n * 生成建表 SQL(自动补 id 主键与 asdate 时间戳列)\r\n */\r\n createSql(sql: Idb, dialect: 'mysql' | 'sqlite' | string = 'mysql'): string {\r\n const autoId = dialect === 'sqlite' ? 'AUTOINCREMENT' : 'AUTO_INCREMENT';\r\n const fields = toFieldArray(sql.field);\r\n const columns: string[] = [];\r\n\r\n if (!fieldHasId(sql.field)) {\r\n columns.push(`id INTEGER PRIMARY KEY ${autoId}`);\r\n }\r\n fields.forEach((name) => columns.push(`${name} text`));\r\n const asdateCol =\r\n dialect === 'sqlite' ? 'asdate text DEFAULT CURRENT_TIMESTAMP' : 'asdate text default(CURRENT_TIMESTAMP)';\r\n columns.push(asdateCol);\r\n\r\n return `create table if not exists ${quoteTable(sql.table)} (${columns.join(',')})`;\r\n },\r\n};\r\n","import * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport type { DbInstance } from '../common';\r\n\r\nfunction dbDriver(opt: any = {}): new (config: any) => DbInstance {\r\n type Idb = typeof opt.IdbType;\r\n const { Sql, DbCommon } = opt;\r\n const { isPathInside, joinTablePath } = DbCommon;\r\n interface DbFileConfig {\r\n dir: string; // 数据存储根目录(相对于进程工作目录)\r\n ext?: string; // 文件扩展名,如 \".json\",\".*\" 表示无扩展名\r\n del?: number; // 非 0 表示启用软删除(重命名为 .delete.ext)\r\n create?: boolean; // 是否自动创建不存在的目录\r\n $asai?: any; // 外部注入的日志对象,用于自定义日志输出\r\n }\r\n\r\n class DbFile {\r\n private readonly config: DbFileConfig;\r\n private readonly fileExt: string;\r\n private readonly fileDel: boolean;\r\n private readonly createDir: boolean;\r\n private readonly baseDirAbs: string;\r\n\r\n constructor(config: DbFileConfig) {\r\n this.config = config;\r\n this.fileExt = config.ext === '.*' ? '' : config.ext || '';\r\n this.fileDel = (config.del || 0) !== 0;\r\n this.createDir = config.create || false;\r\n this.baseDirAbs = path.resolve(process.cwd(), config.dir);\r\n }\r\n\r\n private dbLog(...args: any[]) {\r\n (this.config?.$asai?.$log || console.log)('FILE', ...args);\r\n }\r\n\r\n checkFile(file: string): boolean {\r\n return fs.existsSync(this.getAbsPath(file, false));\r\n }\r\n\r\n /** 解析相对路径并限制在数据根目录内,防止路径穿越(跨平台) */\r\n private resolvePath(relPath: string): string {\r\n if (!relPath) {\r\n return this.baseDirAbs;\r\n }\r\n const abs = path.isAbsolute(relPath) ? path.normalize(relPath) : path.resolve(this.baseDirAbs, relPath);\r\n if (!isPathInside(this.baseDirAbs, abs)) {\r\n return this.baseDirAbs;\r\n }\r\n return abs;\r\n }\r\n\r\n /** 将 table 与文件名片段拼为平台无关相对路径 */\r\n private tableFilePath(table: string, ...segments: string[]): string {\r\n return joinTablePath(table, ...segments);\r\n }\r\n\r\n private normalizeRelPath(relPath: string): string {\r\n if (!relPath) {\r\n return '';\r\n }\r\n return path.isAbsolute(relPath) ? path.relative(this.baseDirAbs, relPath) : relPath;\r\n }\r\n\r\n private ensureDir(relPath: string): string {\r\n const relative = this.normalizeRelPath(relPath);\r\n const dirPath = path.dirname(relative);\r\n const absDir = this.resolvePath(dirPath === '.' ? '' : dirPath);\r\n if (this.createDir && !fs.existsSync(absDir)) {\r\n this.dbLog('mkdir', '[MKDIR]', absDir);\r\n fs.mkdirSync(absDir, { recursive: true });\r\n }\r\n return absDir;\r\n }\r\n\r\n private getAbsPath(file: string, autoCreateDir: boolean = true): string {\r\n let rel = file;\r\n if (this.fileExt && !rel.endsWith(this.fileExt)) {\r\n rel += this.fileExt;\r\n }\r\n if (autoCreateDir) {\r\n this.ensureDir(rel);\r\n }\r\n return this.resolvePath(rel);\r\n }\r\n\r\n deldir(relativePath: string): void {\r\n const absPath = this.resolvePath(relativePath);\r\n if (!fs.existsSync(absPath)) {\r\n return;\r\n }\r\n\r\n this.dbLog('delete', '[RMDIR]', absPath);\r\n const entries = fs.readdirSync(absPath, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const current = path.join(absPath, entry.name);\r\n if (entry.isDirectory()) {\r\n this.deldir(path.join(relativePath, entry.name));\r\n } else {\r\n this.dbLog('delete', '[UNLINK]', current);\r\n fs.unlinkSync(current);\r\n }\r\n }\r\n fs.rmdirSync(absPath);\r\n }\r\n\r\n private getReadPath(file: string, sql: Idb): { path: string; dir: string } {\r\n const candidates: Array<{ dir: string }> = [];\r\n\r\n if (sql?.filename) {\r\n candidates.push({ dir: path.join(file, sql.filename) });\r\n candidates.push({ dir: path.join(file + '.delete' + this.fileExt, sql.filename) });\r\n } else {\r\n candidates.push({ dir: file });\r\n candidates.push({ dir: file + this.fileExt + '.delete' });\r\n }\r\n\r\n for (const candidate of candidates) {\r\n const abs = this.getAbsPath(candidate.dir, false);\r\n if (fs.existsSync(abs)) {\r\n return { path: abs, dir: candidate.dir };\r\n }\r\n }\r\n\r\n return { path: '', dir: '' };\r\n }\r\n\r\n private getDelPath(file: string, sql: Idb): { path: string; dir: string } {\r\n const read = this.getReadPath(file, sql);\r\n if (!read.path) {\r\n return { path: '', dir: read.dir };\r\n }\r\n if (sql?.filename) {\r\n return { path: path.dirname(read.path), dir: path.dirname(read.dir) };\r\n }\r\n return { path: read.path, dir: read.dir };\r\n }\r\n\r\n private getNewPath(file: string, sql: Idb): string {\r\n if (sql?.filename) {\r\n return this.getAbsPath(path.join(file, sql.filename), true);\r\n }\r\n return this.getAbsPath(file, true);\r\n }\r\n\r\n write(file: string, data: any, sql: Idb): string | Error {\r\n try {\r\n const filePath = sql?.type === 'insert' ? this.getNewPath(file, sql) : this.getReadPath(file, sql).path || this.getNewPath(file, sql);\r\n this.dbLog('write', '[WRITE]', filePath);\r\n fs.writeFileSync(filePath, data, 'utf8');\r\n return 'ok';\r\n } catch (e) {\r\n this.dbLog('write failed', '[WRITE ERROR]', e);\r\n return e as Error;\r\n }\r\n }\r\n\r\n read(file: string, sql: Idb, encoding: BufferEncoding = 'utf8'): any {\r\n try {\r\n const read = this.getReadPath(file, sql);\r\n if (!read.path) {\r\n return { error: 'empty' };\r\n }\r\n this.dbLog('read', '[READ]', read.path);\r\n const data = fs.readFileSync(read.path, { encoding }) || '';\r\n const fileName = this.fileExt && read.dir.endsWith(this.fileExt) ? read.dir : read.dir + this.fileExt;\r\n return [{ data, file: fileName }];\r\n } catch (e) {\r\n this.dbLog('read failed', '[READ ERROR]', e);\r\n return e;\r\n }\r\n }\r\n\r\n del(file: string, sql: Idb): string | Error {\r\n try {\r\n const del = this.getDelPath(file, sql);\r\n if (!del.path) {\r\n return '';\r\n }\r\n\r\n if (this.fileDel && sql?.deltrue) {\r\n const target = del.path + '.delete' + this.fileExt;\r\n this.dbLog('soft delete', '[SOFT DELETE]', `${del.path} -> ${target}`);\r\n fs.renameSync(del.path, target);\r\n } else if (sql?.filename) {\r\n this.deldir(del.dir);\r\n } else {\r\n this.dbLog('delete', '[DELETE]', del.path);\r\n fs.unlinkSync(del.path);\r\n }\r\n return 'ok';\r\n } catch (e) {\r\n this.dbLog('delete failed', '[DELETE ERROR]', e);\r\n return e as Error;\r\n }\r\n }\r\n\r\n re(file: string, sql: Idb): string | Error {\r\n try {\r\n const del = this.getDelPath(file, sql);\r\n if (!del.path) {\r\n return '';\r\n }\r\n if (this.fileDel) {\r\n const extPattern = this.fileExt ? this.fileExt.replace(/\\./g, '\\\\.') : '';\r\n const original = del.path.replace(new RegExp(`\\.delete${extPattern}$`), '');\r\n if (original !== del.path) {\r\n this.dbLog('restore', '[RESTORE]', `${del.path} -> ${original}`);\r\n fs.renameSync(del.path, original);\r\n }\r\n } else {\r\n this.dbLog('force delete', '[FORCE DELETE]', del.path);\r\n fs.unlinkSync(del.path);\r\n }\r\n return 'ok';\r\n } catch (e) {\r\n this.dbLog('restore failed', '[RESTORE ERROR]', e);\r\n return e as Error;\r\n }\r\n }\r\n\r\n list(dir: string, sql: Idb): any {\r\n try {\r\n const absDir = this.resolvePath(dir);\r\n this.dbLog('list', '[LIST]', absDir);\r\n let entries: fs.Dirent[];\r\n try {\r\n entries = fs.readdirSync(absDir, { withFileTypes: true });\r\n } catch {\r\n return sql?.list ? { open: [], delete: [] } : [];\r\n }\r\n\r\n const result: any = { open: [], delete: [] };\r\n const deleteSuffix = '.delete' + this.fileExt;\r\n for (const entry of entries) {\r\n if (!entry.isFile()) continue;\r\n const fileName = entry.name;\r\n const isDelete = fileName.endsWith(deleteSuffix);\r\n const baseName = isDelete ? fileName.slice(0, -deleteSuffix.length) : fileName;\r\n if (this.fileExt && !baseName.endsWith(this.fileExt)) continue;\r\n const fullPath = path.join(absDir, fileName);\r\n try {\r\n const data = fs.readFileSync(fullPath, 'utf8');\r\n const entryData = { data, file: baseName };\r\n if (isDelete) {\r\n if (sql?.list) result.delete.push(entryData);\r\n } else {\r\n result.open.push(entryData);\r\n }\r\n } catch {\r\n // 单文件读取失败时忽略\r\n }\r\n }\r\n return sql?.list ? result : result.open;\r\n } catch (e) {\r\n this.dbLog('list failed', '[LIST ERROR]', e);\r\n return e;\r\n }\r\n }\r\n\r\n /** 从 where 首条条件中提取文件名(去掉 SQL 风格引号) */\r\n private getFileNameFromWhere(where: Idb['where']): string {\r\n if (!where || !Array.isArray(where)) return '';\r\n const first = where.find((item) => Array.isArray(item)) as [string, string, unknown] | undefined;\r\n const raw = first?.[2];\r\n if (typeof raw === 'string') {\r\n return raw.replace(/^'+|'+$/g, '');\r\n }\r\n return String(raw ?? '');\r\n }\r\n\r\n sqlDb(sql: Idb): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n let result: any;\r\n const tableDir = this.tableFilePath(sql.table);\r\n\r\n if (sql.type === 'insert') {\r\n const [file, data] = (sql.value as string[][])[0];\r\n result = this.write(this.tableFilePath(sql.table, file), data, sql);\r\n } else if (sql.type === 'delete') {\r\n const file = this.getFileNameFromWhere(sql.where);\r\n result = this.del(this.tableFilePath(sql.table, file), sql);\r\n } else if (sql.type === 're') {\r\n const file = this.getFileNameFromWhere(sql.where);\r\n result = this.re(this.tableFilePath(sql.table, file), sql);\r\n } else if (sql.type === 'update') {\r\n const file = this.getFileNameFromWhere(sql.where);\r\n const data = (sql.set as string[][])[0][1];\r\n result = this.write(this.tableFilePath(sql.table, file), data, sql);\r\n } else if (sql.type === 'select') {\r\n if (sql?.where?.length && sql?.as !== 2) {\r\n const file = this.getFileNameFromWhere(sql.where);\r\n const readRes = this.read(this.tableFilePath(sql.table, file), sql);\r\n const resObj: any = {};\r\n if (readRes?.[0]?.file && !readRes.error) {\r\n if (sql.as === 1) {\r\n try {\r\n const parsed = JSON.parse(readRes[0].data);\r\n if (sql.field?.length) {\r\n (sql.field as string[]).forEach((f) => {\r\n resObj[f] = parsed[f] ?? '';\r\n });\r\n } else {\r\n Object.assign(resObj, parsed);\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n } else {\r\n const fields = sql.field as string[];\r\n resObj[fields[0]] = readRes[0].file;\r\n if (fields[1]) {\r\n resObj[fields[1]] = readRes[0].data;\r\n }\r\n }\r\n }\r\n result = [resObj];\r\n } else {\r\n const listRes = this.list(tableDir, sql);\r\n if (listRes && !listRes.error) {\r\n if (sql?.list) {\r\n const mapEntry = (el: any) => {\r\n const fields = sql.field as string[];\r\n const item: any = { [fields[0]]: el.file };\r\n if (fields[1]) item[fields[1]] = el.data;\r\n return item;\r\n };\r\n if (listRes.open) listRes.open = listRes.open.map(mapEntry);\r\n if (listRes.delete) listRes.delete = listRes.delete.map(mapEntry);\r\n result = listRes;\r\n } else {\r\n if (sql?.as === 2) {\r\n let items = listRes;\r\n if (sql.where?.length) {\r\n const where = sql.where;\r\n const whereType = typeof where[0] === 'string' ? where[0] : 'and';\r\n items = items.filter((el: any) => {\r\n let match = whereType === 'and';\r\n for (let i = 0; i < where.length; i++) {\r\n if (typeof where[i] === 'string') continue;\r\n const cond = where[i];\r\n if (!cond) continue;\r\n const field = cond[0];\r\n const searchVal = String(cond[2]).replace(/%/g, '');\r\n let fieldVal = '';\r\n try {\r\n fieldVal = JSON.parse(el.data)[field] ?? '';\r\n } catch {\r\n /* ignore */\r\n }\r\n const condMatch = String(fieldVal).includes(searchVal);\r\n if (whereType === 'and') {\r\n match = match && condMatch;\r\n if (!match) break;\r\n } else {\r\n match = match || condMatch;\r\n if (match) break;\r\n }\r\n }\r\n return match;\r\n });\r\n }\r\n items = items.map((el: any) => {\r\n const obj: any = {};\r\n try {\r\n const parsed = JSON.parse(el.data);\r\n if (sql.field?.length) {\r\n (sql.field as string[]).forEach((f) => {\r\n obj[f] = parsed[f] ?? '';\r\n });\r\n } else {\r\n Object.assign(obj, parsed);\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n return obj;\r\n });\r\n if (sql.order?.length) {\r\n const orderField = sql.order[0];\r\n const orderFieldName = typeof orderField === 'string' ? orderField : orderField[0];\r\n const direction = typeof orderField === 'string' ? 'ASC' : String(orderField[1]).toUpperCase();\r\n items.sort((a: any, b: any) => {\r\n const valA = String(a[orderFieldName] ?? '');\r\n const valB = String(b[orderFieldName] ?? '');\r\n const cmp = valA.localeCompare(valB);\r\n return direction === 'DESC' ? -cmp : cmp;\r\n });\r\n }\r\n result = items;\r\n } else {\r\n const fields = sql.field as string[];\r\n result = listRes.map((el: any) => ({\r\n [fields[0]]: el.file,\r\n ...(fields[1] ? { [fields[1]]: el.data } : {}),\r\n }));\r\n }\r\n }\r\n } else {\r\n result = sql?.list ? { open: [], delete: [] } : [];\r\n }\r\n }\r\n }\r\n\r\n if (result !== undefined) {\r\n resolve(result);\r\n } else {\r\n reject('');\r\n }\r\n } catch (e) {\r\n reject(e);\r\n }\r\n });\r\n }\r\n }\r\n return DbFile;\r\n}\r\nexport default dbDriver;\r\n","import type Idb from './src/type';\r\nimport type { DbInstance } from './src/common';\r\nimport Sql from './src/Sql';\r\nimport * as DbCommon from './src/common';\r\nimport fileDb from './src/file/Index';\r\n\r\n/** 内置与插件注册的存储后端类型 */\r\nexport type DbType = 'file' | 'sqlite' | 'mysql' | (string & {});\r\n\r\n/** 传给各 db 驱动插件的共享依赖(sqlite/mysql 插件 factory 入参) */\r\nexport interface DbDriverContext {\r\n IdbType: Idb;\r\n Sql: typeof Sql;\r\n DbCommon: typeof DbCommon;\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport type DbDriverCtor = new (config: any) => DbInstance;\r\nexport type DbDriverFactory = (ctx: DbDriverContext) => DbDriverCtor;\r\nexport type DbDriversMap = Partial<Record<string, DbDriverFactory>>;\r\n\r\nexport type InitDbFn = (\r\n type?: string,\r\n config?: Record<string, unknown>,\r\n dbDrivers?: DbDriversMap,\r\n) => DbInstance;\r\n\r\nconst BUILTIN_FILE = 'file';\r\n\r\nfunction buildFileDriver(): DbDriverCtor {\r\n return fileDb({ IdbType: {} as Idb, Sql, DbCommon }) as DbDriverCtor;\r\n}\r\n\r\nfunction resolveDriver(type: string, dbDrivers: DbDriversMap): DbDriverCtor | null {\r\n if (type === BUILTIN_FILE) {\r\n return buildFileDriver();\r\n }\r\n const factory = dbDrivers[type];\r\n if (typeof factory !== 'function') {\r\n return null;\r\n }\r\n return factory({ IdbType: {} as Idb, Sql, DbCommon });\r\n}\r\n\r\n/**\r\n * 数据库工厂:内置 file;sqlite/mysql 等由 app 经 sysserver(opt.db) 注入插件驱动。\r\n */\r\nconst initDb: InitDbFn = (type = BUILTIN_FILE, config = {}, dbDrivers = {}) => {\r\n let Driver = resolveDriver(type, dbDrivers);\r\n if (!Driver) {\r\n if (type !== BUILTIN_FILE) {\r\n console.warn(\r\n `[initDb] 未注册驱动 \"${type}\"(请在 sysserver($asai, { db: { ${type}: driver } }) 挂载),已回退 file 存储`,\r\n );\r\n }\r\n Driver = buildFileDriver();\r\n }\r\n return new Driver(config);\r\n};\r\n\r\nexport default initDb;\r\nexport type { Idb };\r\n","import sysserverws from './ws/index';\r\nimport sysserverapi from './api/index';\r\nimport sysserverlib from './lib/index';\r\nimport sysserverdb from './db/index';\r\nimport type { DbDriversMap } from './db/index';\r\n\r\nexport interface SysserverBootOptions {\r\n /** 外部 db 驱动插件,键名与 dataStores.type 一致(sqlite / mysql …) */\r\n db?: DbDriversMap;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport type SysserverFn = ($asai: unknown, opt?: SysserverBootOptions) => void;\r\n\r\nexport default function sysserver($asai: any, opt: SysserverBootOptions = {}): void {\r\n if (!$asai.$lib) $asai.$lib = {};\r\n $asai.$lib = { ...sysserverlib, ...$asai.$lib, ...(opt || {}) };\r\n $asai.dataserver = sysserverdb;\r\n $asai.$lib.ErrorCode?.loadErrorCodes?.($asai);\r\n if (!$asai.$lib.api) $asai.$lib.api = {};\r\n $asai.$lib.api = { ...sysserverapi, ...$asai.$lib.api };\r\n if (!$asai.$lib.ws) $asai.$lib.ws = {};\r\n $asai.$lib.ws = { ...sysserverws, ...$asai.$lib.ws };\r\n}\r\n","/**\n * asaihost.json 启动校验(轻量 schema,fail-fast)\n */\nimport { normalizeHostSiteDefaults } from '../infra/host-limits';\n\n/** 启动前归一化 host 配置 */\nexport function normalizeHostConfig(cfg: Record<string, any>): Record<string, any> {\n\tif (!cfg || typeof cfg !== 'object') return {};\n\tnormalizeSecurityConfig(cfg);\n\tnormalizeUserStoreConfig(cfg);\n\tif (cfg.logger && typeof cfg.logger === 'object') {\n\t\tnormalizeLoggerStoreConfig(cfg.logger);\n\t}\n\tnormalizeDataStoresConfig(cfg);\n\tnormalizeHostsConfig(cfg);\n\treturn cfg;\n}\n\nfunction normalizeHostsConfig(cfg: Record<string, any>): void {\n\tif (!cfg.hosts || typeof cfg.hosts !== 'object') return;\n\tif (cfg.hosts.default && typeof cfg.hosts.default === 'object') {\n\t\tnormalizeHostSiteDefaults(cfg.hosts.default);\n\t}\n\tfor (const [name, host] of Object.entries(cfg.hosts)) {\n\t\tif (name === 'default' || !host || typeof host !== 'object') continue;\n\t\tnormalizeHostSiteDefaults(host as Record<string, unknown>);\n\t}\n}\n\n/** 启动时合并 security 默认值(向后兼容:未配置时等同旧行为) */\nexport function normalizeSecurityConfig(cfg: Record<string, any>): void {\n\tif (!cfg.security || typeof cfg.security !== 'object') {\n\t\tcfg.security = { requireAuth: 0, csp: 0, auditLog: 1 };\n\t\treturn;\n\t}\n\tconst sec = cfg.security;\n\tif (sec.requireAuth == null) sec.requireAuth = 0;\n\tif (sec.csp == null) sec.csp = 0;\n\tif (sec.auditLog == null) sec.auditLog = 1;\n\tif (!Array.isArray(sec.authSkipPaths)) {\n\t\tsec.authSkipPaths = [\n\t\t\t'/api/asailog/*',\n\t\t\t'/api/sys/errorcodes/*',\n\t\t\t'/api/user/login/auth/*',\n\t\t\t'/api/user/login/changepass/*',\n\t\t\t'/api/user/login/register/*',\n\t\t\t'/api/user/login/config/*',\n\t\t\t'/api/sys/health/metrics/*',\n\t\t\t'/sys/info/*',\n\t\t\t'/jsonp/*',\n\t\t];\n\t}\n\tif (!sec.quota || typeof sec.quota !== 'object') {\n\t\tsec.quota = { enabled: 0 };\n\t}\n\tif (sec.allowRegister == null) sec.allowRegister = 1;\n\tif (sec.lockoutMaxFails == null) sec.lockoutMaxFails = 5;\n\tif (sec.lockoutMinutes == null) sec.lockoutMinutes = 15;\n\tif (sec.sessionTtlHours == null) sec.sessionTtlHours = 24;\n\tif (sec.passwordMinLength == null) sec.passwordMinLength = 8;\n\tif (!sec.passwordPolicy || typeof sec.passwordPolicy !== 'object') {\n\t\tsec.passwordPolicy = {\n\t\t\tminLength: sec.passwordMinLength,\n\t\t\trequireLower: 1,\n\t\t\trequireDigit: 1,\n\t\t\trequireUpper: 0,\n\t\t\trequireSpecial: 0,\n\t\t\tmaxAgeDays: 0,\n\t\t\thistoryCount: 0,\n\t\t};\n\t}\n\tif (!sec.banner || typeof sec.banner !== 'object') {\n\t\tsec.banner = { enabled: 0, text: '' };\n\t}\n\tif (sec.sessionIdleMinutes == null) sec.sessionIdleMinutes = 0;\n\tif (!Array.isArray(sec.roles) || !sec.roles.length) {\n\t\tsec.roles = [\n\t\t\t{ name: 'viewer', minLv: 0, permissions: ['read'] },\n\t\t\t{ name: 'operator', minLv: 3, permissions: ['read', 'operate'] },\n\t\t\t{ name: 'engineer', minLv: 5, permissions: ['read', 'operate', 'audit'] },\n\t\t\t{ name: 'admin', minLv: 7, permissions: ['read', 'operate', 'audit', 'admin'] },\n\t\t\t{ name: 'developer', minLv: 9, permissions: ['read', 'operate', 'audit', 'admin', 'develop'] },\n\t\t\t{ name: 'superadmin', minLv: 99, permissions: ['read', 'operate', 'audit', 'admin', 'develop', 'super'] },\n\t\t];\n\t}\n\tif (sec.forceWss == null) sec.forceWss = 0;\n\tif (!Array.isArray(sec.userLevels) || !sec.userLevels.length) {\n\t\tsec.userLevels = [\n\t\t\t{ lv: 0, key: 'guest', name: '普通用户', nameEn: 'Guest' },\n\t\t\t{ lv: 3, key: 'operator', name: '操作员', nameEn: 'Operator' },\n\t\t\t{ lv: 5, key: 'engineer', name: '工程师', nameEn: 'Engineer' },\n\t\t\t{ lv: 7, key: 'admin', name: '管理员', nameEn: 'Administrator' },\n\t\t\t{ lv: 9, key: 'developer', name: '开发者', nameEn: 'Developer' },\n\t\t\t{ lv: 99, key: 'superadmin', name: '超级管理员', nameEn: 'Super Administrator' },\n\t\t];\n\t}\n\tif (!sec.permissionThresholds || typeof sec.permissionThresholds !== 'object') {\n\t\tsec.permissionThresholds = { logRead: 3, adminRead: 7, adminWrite: 9 };\n\t}\n}\n\n/** userStore 默认值(file / sqlite / mysql 可切换) */\nexport function normalizeUserStoreConfig(cfg: Record<string, any>): void {\n\tif (!cfg.userStore || typeof cfg.userStore !== 'object') {\n\t\tcfg.userStore = {\n\t\t\ttype: 'file',\n\t\t\topt: { dir: 'webdata/webdb/users/', ext: '.json', create: 1 },\n\t\t};\n\t\treturn;\n\t}\n\tconst store = cfg.userStore;\n\tif (!store.type) store.type = 'file';\n\tif (!store.opt || typeof store.opt !== 'object') store.opt = {};\n\tif (store.type === 'file') {\n\t\tif (!store.opt.dir) store.opt.dir = 'webdata/webdb/users/';\n\t\tif (!store.opt.ext) store.opt.ext = '.json';\n\t\tif (store.opt.create == null) store.opt.create = 1;\n\t} else if (store.type === 'sqlite') {\n\t\tif (!store.opt.database) store.opt.database = './webdata/webdb/users/users.db';\n\t\tif (store.opt.create == null) store.opt.create = 1;\n\t} else if (store.type === 'mysql') {\n\t\tif (!store.opt.host) store.opt.host = '127.0.0.1';\n\t\tif (!store.opt.user) store.opt.user = 'root';\n\t\tif (store.opt.password == null) store.opt.password = '';\n\t\tif (!store.opt.database) store.opt.database = 'asai';\n\t\tif (store.opt.create == null) store.opt.create = 1;\n\t}\n}\n\n/** 统一日志存储(IEC 62443-4-2 + WEB 日志)— file / sqlite / mysql;默认 file 文件夹模式 */\nexport function normalizeLoggerStoreConfig(logger: Record<string, any>): void {\n\tif (!logger.store || typeof logger.store !== 'object') {\n\t\tlogger.store = { type: 'file', dir: 'webdata/webdb/log/store/', ext: '.json', create: 1 };\n\t\treturn;\n\t}\n\tconst store = logger.store;\n\tif (!store.type) store.type = 'file';\n\tif (store.type === 'file') {\n\t\tif (!store.dir) store.dir = 'webdata/webdb/log/store/';\n\t\tif (!store.ext) store.ext = '.json';\n\t} else if (store.type === 'sqlite') {\n\t\tif (!store.database) store.database = './webdata/webdb/log/asai-logs.db';\n\t} else if (store.type === 'mysql') {\n\t\tif (!store.host) store.host = '127.0.0.1';\n\t\tif (!store.user) store.user = 'root';\n\t\tif (store.password == null) store.password = '';\n\t\tif (!store.database) store.database = 'asai_logs';\n\t}\n\tif (store.create == null) store.create = 1;\n\tif (!logger.intervention) logger.intervention = {};\n\tif (!logger.intervention.archivePath) {\n\t\tlogger.intervention.archivePath = './webdata/webdb/log/intervention/archive/';\n\t}\n\tif (!logger.siem || typeof logger.siem !== 'object') {\n\t\tlogger.siem = { enabled: 0 };\n\t}\n\tif (logger.siem.enabled == null) logger.siem.enabled = 0;\n\tif (logger.diskAlertMb == null) logger.diskAlertMb = 512;\n\tif (logger.complianceIntervalHours == null) logger.complianceIntervalHours = 6;\n}\n\n/**\n * dataStores 统一注册表 — 合并 userStore / logger.store,全库经 getDataServer 切换后端\n */\nexport function normalizeDataStoresConfig(cfg: Record<string, any>): void {\n\tif (!cfg.dataStores || typeof cfg.dataStores !== 'object') {\n\t\tcfg.dataStores = {};\n\t}\n\tconst stores = cfg.dataStores;\n\n\tif (!stores.user && cfg.userStore) {\n\t\tstores.user = { type: cfg.userStore.type || 'file', opt: { ...(cfg.userStore.opt || {}) } };\n\t}\n\tif (!stores.user) {\n\t\tstores.user = {\n\t\t\ttype: 'file',\n\t\t\topt: { dir: 'webdata/webdb/users/', ext: '.json', create: 1 },\n\t\t};\n\t}\n\tif (stores.user && typeof stores.user === 'object') {\n\t\tconst userStore = stores.user as Record<string, any>;\n\t\tconst userType = (userStore.type || 'file') as 'file' | 'sqlite' | 'mysql';\n\t\tif (!userStore.type) userStore.type = 'file';\n\t\tif (!userStore.opt || typeof userStore.opt !== 'object') userStore.opt = {};\n\t\tif (userType === 'file') {\n\t\t\tif (!userStore.opt.dir) userStore.opt.dir = 'webdata/webdb/users/';\n\t\t\tif (!userStore.opt.ext) userStore.opt.ext = '.json';\n\t\t} else if (userType === 'sqlite') {\n\t\t\tif (!userStore.opt.database) userStore.opt.database = './webdata/webdb/users/users.db';\n\t\t} else if (userType === 'mysql') {\n\t\t\tif (!userStore.opt.host) userStore.opt.host = '127.0.0.1';\n\t\t\tif (!userStore.opt.user) userStore.opt.user = 'root';\n\t\t\tif (userStore.opt.password == null) userStore.opt.password = '';\n\t\t\tif (!userStore.opt.database) userStore.opt.database = 'asai';\n\t\t}\n\t\tif (userStore.opt.create == null) userStore.opt.create = 1;\n\t}\n\tif (!stores.log && cfg.logger?.store) {\n\t\tconst s = cfg.logger.store;\n\t\tstores.log = {\n\t\t\ttype: s.type || 'file',\n\t\t\topt: {\n\t\t\t\tdatabase: s.database,\n\t\t\t\tdir: s.dir,\n\t\t\t\text: s.ext,\n\t\t\t\thost: s.host,\n\t\t\t\tuser: s.user,\n\t\t\t\tpassword: s.password,\n\t\t\t\tcreate: s.create,\n\t\t\t},\n\t\t};\n\t}\n\tif (stores.log && typeof stores.log === 'object') {\n\t\tconst logStore = stores.log as Record<string, any>;\n\t\tconst logType = (logStore.type || 'file') as 'file' | 'sqlite' | 'mysql';\n\t\tif (!logStore.opt || typeof logStore.opt !== 'object') logStore.opt = {};\n\t\tif (logType === 'file') {\n\t\t\tif (!logStore.opt.dir) logStore.opt.dir = 'webdata/webdb/log/store/';\n\t\t\tif (!logStore.opt.ext) logStore.opt.ext = '.json';\n\t\t} else if (logType === 'sqlite') {\n\t\t\tif (!logStore.opt.database) logStore.opt.database = './webdata/webdb/log/asai-logs.db';\n\t\t}\n\t\tif (logStore.opt.create == null) logStore.opt.create = 1;\n\t}\n\tif (!stores.default) {\n\t\tstores.default = {\n\t\t\ttype: 'sqlite',\n\t\t\topt: { database: './webdata/webdb/sqlite/asaisqlite.db', create: 1 },\n\t\t};\n\t}\n\n\t// 反向同步 legacy 字段,保持旧配置可读\n\tif (stores.user) {\n\t\tcfg.userStore = { type: stores.user.type || 'file', opt: stores.user.opt || {} };\n\t\tnormalizeUserStoreConfig(cfg);\n\t}\n\tif (stores.log && cfg.logger) {\n\t\tconst lo = stores.log.opt || {};\n\t\tcfg.logger.store = {\n\t\t\ttype: stores.log.type || 'file',\n\t\t\tdatabase: lo.database,\n\t\t\tdir: lo.dir,\n\t\t\text: lo.ext,\n\t\t\thost: lo.host,\n\t\t\tuser: lo.user,\n\t\t\tpassword: lo.password,\n\t\t\tcreate: lo.create,\n\t\t};\n\t\tnormalizeLoggerStoreConfig(cfg.logger);\n\t}\n}\n\nexport function validateHostConfig(cfg: Record<string, any>): string[] {\n\tconst errors: string[] = [];\n\tif (!cfg || typeof cfg !== 'object') {\n\t\treturn ['hostconfig 必须为非空对象'];\n\t}\n\n\t// password / asaisn / aes.keybase64 / httpscert PEM 由 secrets 模块注入,禁止出现在 asaihost.json\n\tif (cfg.password != null) {\n\t\terrors.push('password 禁止写入 asaihost.json,请使用 ASAI_HOST_PASSWORD 或 asaihost.secrets.local.json');\n\t}\n\tif (cfg.asaisn != null) {\n\t\terrors.push('asaisn 禁止写入 asaihost.json,请使用 ASAI_ASAISN');\n\t}\n\tif (cfg.aes?.keybase64 != null) {\n\t\terrors.push('aes.keybase64 禁止写入 asaihost.json,请使用 ASAI_AES_KEYBASE64');\n\t}\n\tif (cfg.httpscert?.key != null || cfg.httpscert?.cert != null) {\n\t\terrors.push('httpscert.key/cert 禁止内联于 asaihost.json,请使用 keyPath/certPath 或环境变量');\n\t}\n\tif (cfg.security?.sessionSecret != null) {\n\t\terrors.push('security.sessionSecret 禁止写入 asaihost.json,请使用 ASAI_SESSION_SECRET');\n\t}\n\tif (Array.isArray(cfg.wssec) && typeof cfg.wssec[0] === 'string' && cfg.wssec[0].length > 0) {\n\t\terrors.push('wssec[0] 禁止写入 asaihost.json,请使用 ASAI_WSSEC_TOKEN');\n\t}\n\n\tnormalizeSecurityConfig(cfg);\n\tnormalizeUserStoreConfig(cfg);\n\n\tif (cfg.logger && typeof cfg.logger === 'object') {\n\t\tnormalizeLoggerStoreConfig(cfg.logger);\n\t}\n\tnormalizeDataStoresConfig(cfg);\n\n\tif (cfg.dataStores && typeof cfg.dataStores === 'object') {\n\t\tfor (const [name, store] of Object.entries(cfg.dataStores)) {\n\t\t\tconst s = store as Record<string, any>;\n\t\t\tif (!s.type || !['file', 'sqlite', 'mysql'].includes(s.type)) {\n\t\t\t\terrors.push(`dataStores.${name}.type 必须为 file|sqlite|mysql`);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (cfg.security && typeof cfg.security === 'object') {\n\t\tconst sec = cfg.security;\n\t\tif (sec.requireAuth != null && sec.requireAuth !== 0 && sec.requireAuth !== 1) {\n\t\t\terrors.push('security.requireAuth 必须为 0 或 1');\n\t\t}\n\t\tif (sec.csp != null && sec.csp !== 0 && sec.csp !== 1) {\n\t\t\terrors.push('security.csp 必须为 0 或 1');\n\t\t}\n\t\tif (sec.minUserLevel != null && (typeof sec.minUserLevel !== 'number' || sec.minUserLevel < 0)) {\n\t\t\terrors.push('security.minUserLevel 必须为非负整数');\n\t\t}\n\t}\n\n\tif (!cfg.hosts || typeof cfg.hosts !== 'object') {\n\t\terrors.push('hosts 必须为对象');\n\t} else {\n\t\tif (!cfg.hosts.default) {\n\t\t\terrors.push('hosts.default 缺失');\n\t\t} else {\n\t\t\tnormalizeHostSiteDefaults(cfg.hosts.default as Record<string, unknown>);\n\t\t}\n\t\tfor (const [name, host] of Object.entries(cfg.hosts)) {\n\t\t\tconst h = host as Record<string, any>;\n\t\t\tif (name === 'default') {\n\t\t\t\tvalidateHostSiteLimits(name, h, errors);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (h.port != null && (typeof h.port !== 'number' || h.port <= 0 || h.port > 65535)) {\n\t\t\t\terrors.push(`hosts.${name}.port 无效: ${h.port}`);\n\t\t\t}\n\t\t\tif (h.hostdirs != null && !Array.isArray(h.hostdirs)) {\n\t\t\t\terrors.push(`hosts.${name}.hostdirs 必须为数组`);\n\t\t\t}\n\t\t\tvalidateHostSiteLimits(name, h, errors);\n\t\t}\n\t}\n\n\tif (cfg.logger?.sample && typeof cfg.logger.sample !== 'object') {\n\t\terrors.push('logger.sample 必须为对象(如 { \"REQ_OTHER\": 0.1 })');\n\t}\n\tif (cfg.logger?.skip != null && !Array.isArray(cfg.logger.skip)) {\n\t\terrors.push('logger.skip 必须为字符串数组(如 [\"/sys/info/metrics\"])');\n\t}\n\n\tif (cfg.proxyhosts && typeof cfg.proxyhosts === 'object') {\n\t\tfor (const [name, proxy] of Object.entries(cfg.proxyhosts)) {\n\t\t\tconst p = proxy as Record<string, any>;\n\t\t\tif (p.url && p.proxyport != null && typeof p.proxyport !== 'number') {\n\t\t\t\terrors.push(`proxyhosts.${name}.proxyport 无效`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn errors;\n}\n\nfunction validateHostSiteLimits(name: string, h: Record<string, any>, errors: string[]): void {\n\tconst flags = ['close', 'ws', 'ckhttp', 'ckws', 'oncors'] as const;\n\tfor (const key of flags) {\n\t\tif (h[key] != null && h[key] !== 0 && h[key] !== 1) {\n\t\t\terrors.push(`hosts.${name}.${key} 必须为 0 或 1`);\n\t\t}\n\t}\n\tfor (const key of ['maxhttp', 'maxws', 'maxonline'] as const) {\n\t\tif (h[key] != null && (typeof h[key] !== 'number' || h[key] <= 0)) {\n\t\t\terrors.push(`hosts.${name}.${key} 必须为正整数`);\n\t\t}\n\t}\n\tif (h.cors != null && !Array.isArray(h.cors)) {\n\t\terrors.push(`hosts.${name}.cors 必须为字符串数组`);\n\t}\n}\n\n/** IEC 62443-4-2 — 生产环境强制安全配置(开发环境不校验) */\nexport function validateProductionSecurity(cfg: Record<string, any>): string[] {\n\tconst errors: string[] = [];\n\tif (process.env.NODE_ENV !== 'production') return errors;\n\n\tconst sec = cfg?.security;\n\tif (!sec || typeof sec !== 'object') {\n\t\terrors.push('生产环境必须配置 security 对象');\n\t\treturn errors;\n\t}\n\tif (sec.requireAuth !== 1) {\n\t\terrors.push('生产环境 security.requireAuth 必须为 1(CR 1.1 身份鉴别)');\n\t}\n\tif (sec.allowRegister === 1) {\n\t\terrors.push('生产环境 security.allowRegister 应为 0(CR 1.3 禁止开放注册)');\n\t}\n\tif (!sec.quota?.enabled) {\n\t\terrors.push('生产环境 security.quota.enabled 应为 1(CR 7.1 资源限制)');\n\t}\n\tif (sec.csp !== 1) {\n\t\terrors.push('生产环境 security.csp 应为 1(CR 7.6 内容安全策略)');\n\t}\n\tif (typeof sec.minUserLevel !== 'number' || sec.minUserLevel < 0) {\n\t\terrors.push('生产环境 security.minUserLevel 应显式配置');\n\t}\n\tif (sec.forceWss === 1 && !cfg?.httpscert?.keyPath && !cfg?.httpscert?.key) {\n\t\terrors.push('生产环境 security.forceWss=1 时需配置 HTTPS 证书');\n\t}\n\n\treturn errors;\n}\n","/**\r\n * syscom 通信配置 — tcp / grpc / rs485 统一读取、归一化与重连参数\r\n *\r\n * 配置结构(推荐):\r\n * hostconfig.syscom.{tcp|grpc|rs485}.default\r\n * 兼容旧版顶层 tcp/grpc/rs485/serial485/1tcp 等键名。\r\n */\r\n\r\nexport type TransportKind = 'tcp' | 'grpc' | 'rs485';\r\n\r\nexport interface ReconnectOptions {\r\n\tenabled?: boolean;\r\n\tmaxRetries?: number;\r\n\tinitialDelay?: number;\r\n\tmaxDelay?: number;\r\n\tfactor?: number;\r\n}\r\n\r\nconst LEGACY_TOP_LEVEL: Record<string, TransportKind> = {\r\n\t'1tcp': 'tcp',\r\n\t'1grpc': 'grpc',\r\n\t'1rs485': 'rs485',\r\n\tserial485: 'rs485',\r\n};\r\n\r\nconst DEFAULT_CONN_ID: Record<TransportKind, string> = {\r\n\ttcp: 'testtcp',\r\n\tgrpc: 'testgrpc',\r\n\trs485: 'testrs485',\r\n};\r\n\r\nconst DEFAULT_RECONNECT: Record<TransportKind, ReconnectOptions> = {\r\n\ttcp: { enabled: true, maxRetries: 60, initialDelay: 1000, maxDelay: 30000, factor: 2 },\r\n\tgrpc: { enabled: true, maxRetries: 60, initialDelay: 1000, maxDelay: 30000, factor: 2 },\r\n\trs485: { enabled: true, maxRetries: 60, initialDelay: 3000, maxDelay: 30000, factor: 2 },\r\n};\r\n\r\n/** 启动时归一化:syscom 优先,合并 legacy 键到 tcp/grpc/rs485 */\r\nexport function normalizeHostConfig(cfg: Record<string, any>): Record<string, any> {\r\n\tif (!cfg || typeof cfg !== 'object') return {};\r\n\r\n\tif (cfg.syscom && typeof cfg.syscom === 'object') {\r\n\t\tfor (const kind of Object.keys(DEFAULT_CONN_ID) as TransportKind[]) {\r\n\t\t\tif (cfg.syscom[kind]) {\r\n\t\t\t\tcfg[kind] = cfg.syscom[kind];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const [legacy, canonical] of Object.entries(LEGACY_TOP_LEVEL)) {\r\n\t\tif (cfg[legacy] && !cfg[canonical]) {\r\n\t\t\tcfg[canonical] = cfg[legacy];\r\n\t\t}\r\n\t}\r\n\r\n\treturn cfg;\r\n}\r\n\r\nexport function getTransportBlock(cfg: any, kind: TransportKind): Record<string, any> | null {\r\n\tconst block = cfg?.[kind];\r\n\treturn block && typeof block === 'object' ? block : null;\r\n}\r\n\r\nexport function getTransportDefault(cfg: any, kind: TransportKind): Record<string, any> | null {\r\n\tconst def = getTransportBlock(cfg, kind)?.default;\r\n\treturn def && typeof def === 'object' ? def : null;\r\n}\r\n\r\nexport function hasTransportDefault(cfg: any, kind: TransportKind): boolean {\r\n\treturn !!getTransportDefault(cfg, kind);\r\n}\r\n\r\n/** 默认连接 ID(来自配置 default.id,否则各传输内置默认值) */\r\nexport function getDefaultConnId(cfg: any, kind: TransportKind): string {\r\n\tconst def = getTransportDefault(cfg, kind);\r\n\tconst id = def?.id;\r\n\treturn typeof id === 'string' && id.length > 0 ? id : DEFAULT_CONN_ID[kind];\r\n}\r\n\r\n/** 是否在启动时自动 connect(default.autoConnect !== false 时为 true) */\r\nexport function shouldAutoConnect(def: Record<string, any> | null | undefined): boolean {\r\n\tif (!def) return false;\r\n\treturn def.autoConnect !== false;\r\n}\r\n\r\n/** 解析重连参数:default.reconnect > 传输默认值 > tm.maxtry */\r\nexport function resolveReconnectOptions(\r\n\tdef: Record<string, any> | null | undefined,\r\n\tkind: TransportKind,\r\n\tcfg?: Record<string, any>,\r\n): ReconnectOptions {\r\n\tconst base = DEFAULT_RECONNECT[kind];\r\n\tconst rc = def?.reconnect;\r\n\tconst tmMaxTry = cfg?.tm?.maxtry;\r\n\r\n\treturn {\r\n\t\tenabled: rc?.enabled !== false && base.enabled !== false,\r\n\t\tmaxRetries: rc?.maxRetries ?? tmMaxTry ?? base.maxRetries ?? 60,\r\n\t\tinitialDelay: rc?.initialDelay ?? base.initialDelay ?? 1000,\r\n\t\tmaxDelay: rc?.maxDelay ?? base.maxDelay ?? 30000,\r\n\t\tfactor: rc?.factor ?? base.factor ?? 2,\r\n\t};\r\n}\r\n","/**\r\n * TCP / gRPC / RS485 传输桥公共模板 — 连接管理、路由注册、数据 watch 广播\r\n */\r\nimport { registerApi, registerWs } from './registry';\r\nimport {\r\n\tgetTransportDefault,\r\n\tgetDefaultConnId,\r\n\tshouldAutoConnect,\r\n\ttype TransportKind,\r\n} from '../config/syscom';\r\n\r\nconst PENDING_CFG_KEY: Record<TransportKind, string> = {\r\n\ttcp: 'asaihosttcpPending',\r\n\tgrpc: 'asaihostgrpcPending',\r\n\trs485: 'asaihost485Pending',\r\n};\r\n\r\nexport interface TransportBridgeOptions {\r\n\t$asai: any;\r\n\tmanager: any;\r\n\tmanagerKey: string;\r\n\tserversKey: string;\r\n\ttransport: TransportKind;\r\n\tbuildDefaultConfig: (def: Record<string, any>) => Record<string, any>;\r\n\tapiRoute: string;\r\n\tapiHandler: any;\r\n\twsRoute: string;\r\n\twsHandler: any;\r\n}\r\n\r\n/** 初始化传输管理器:挂 $asai、可选默认连接、注册 API/WS 路由 */\r\nexport function initTransportBridge(opts: TransportBridgeOptions): any {\r\n\tconst { $asai, manager } = opts;\r\n\t$asai[opts.managerKey] = manager;\r\n\tif (!$asai[opts.serversKey]) {\r\n\t\t$asai[opts.serversKey] = {};\r\n\t}\r\n\r\n\tconst defaultCfg = getTransportDefault($asai.hostconfig, opts.transport);\r\n\tconst connId = getDefaultConnId($asai.hostconfig, opts.transport);\r\n\r\n\tif (defaultCfg) {\r\n\t\tconst built = opts.buildDefaultConfig(defaultCfg);\r\n\t\t$asai[PENDING_CFG_KEY[opts.transport]] = { connId, config: built };\r\n\t\tif (shouldAutoConnect(defaultCfg) && !$asai[opts.serversKey][connId]) {\r\n\t\t\t$asai[opts.serversKey][connId] = manager.connect(built);\r\n\t\t}\r\n\t}\r\n\r\n\tregisterApi($asai, opts.apiRoute, opts.apiHandler);\r\n\tregisterWs($asai, opts.wsRoute, opts.wsHandler);\r\n\treturn manager;\r\n}\r\n\r\n/** 首次 API/WS 调用时再建立默认连接(autoConnect: false 时) */\r\nexport function ensureDefaultConnection($asai: any, transport: TransportKind): string | null {\r\n\tconst pending = $asai[PENDING_CFG_KEY[transport]];\r\n\tif (!pending) return null;\r\n\r\n\tconst managerKey =\r\n\t\ttransport === 'tcp' ? 'asaihosttcp' : transport === 'grpc' ? 'asaihostgrpc' : 'asaihost485';\r\n\tconst serversKey =\r\n\t\ttransport === 'tcp'\r\n\t\t\t? 'asaihosttcpserver'\r\n\t\t\t: transport === 'grpc'\r\n\t\t\t\t? 'asaihostgrpcserver'\r\n\t\t\t\t: 'asaihost485server';\r\n\r\n\tconst manager = $asai[managerKey];\r\n\tif (!manager || !pending.connId) return null;\r\n\r\n\tif (!$asai[serversKey]) $asai[serversKey] = {};\r\n\tif (!$asai[serversKey][pending.connId]) {\r\n\t\t$asai[serversKey][pending.connId] = manager.connect(pending.config);\r\n\t}\r\n\treturn pending.connId;\r\n}\r\n\r\n/** 标准 DATA 事件:JSON 解析 + watch 匹配 / WS 广播 */\r\nexport function createTransportDataHandler($asai: any, manager: any) {\r\n\treturn (event: any) => {\r\n\t\tif (typeof event.data === 'string') {\r\n\t\t\ttry {\r\n\t\t\t\tevent.data = JSON.parse(event.data);\r\n\t\t\t} catch {\r\n\t\t\t\t// 非 JSON 保持原样\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (event.data?.id) {\r\n\t\t\tmanager.watch(event.id, event.data);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tconst wsKey = $asai?.command?.commandconfig?.config?.commandclient;\r\n\t\t\t$asai.serversws?.[wsKey]?.broadws?.(event.data);\r\n\t\t} catch {\r\n\t\t\t// 广播非必需\r\n\t\t}\r\n\t};\r\n}\r\n\r\n/** 连接状态日志(ERROR 由各 manager 内部输出,避免重复) */\r\nexport function wireTransportConnectionLogs(\r\n\tmanager: any,\r\n\tevents: { CONNECTED: string; DISCONNECTED: string; ERROR?: string },\r\n\tlogPrefix: string,\r\n): void {\r\n\tmanager.on(events.CONNECTED, (event: any) => {\r\n\t\tconsole.log(`${logPrefix} 连接上线`, event.id, event.label || '');\r\n\t});\r\n\tmanager.on(events.DISCONNECTED, (event: any) => {\r\n\t\tconsole.log(`${logPrefix} 连接离线`, event.id, event.label || '');\r\n\t});\r\n\t// manager 内部已 console.error;此处仅注册 listener,避免 ERR_UNHANDLED_ERROR\r\n\tif (events.ERROR) {\r\n\t\tmanager.on(events.ERROR, () => {});\r\n\t}\r\n}\r\n","/**\n * AsaiRuntime 类型定义 — 逐步替换 any,保持与现有 $asai 对象兼容\n */\nimport type { WsRouteIndex } from './ws/route-index';\nimport type { SysserverBootOptions } from './sysserver/index';\n\nexport type RouteFactory = ($asai: AsaiRuntime) => Record<string, unknown>;\n\n/** IEC 62443-4-2 安全策略(默认全关,不影响现有行为) */\nexport interface SecurityConfig {\n\t/** 1=强制 HTTP Userinfo 鉴权;0=关闭(默认) */\n\trequireAuth?: number;\n\t/** 1=启用 Content-Security-Policy */\n\tcsp?: number;\n\t/** 自定义 CSP 策略字符串 */\n\tcspPolicy?: string;\n\t/** 1=记录安全审计事件(默认开启) */\n\tauditLog?: number;\n\t/** 鉴权白名单路径(支持 * 后缀前缀匹配) */\n\tauthSkipPaths?: string[];\n\t/** 最低用户等级(requireAuth=1 时生效) */\n\tminUserLevel?: number;\n\t/** 0=禁止开放注册(生产推荐) */\n\tallowRegister?: number;\n\tlockoutMaxFails?: number;\n\tlockoutMinutes?: number;\n\tsessionTtlHours?: number;\n\tpasswordMinLength?: number;\n\t/** CR 1.12 登录前系统使用通知 */\n\tbanner?: { enabled?: number; text?: string };\n\t/** CR 1.7 口令强度策略 */\n\tpasswordPolicy?: {\n\t\tminLength?: number;\n\t\trequireUpper?: number;\n\t\trequireLower?: number;\n\t\trequireDigit?: number;\n\t\trequireSpecial?: number;\n\t\tmaxAgeDays?: number;\n\t\thistoryCount?: number;\n\t};\n\t/** CR 2.5 会话空闲锁定(分钟,0=关闭) */\n\tsessionIdleMinutes?: number;\n\t/** CR 2.1 SL-2 角色定义 */\n\troles?: Array<{ name: string; minLv: number; permissions?: string[] }>;\n\t/** CR 3.1 SL-2 生产强制 WSS */\n\tforceWss?: number;\n\tquota?: {\n\t\tenabled?: number;\n\t\tmaxApiConcurrent?: number;\n\t\tmaxApiPerIp?: number;\n\t\tmaxApiPerIpPerMin?: number;\n\t\tmaxWsPerIp?: number;\n\t\tmaxLoginSessions?: number;\n\t\tmaxSessionsPerUser?: number;\n\t\tonUserSessionOverflow?: string;\n\t};\n}\n\nexport interface HostConfig {\n\twebsite?: { title?: string; ver?: string };\n\tpassword?: string;\n\tsecurity?: SecurityConfig;\n\tip?: string;\n\tindex?: string;\n\toncors?: number;\n\tasaiport?: number[];\n\tguardtm?: ReturnType<typeof setTimeout> | null;\n\thosts?: Record<string, HostSiteConfig>;\n\tproxyhosts?: Record<string, ProxySiteConfig>;\n\tlogger?: LoggerConfig;\n\tmimetypes?: Record<string, string>;\n\taes?: { lv?: number; keybase64?: string; aad?: string };\n\tpath?: { mock?: string; ip?: string };\n\ttm?: { c?: number; d?: number; maxtry?: number };\n\tpkg?: { type?: number };\n\t[key: string]: unknown;\n}\n\nexport interface HostSiteConfig {\n\tclose?: number;\n\tport?: number;\n\tws?: number;\n\tckhttp?: number;\n\tckws?: number;\n\tmaxhttp?: number;\n\tmaxws?: number;\n\tmaxonline?: number;\n\toncors?: number;\n\twstype?: string;\n\thttptype?: string;\n\thostdirs?: string[];\n\tweburls?: {\n\t\trewrite?: boolean;\n\t\twebdir?: string;\n\t\tkeys?: string[];\n\t};\n\tmimetypes?: Record<string, string>;\n\tcors?: string[];\n\t[key: string]: unknown;\n}\n\nexport interface ProxySiteConfig {\n\turl?: string;\n\tport?: number;\n\tproxyport?: number;\n\thttptype?: string;\n\tproxyhttptype?: string;\n\t[key: string]: unknown;\n}\n\nexport interface LoggerConfig {\n\tlv?: { view?: number; record?: number };\n\tpath?: { maxsize?: number; client?: string; server?: string };\n\t/** 采样率 0~1,如 { \"REQ_OTHER\": 0.05 } */\n\tsample?: Record<string, number>;\n\t/** 不写日志的请求路径(精确匹配;以 * 结尾为前缀匹配) */\n\tskip?: string[];\n\t/** IEC 62443-4-2 干预日志(CEF 格式,留存≥5年) */\n\tintervention?: {\n\t\tpath?: string;\n\t\tretentionYears?: number;\n\t\t/** 演示/自动化测试触发的干预动作专用存储目录,与生产留存数据完全隔离,不计入合规审计留存 */\n\t\ttestPath?: string;\n\t};\n}\n\nexport type WorkHandler = (req: unknown, res: unknown, hostdir: string) => void;\nexport type WsWorkHandler = (msg: unknown, ws: unknown, hostdir: string, req: unknown) => void;\n\nexport interface AsaiHostNodejsOptions {\n\tsysWork: WorkHandler;\n\tapiWork: WorkHandler;\n\twsWork: WsWorkHandler;\n\tjsonpWork: WorkHandler;\n}\n\n/** 运行时主对象(与 app.ts 中 $asai 结构一致) */\nexport interface AsaiRuntime {\n\t$lib: Record<string, unknown>;\n\thostconfig: HostConfig;\n\tasaizip?: unknown;\n\tdataserver?: unknown;\n\tasaihost?: Record<string, unknown>;\n\tasaimock?: Record<string, unknown>;\n\tconnectionshttp: Record<string, Set<unknown>>;\n\tconnectionsws: Record<string, Record<string, unknown>>;\n\ttaskshttp: Record<string, unknown>;\n\ttasksws: Record<string, unknown>;\n\tservershttp: Record<string, unknown>;\n\tserversws: Record<string, unknown>;\n\thostserverapi?: Record<string, RouteFactory>;\n\thostserverapis?: string[];\n\thostserverws?: Record<string, RouteFactory>;\n\thostserverwss?: string[];\n\thostserversys?: Record<string, RouteFactory>;\n\thostserversyss?: string[];\n\twsRouteIndex?: WsRouteIndex;\n\tregisterApi?: (key: string, factory: RouteFactory) => void;\n\tregisterWs?: (key: string, factory: RouteFactory) => void;\n\tsetAppend?: (src: string, logstr: string) => Promise<void>;\n\tgetHost?: (hostdir: string) => HostSiteConfig;\n\tgetHostIP?: (ip?: string | null) => string;\n\tstartHTTPServer?: (hostdir: string) => unknown;\n\t$log?: (...args: unknown[]) => void | Promise<void>;\n\tcommand?: Record<string, unknown>;\n\ttmpdata: Record<string, unknown>;\n\ttm: number;\n\t[key: string]: unknown;\n}\n\n/** 兼容旧代码的全局别名 */\nexport type AsaiGlobal = AsaiRuntime;\nexport type HostConfigLegacy = HostConfig;\nexport type ProxyHostConfig = ProxySiteConfig;\n\n/** npm 包标识(与 package.json name 一致) */\nexport const PLUGIN_NAME = 'asaihost-nodejs' as const;\n\n/** sysserver 启动时可注入外部 db 驱动(见 app.ts) */\nexport type { SysserverBootOptions, SysserverFn } from './sysserver/index';\n\n/** `fn($asai, opt)` 返回值:启动函数 + ws 模块引用 */\nexport interface HostBootResult {\n\tStartAsaiHostNodejs: () => void;\n\tasaiWs: typeof import('ws');\n}\n\n/** wsMock($asai) 返回值 — 供 asaimock 挂载与 WS 开发回包 */\nexport interface WsMockToolkit {\n\tgetKeyByData: (reqdata: unknown, hostdir?: string) => string;\n\twsWorkApi: (workopt: unknown) => void;\n\twsWorkMock: (workopt: unknown) => void;\n\twsWorkListen: (workopt: unknown, reqkey: unknown) => void;\n\tgetMockDb: (workopt: unknown) => Record<string, unknown>;\n}\n\n/** AsaiUtils 命名空间(见 src/utils/index.ts) */\nexport interface AsaiUtilsModule {\n\tdeUserInfoWithAsai: (userinfo: string[] | null | undefined, $asai: AsaiRuntime) => string[] | null;\n\twsMock: ($asai: AsaiRuntime) => WsMockToolkit;\n}\n\n/** 宿主插件核心 API(其余 host-api 方法通过交叉类型扩展) */\nexport interface AsaiNodejsHostPluginBase {\n\treadonly name: typeof PLUGIN_NAME;\n\tfn: (runtime: AsaiRuntime, options: AsaiHostNodejsOptions) => HostBootResult;\n\tsysserver: (runtime: AsaiRuntime, opt?: SysserverBootOptions) => void;\n\tAsaiCommon: Record<string, unknown>;\n\tAsaiUtils: AsaiUtilsModule;\n}\n\n/** 宿主插件对外 API 形状(含 normalizeHostConfig 等扩展方法) */\nexport type AsaiNodejsHostPlugin = AsaiNodejsHostPluginBase & Record<string, unknown>;\n","/**\r\n * asaihost-nodejs — Node.js HTTP/WebSocket 服务器宿主\r\n *\r\n * 默认导出为宿主插件对象;配置校验、路由注册、安全工具等见命名导出。\r\n */\r\nimport hostMainMod from './src/index';\r\nimport * as AsaiUtils from './src/utils';\r\nimport AsaiCommon from './src/common/Index';\r\nimport sysserver from './src/sysserver/index';\r\nimport {\r\n\tnormalizeHostConfig,\r\n\tvalidateHostConfig,\r\n\tvalidateProductionSecurity,\r\n} from './src/config/validate';\r\nimport {\r\n\tgetHostAllowedRoots,\r\n\tinitHostserverApi,\r\n\tinitHostserverWs,\r\n\tregisterApi,\r\n\tregisterWs,\r\n\tresolvePathUnderRoots,\r\n\tsecureCompare,\r\n\tsyncApiRouteKeys,\r\n\tsyncWsRouteKeys,\r\n\tlogSecurityEvent,\r\n\tsanitizeString,\r\n\tvalidateHttpAuth,\r\n\tnormalizeSecurityConfig,\r\n\tstripForbiddenSecretsFromHostConfig,\r\n\tloadAsaiSecrets,\r\n\tloadDotEnvFile,\r\n\tapplySecretsToHostConfig,\r\n\tresolveHttpsCertFromPaths,\r\n\tvalidateAsaiSecrets,\r\n\tisDevDefaultPassword,\r\n\thasTransportDefault,\r\n\tgetTransportDefault,\r\n\tgetDefaultConnId,\r\n\tgetTransportBlock,\r\n\tresolveReconnectOptions,\r\n\tshouldAutoConnect,\r\n\tinitTransportBridge,\r\n\tensureDefaultConnection,\r\n\tcreateTransportDataHandler,\r\n\twireTransportConnectionLogs,\r\n} from './src/host-api';\r\nimport type {\r\n\tAsaiNodejsHostPlugin,\r\n\tAsaiRuntime,\r\n\tAsaiHostNodejsOptions,\r\n\tHostBootResult,\r\n\tHostConfig,\r\n} from './src/types';\r\nimport { PLUGIN_NAME as PLUGIN_NAME_CONST } from './src/types';\r\n\r\ndeclare const __ASAIHOST_NODEJS_VERSION__: string;\r\n\r\n/** 兼容 tsx / CJS default 互操作 */\r\nfunction hostDefault<T>(mod: T): T {\r\n\tif (mod && typeof mod === 'object' && 'default' in (mod as object)) {\r\n\t\tconst d = (mod as unknown as { default?: T }).default;\r\n\t\tif (d !== undefined) return d;\r\n\t}\r\n\treturn mod;\r\n}\r\n\r\nconst hostMain = hostDefault(hostMainMod);\r\n\r\nconst initAsaiHostNodejs: AsaiNodejsHostPlugin = {\r\n\tname: PLUGIN_NAME_CONST,\r\n\tfn: ($asai: AsaiRuntime, opt: AsaiHostNodejsOptions): HostBootResult =>\r\n\t\thostMain($asai, opt) as HostBootResult,\r\n\tsysserver,\r\n\tAsaiCommon,\r\n\tAsaiUtils,\r\n\tnormalizeHostConfig,\r\n\tvalidateHostConfig,\r\n\tvalidateProductionSecurity,\r\n\tregisterApi,\r\n\tregisterWs,\r\n\tinitHostserverApi,\r\n\tinitHostserverWs,\r\n\tsyncApiRouteKeys,\r\n\tsyncWsRouteKeys,\r\n\tsecureCompare,\r\n\tresolvePathUnderRoots,\r\n\tgetHostAllowedRoots,\r\n\tlogSecurityEvent,\r\n\tsanitizeString,\r\n\tvalidateHttpAuth,\r\n\tnormalizeSecurityConfig,\r\n\tstripForbiddenSecretsFromHostConfig,\r\n\tloadAsaiSecrets,\r\n\tloadDotEnvFile,\r\n\tapplySecretsToHostConfig,\r\n\tresolveHttpsCertFromPaths,\r\n\tvalidateAsaiSecrets,\r\n\tisDevDefaultPassword,\r\n\tgetTransportBlock,\r\n\tgetTransportDefault,\r\n\thasTransportDefault,\r\n\tgetDefaultConnId,\r\n\tresolveReconnectOptions,\r\n\tshouldAutoConnect,\r\n\tinitTransportBridge,\r\n\tensureDefaultConnection,\r\n\tcreateTransportDataHandler,\r\n\twireTransportConnectionLogs,\r\n};\r\n\r\nexport {\r\n\tPLUGIN_NAME_CONST as PLUGIN_NAME,\r\n\tinitAsaiHostNodejs,\r\n\tnormalizeHostConfig,\r\n\tvalidateHostConfig,\r\n\tvalidateProductionSecurity,\r\n\tregisterApi,\r\n\tregisterWs,\r\n\tinitHostserverApi,\r\n\tinitHostserverWs,\r\n\tsyncApiRouteKeys,\r\n\tsyncWsRouteKeys,\r\n\tsecureCompare,\r\n\tresolvePathUnderRoots,\r\n\tgetHostAllowedRoots,\r\n\tlogSecurityEvent,\r\n\tsanitizeString,\r\n\tvalidateHttpAuth,\r\n\tnormalizeSecurityConfig,\r\n\tstripForbiddenSecretsFromHostConfig,\r\n\tloadAsaiSecrets,\r\n\tloadDotEnvFile,\r\n\tapplySecretsToHostConfig,\r\n\tresolveHttpsCertFromPaths,\r\n\tvalidateAsaiSecrets,\r\n\tisDevDefaultPassword,\r\n\tgetTransportBlock,\r\n\tgetTransportDefault,\r\n\thasTransportDefault,\r\n\tgetDefaultConnId,\r\n\tresolveReconnectOptions,\r\n\tshouldAutoConnect,\r\n\tinitTransportBridge,\r\n\tensureDefaultConnection,\r\n\tcreateTransportDataHandler,\r\n\twireTransportConnectionLogs,\r\n\tAsaiCommon,\r\n\tAsaiUtils,\r\n\tsysserver,\r\n};\r\n\r\nexport type {\r\n\tAsaiNodejsHostPlugin,\r\n\tAsaiNodejsHostPluginBase,\r\n\tAsaiRuntime,\r\n\tAsaiHostNodejsOptions,\r\n\tHostBootResult,\r\n\tHostConfig,\r\n\tSecurityConfig,\r\n\tHostSiteConfig,\r\n\tProxySiteConfig,\r\n\tLoggerConfig,\r\n\tRouteFactory,\r\n\tWorkHandler,\r\n\tWsWorkHandler,\r\n} from './src/types';\r\n\r\nexport type { AsaiSecrets } from './src/config/secrets';\r\nexport type { TransportKind, ReconnectOptions } from './src/config/syscom';\r\nexport type { SecurityAuditEvent, SecurityEventType } from './src/infra/security-audit';\r\nexport type { AuthCheckResult } from './src/infra/access-control';\r\nexport type { SysserverBootOptions, SysserverFn } from './src/sysserver/index';\r\nexport type { StoreDomain } from './src/sysserver/db/data-store';\r\n\r\n/** 构建时注入的版本号(与 package.json version 同步) */\r\nexport const PLUGIN_VERSION =\r\n\ttypeof __ASAIHOST_NODEJS_VERSION__ !== 'undefined'\r\n\t\t? __ASAIHOST_NODEJS_VERSION__\r\n\t\t: '0.0.1';\r\n\r\nexport default initAsaiHostNodejs;\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,YAAY,QAAQ;;;ACLpB,YAAY,QAAQ;AAEb,SAAS,QAAgB;AAC/B,MAAI;AACH,UAAM,aAAgB,qBAAkB;AACxC,eAAW,QAAQ,OAAO,KAAK,UAAU,GAAG;AAC3C,YAAM,QAAQ,WAAW,IAAI;AAC7B,UAAI,CAAC,MAAO;AACZ,iBAAW,SAAS,OAAO;AAC1B,YAAI,MAAM,WAAW,UAAU,MAAM,YAAY,eAAe,CAAC,MAAM,UAAU;AAChF,iBAAO,MAAM;AAAA,QACd;AAAA,MACD;AAAA,IACD;AAAA,EACD,SAAS,KAAK;AACb,YAAQ,MAAM,yBAAyB,GAAG;AAAA,EAC3C;AACA,SAAO;AACR;AAhBgB;AAkBT,SAAS,UAAU,IAAoB,OAAqB;AAClE,MAAI,MAAM,OAAO,OAAO,SAAU,QAAO;AACzC,MAAI,OAAO,YAAY,OAAO,OAAQ,QAAO;AAC7C,SAAO,OAAO,YAAY,MAAM;AACjC;AAJgB;;;AClBhB,IAAM,eAAe,oBAAI,IAAiB;AAC1C,IAAM,oBAAoB,oBAAI,IAAiB;AAExC,SAAS,gBAAgB,SAA0B;AACzD,MAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,KAAK,QAAQ,SAAS,OAAO,YAAY,aAAa,YAAY,QAAQ;AAC/H,WAAO;AAAA,EACR;AACA,SAAO,mBAAmB,KAAK,OAAO;AACvC;AALgB;AAOhB,SAAS,YAAY,SAAiB,OAAiB;AACtD,MAAI,OAAO,aAAa,IAAI,OAAO;AACnC,MAAI,CAAC,MAAM;AACV,UAAM,aAAa,MAAM,WAAW,MAAM,WAAW,CAAC;AACtD,UAAM,UAAU,MAAM,WAAW,MAAM,OAAO,KAAK,CAAC;AACpD,WAAO,EAAE,GAAG,YAAY,GAAG,QAAQ;AACnC,iBAAa,IAAI,SAAS,IAAI;AAAA,EAC/B;AACA,SAAO;AACR;AATS;AAYF,SAAS,WAAW,SAAiB,OAAiB;AAC5D,SAAO,EAAE,GAAG,YAAY,SAAS,KAAK,EAAE;AACzC;AAFgB;AAIhB,SAAS,iBAAiB,cAAsB,OAAiB;AAChE,MAAI,OAAO,kBAAkB,IAAI,YAAY;AAC7C,MAAI,CAAC,MAAM;AACV,UAAM,aAAa,MAAM,WAAW,YAAY,WAAW,CAAC;AAC5D,UAAM,WAAW,MAAM,WAAW,aAAa,YAAY,KAAK,CAAC;AACjE,WAAO,EAAE,GAAG,YAAY,GAAG,SAAS;AACpC,QAAI,CAAC,KAAK,OAAO,KAAK,MAAM;AAC3B,WAAK,OAAO,KAAK,YAAY,aAAa,UAAU,KAAK,IAAI,KAAK,IAAI,MAAM,KAAK;AAAA,IAClF;AACA,sBAAkB,IAAI,cAAc,IAAI;AAAA,EACzC;AACA,SAAO;AACR;AAZS;AAcF,SAAS,gBAAgB,cAAsB,OAAiB;AACtE,SAAO,EAAE,GAAG,iBAAiB,cAAc,KAAK,EAAE;AACnD;AAFgB;;;ACpCT,SAAS,YAAY,OAAY,IAA0C;AAC9E,QAAM,eAAe,OAAO,YAAY,IAAI,UAAU;AACtD,QAAM,iBAAiB,OAAO,YAAY,IAAI,iBAAiB;AAC/D,QAAM,eAAyB,CAAC;AAGhC,MAAI,QAAQ,MAAM,OAAO,QAAQ,OAAO,cAAc,8BAA8B,SAAS;AACzF,YAAQ,GAAG,4BAA4B,CAAC,QAAe;AACnD,UAAI;AACA,cAAM,KAAK,SAAS,mBAAmB,KAAK,WAAW,GAAG,EAAE;AAAA,MAChE,QAAQ;AAAA,MAER;AAAA,IACJ,CAAC;AAAA,EACL;AAEA,UAAQ,GAAG,sBAAsB,CAAC,QAAiB,YAA8B;AAC7E,UAAM,aAAa,IAAI,MAAM,EAAE;AAC/B,QAAI,cAAc;AAClB,QAAI,WAAW,OAAO,YAAY,UAAU;AACxC,oBAAc,QAAQ,aAAa,QAAQ;AAC3C,YAAM,aAAa,YAAY,MAAM,IAAI,KAAK,CAAC;AAC/C,YAAM,gBAAgB,WAAW,MAAM,GAAG,CAAC,EAAE,KAAK,KAAK;AACvD,qBAAe,gBAAgB,aAAa;AAAA,IAChD;AAEA,QAAI,aAAa;AACjB,QAAI,kBAAkB,OAAO;AACzB,mBAAa;AAAA,EAAK,OAAO,IAAI,KAAK,OAAO,OAAO;AAChD,UAAI,OAAO,MAAO,eAAc;AAAA,mBAAY,OAAO,KAAK;AAAA,IAC5D,WAAW,OAAO,WAAW,YAAY,WAAW,MAAM;AACtD,UAAI;AACA,qBAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,UAAU,GAAG,GAAG;AAAA,MACjE,QAAQ;AACJ,qBAAa,OAAO,MAAM;AAAA,MAC9B;AAAA,IACJ,OAAO;AACH,mBAAa,OAAO,MAAM;AAAA,IAC9B;AAEA,UAAM,WAAW;AAAA,qBAA0C,UAAU;AAAA,qBAAc,WAAW;AAC9F,UAAM,KAAK,uBAAuB,QAAQ;AAAA,EAC9C,CAAC;AAED,UAAQ,GAAG,qBAAqB,CAAC,QAAe;AAC5C,UAAM,WAAW,uBAAuB,KAAK,UAAU,GAAG,CAAC;AAC3D,QAAI;AACA,YAAM,KAAK,uBAAuB,QAAQ;AAAA,IAC9C,QAAQ;AAAA,IAER;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,iBAAa,KAAK,GAAG;AACrB,WAAO,aAAa,SAAS,KAAK,aAAa,CAAC,IAAI,MAAM,gBAAgB;AACtE,mBAAa,MAAM;AAAA,IACvB;AAEA,QAAI,aAAa,SAAS,cAAc;AACpC,UAAI;AACA,cAAM,KAAK,cAAc,kFAAkF;AAC3G,aAAK,OAAO,qCAA4C,EAAE;AAAA,UAAK,CAAC,EAAE,qBAAqB,MACnF,qBAAqB,OAAO;AAAA,YACxB,QAAQ;AAAA,YACR,QAAQ,GAAG,aAAa,MAAM,eAAe,cAAc;AAAA,YAC3D,SAAS;AAAA,YACT,UAAU;AAAA,UACd,CAAC;AAAA,QACL,EAAE,MAAM,MAAM,MAAS;AAAA,MAC3B,QAAQ;AAAA,MAER;AACA,UAAI;AACA,cAAM,KAAK,YAAY,UAAU,KAAK,WAAW,GAAG;AAAA,MACxD,QAAQ;AAAA,MAER;AACA,uBAAiB,KAAK;AACtB;AAAA,IACJ;AAEA,QAAI,MAAM,OAAO,OAAO,YAAY;AAChC,UAAI;AACA,WAAG,GAAG;AAAA,MACV,SAAS,aAAa;AAClB,gBAAQ,MAAM,oCAAoC,WAAW;AAAA,MACjE;AAAA,IACJ;AAAA,EACJ,CAAC;AAED,UAAQ,GAAG,WAAW,MAAM;AACxB,QAAI;AACA,YAAM,KAAK,WAAW,yBAAoB;AAAA,IAC9C,QAAQ;AAAA,IAER;AACA,qBAAiB,KAAK;AAAA,EAC1B,CAAC;AAED,UAAQ,GAAG,UAAU,MAAM;AACvB,QAAI;AACA,YAAM,KAAK,UAAU,wBAAmB;AAAA,IAC5C,QAAQ;AAAA,IAER;AACA,qBAAiB,KAAK;AAAA,EAC1B,CAAC;AACL;AA3GgB;AA6GT,SAAS,iBAAiB,OAAkB;AAC/C,OAAK,OAAO,qCAA4C,EAAE;AAAA,IAAK,CAAC,EAAE,qBAAqB,MACnF,qBAAqB,OAAO;AAAA,MACxB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACb,CAAC;AAAA,EACL,EAAE,MAAM,MAAM,MAAS;AAEvB,QAAM,kBAAkB;AACxB,MAAI;AAEJ,QAAM,YAAY,KAAK,IAAI;AAC3B,kBAAgB,WAAW,MAAM;AAC7B,UAAM,KAAK,YAAY,0BAA0B,KAAK,IAAI,IAAI,SAAS,IAAI;AAC3E,YAAQ,KAAK,CAAC;AAAA,EAClB,GAAG,eAAe;AAElB,MAAI;AACA,WAAO,OAAO,MAAM,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAgB;AAC5D,UAAI,UAAU,OAAO,OAAO,UAAU,YAAY;AAC9C,eAAO,MAAM,CAAC,QAAgB;AAC1B,cAAI,IAAK,OAAM,KAAK,QAAQ,4BAA4B,GAAG;AAAA,QAC/D,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAED,WAAO,OAAO,MAAM,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAgB;AAC1D,UAAI,UAAU,OAAO,OAAO,UAAU,YAAY;AAC9C,eAAO,MAAM,CAAC,QAAgB;AAC1B,cAAI,IAAK,OAAM,KAAK,MAAM,0BAA0B,GAAG;AAAA,QAC3D,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAED,QAAI,MAAM,WAAW,SAAS;AAC1B,mBAAa,MAAM,WAAW,OAAO;AACrC,YAAM,WAAW,UAAU;AAAA,IAC/B;AAEA,WAAO,KAAK,MAAM,WAAW,CAAC,CAAC,EAAE,QAAQ,CAAC,YAAY;AAClD,UAAI,MAAM,QAAQ,OAAO,EAAE,aAAa;AACpC,sBAAc,MAAM,QAAQ,OAAO,EAAE,WAAW;AAChD,eAAO,MAAM,QAAQ,OAAO,EAAE;AAAA,MAClC;AAAA,IACJ,CAAC;AAED,eAAW,MAAM;AACb,mBAAa,aAAa;AAC1B,YAAM,KAAK,YAAY,sBAAsB,KAAK,IAAI,IAAI,SAAS,KAAK;AACxE,cAAQ,KAAK,CAAC;AAAA,IAClB,GAAG,GAAI;AAAA,EACX,SAAS,KAAK;AACV,UAAM,KAAK,YAAY,4BAA4B,GAAG;AACtD,iBAAa,aAAa;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAClB;AACJ;AAzDgB;;;AC1GhB,OAAO,QAAQ;AAYf,IAAM,aAAa,oBAAI,IAAuB;AAG9C,SAAS,qBAA2B;AAClC,aAAW,QAAQ,CAAC,WAAW;AAC7B,WAAO,WAAW;AAAA,EACpB,CAAC;AACH;AAJS;AAWT,IAAM,YAAN,MAAM,WAAU;AAAA,EASd,YACU,OACA,UACR;AAFQ;AACA;AAVV,SAAQ,SAAmB,CAAC;AAC5B,SAAQ,QAA8C;AACtD,SAAiB,gBAAgB;AACjC;AAAA,SAAiB,gBAAgB;AAU/B,QAAI,CAAC,WAAU,uBAAuB;AACpC,iBAAU,wBAAwB;AAClC,cAAQ,KAAK,cAAc,MAAM,mBAAmB,CAAC;AAAA,IACvD;AAAA,EACF;AAAA,EAtDF,OAoCgB;AAAA;AAAA;AAAA,EAOd;AAAA;AAAA;AAAA,SAAe,wBAAwB;AAAA;AAAA;AAAA,EAchC,IAAI,SAAuB;AAChC,SAAK,OAAO,KAAK,OAAO;AAExB,QAAI,KAAK,OAAO,UAAU,KAAK,eAAe;AAC5C,WAAK,MAAM;AAAA,IACb,WAAW,CAAC,KAAK,OAAO;AACtB,WAAK,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,aAAa;AAAA,IAChE;AAAA,EACF;AAAA;AAAA,EAGO,aAAmB;AACxB,SAAK,MAAM;AAAA,EACb;AAAA;AAAA,EAGQ,QAAc;AACpB,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AACA,QAAI,KAAK,OAAO,WAAW,EAAG;AAE9B,UAAM,aAAa,KAAK,OAAO,KAAK,EAAE;AACtC,SAAK,SAAS,CAAC;AACf,SAAK,KAAK,WAAW,UAAU;AAAA,EACjC;AAAA,EAEA,MAAc,WAAW,YAAmC;AAC1D,QAAI;AACF,YAAM,EAAE,YAAAA,YAAW,IAAI,KAAK,MAAM,KAAK;AACvC,YAAMA,YAAW,KAAK,QAAQ;AAC9B,YAAM,OAAO,MAAM,GAAG,KAAK,KAAK,QAAQ;AACxC,YAAM,UAAU,KAAK,MAAM,WAAW,QAAQ,MAAM,WAAW;AAC/D,UAAI,KAAK,QAAQ,SAAS;AACxB,cAAM,YAAY,KAAK,SAAS,YAAY,GAAG;AAC/C,cAAM,WAAW,KAAK,SAAS,UAAU,GAAG,SAAS;AACrD,cAAM,UAAU,KAAK,SAAS,UAAU,SAAS;AACjD,cAAM,GAAG;AAAA,UACP,KAAK;AAAA,UACL,GAAG,QAAQ,IAAI,WAAW,CAAC,CAAC,GAAG,OAAO;AAAA,QACxC;AAAA,MACF;AACA,YAAM,GAAG,WAAW,KAAK,UAAU,YAAY,MAAM;AACrD,YAAM,MAAM,KAAK,SAAS,SAAS,UAAU,KAAK,KAAK,SAAS,SAAS,YAAY,IAAI,WAAW;AACpG,YAAM,OAAO,WAAW,SAAS,aAAa,IAAI,QAAQ;AAC1D,WAAK,aAAa,KAAK,OAAO;AAAA,QAC5B,QAAQ,SAAS,QAAQ,QAAQ;AAAA,QACjC,SAAS;AAAA,MACX,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IAC1B,SAAS,KAAK;AACZ,cAAQ,MAAM,oBAAoB,GAAG;AAAA,IACvC;AAAA,EACF;AAAA;AAAA,EAGO,UAAgB;AACrB,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,MAAM;AAAA,EACb;AACF;AAMA,SAAS,QAAQ,OAAY,KAAa,QAA+B;AACvE,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,QAAI;AACF,YAAM,YAAY,GAAG,MAAM,MAAM,SAAS,IAAI,GAAG;AACjD,UAAI,YAAY,WAAW,IAAI,SAAS;AACxC,UAAI,CAAC,WAAW;AACd,oBAAY,IAAI,UAAU,OAAO,GAAG;AACpC,mBAAW,IAAI,WAAW,SAAS;AAAA,MACrC;AACA,gBAAU,IAAI,MAAM;AACpB,MAAAA,SAAQ;AAAA,IACV,SAAS,KAAK;AACZ,cAAQ,MAAM,GAAG;AACjB,aAAO,GAAG;AAAA,IACZ;AAAA,EACF,CAAC;AACH;AAhBS;AA8BT,IAAM,mBAAmB,oBAAI,IAAY;AAEzC,eAAe,gBAAgB,OAAY,UAAkB,SAA8B;AACzF,MAAI,iBAAiB,IAAI,QAAQ,EAAG;AACpC,MAAI;AACF,UAAM,OAAO,MAAM,GAAG,KAAK,QAAQ;AACnC,QAAI,KAAK,OAAO,GAAG;AACjB,uBAAiB,IAAI,QAAQ;AAC7B;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,QAAM,SAAS,gBAAgB;AAAA,IAC7B,UAAU,MAAM,WAAW,SAAS,SAAS;AAAA,IAC7C,SAAS,MAAM,WAAW,SAAS,OAAO;AAAA,IAC1C,QAAQ,CAAC,GAAG,iBAAiB;AAAA,IAC7B,MAAM;AAAA,EACR,CAAC;AACD,QAAM,GAAG,WAAW,UAAU,QAAQ,MAAM;AAC5C,mBAAiB,IAAI,QAAQ;AAC/B;AAnBe;AA+Bf,IAAM,cAAc,oBAAI,IAAyB;AAEjD,IAAM,wBAAwB;AAQ9B,eAAsB,UACpB,OACA,KACA,QACe;AACf,MAAI;AACF,UAAM,UAAU,MAAM,WAAW,QAAQ,MAAM,WAAW;AAC1D,QAAI,OAAO,YAAY,IAAI,GAAG;AAC9B,UAAM,MAAM,KAAK,IAAI;AAGrB,QACE,CAAC,QACD,CAAC,KAAK,WACN,MAAM,KAAK,cAAc,uBACzB;AACA,YAAM,EAAE,YAAAC,YAAW,IAAI,MAAM,KAAK;AAClC,YAAMA,YAAW,GAAG;AACpB,YAAM,OAAO,MAAM,GAAG,KAAK,GAAG;AAC9B,aAAO,EAAE,SAAS,MAAM,MAAM,KAAK,MAAM,YAAY,IAAI;AACzD,kBAAY,IAAI,KAAK,IAAI;AAAA,IAC3B;AAGA,QAAI,KAAK,QAAQ,SAAS;AACxB,YAAM,UAAe,oBAAI,KAAK;AAC9B,YAAM,YAAY,IAAI,YAAY,GAAG;AACrC,YAAM,WAAW,IAAI,UAAU,GAAG,SAAS;AAC3C,YAAM,UAAU,IAAI,UAAU,SAAS;AACvC,YAAM,GAAG,OAAO,KAAK,GAAG,QAAQ,IAAI,WAAW,GAAG,OAAO,CAAC,GAAG,OAAO,EAAE;AACtE,WAAK,UAAU;AACf,WAAK,OAAO;AAAA,IACd;AAGA,SAAK,QAAQ,OAAO,WAAW,MAAM;AACrC,UAAM,QAAQ,OAAO,KAAK,MAAM;AAAA,EAClC,SAAS,KAAK;AACZ,YAAQ,MAAM,GAAG;AAEjB,gBAAY,OAAO,GAAG;AAAA,EACxB;AACF;AA1CsB;AA6CtB,eAAsB,gBAAgB,OAAY,SAAiB,SAAgC;AACjG,QAAM,YAAY,MAAM,WAAW,QAAQ,MAAM;AACjD,MAAI,CAAC,UAAW;AAChB,QAAM,UAAU,oBAAI,KAAK;AACzB,QAAM,UAAU,WAAW,GAAG,OAAO;AACrC,QAAM,UAAU,GAAG,SAAS,cAAc,OAAO;AACjD,QAAM,UAAU,GAAG,SAAS,cAAc,OAAO;AAEjD,MAAI;AACF,UAAM,EAAE,YAAAA,YAAW,IAAI,MAAM,KAAK;AAClC,UAAMA,YAAW,OAAO;AACxB,UAAM,GAAG,WAAW,SAAS,SAAS,MAAM;AAC5C,UAAM,sBAAsB,OAAO,SAAS,OAAO;AACnD,UAAM,GAAG,WAAW,SAAS,SAAS,MAAM;AAC5C,UAAM,YAAY,SAAS,OAAO;AAClC,SAAK,gBAAgB,OAAO;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,MAAM,WAAW;AAAA,MACjB,QAAQ,WAAW;AAAA,MACnB,KAAK,WAAW;AAAA,MAChB,QAAQ,WAAW;AAAA,IACrB,CAAC,EAAE,MAAM,MAAM,MAAS;AACxB,SAAK,gBAAgB,OAAO;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,EAC1B,SAAS,KAAK;AACZ,YAAQ,MAAM,2BAA2B,GAAG;AAAA,EAC9C;AACF;AA9BsB;AAgCtB,IAAM,yBAAyB,oBAAI,IAAY;AAE/C,eAAe,sBAAsB,OAAY,UAAkB,SAA8B;AAC/F,MAAI,uBAAuB,IAAI,QAAQ,EAAG;AAC1C,MAAI;AACF,UAAM,OAAO,MAAM,GAAG,KAAK,QAAQ;AACnC,QAAI,KAAK,OAAO,GAAG;AACjB,6BAAuB,IAAI,QAAQ;AACnC;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,QAAM,SAAS,gBAAgB;AAAA,IAC7B,UAAU,MAAM,WAAW,SAAS,SAAS;AAAA,IAC7C,SAAS,MAAM,WAAW,SAAS,OAAO;AAAA,IAC1C,QAAQ,CAAC,GAAG,iBAAiB;AAAA,IAC7B,MAAM;AAAA,EACR,CAAC;AACD,QAAM,GAAG,WAAW,UAAU,QAAQ,MAAM;AAC5C,yBAAuB,IAAI,QAAQ;AACrC;AAnBe;AAwCR,SAAS,QAAQ,OAAkB;AAExC,WAAS,QAAQ,MAAmB;AAClC,QAAI,MAAM,WAAW,QAAQ,IAAI,MAAM;AACrC,cAAQ,IAAI,GAAG,IAAI;AAAA,IACrB;AAAA,EACF;AAJS;AAMT,WAAS,UAAU,MAAmB;AACpC,QAAI,gBAAgB,MAAO,QAAO,KAAK,WAAW,OAAO,IAAI;AAC7D,QAAI,OAAO,SAAS,UAAU;AAC5B,UAAI;AACF,eAAO,KAAK,UAAU,IAAI;AAAA,MAC5B,QAAQ;AACN,eAAO,OAAO,IAAI;AAAA,MACpB;AAAA,IACF;AACA,WAAO,OAAO,IAAI;AAAA,EACpB;AAVS;AAaT,WAAS,aAAa,MAAsB;AAC1C,UAAM,SAAS,MAAM,WAAW,QAAQ;AACxC,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,UAAM,UAAU,KAAK,KAAK,CAAC,MAAM,OAAO,MAAM,QAAQ;AACtD,QAAI,CAAC,WAAW,OAAO,OAAO,KAAK,KAAM,QAAO;AAChD,UAAM,OAAO,OAAO,OAAO,OAAO,CAAC;AACnC,QAAI,OAAO,MAAM,IAAI,KAAK,QAAQ,EAAG,QAAO;AAC5C,QAAI,QAAQ,EAAG,QAAO;AACtB,WAAO,KAAK,OAAO,IAAI;AAAA,EACzB;AATS;AAWT,WAAS,iBAAiB,SAAiB,QAA4B,KAAyB,SAAiB,SAAqB;AACpI,UAAM,WAAW,GAAG,MAAM,WAAW,OAAO,KAAK,MAAM,OAAO,WAAW,GAAG,OAAO,CAAC;AACpF,UAAM,SAAS,sBAAsB;AAAA,MACnC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,gBAAgB,OAAO,UAAU,OAAO;AAC9C,cAAM,QAAQ,OAAO,UAAU,MAAM;AAAA,MACvC,SAAS,KAAK;AACZ,gBAAQ,MAAM,sBAAsB,GAAG;AAAA,MACzC;AAAA,IACF,GAAG;AAAA,EACL;AAjBS;AAoBT,WAAS,QAAQ,MAAmB;AAClC,SAAK,GAAG,IAAI;AAAA,EACd;AAFS;AAKT,WAAS,QAAQ,MAAmB;AAClC,QAAI,CAAC,aAAa,IAAI,EAAG;AAEzB,UAAM,UAAU,oBAAI,KAAK;AACzB,UAAM,UAAU,KAAK,CAAC;AAEtB,QAAI,YAAY,GAAG;AACjB,UAAI,MAAM,WAAW,QAAQ,MAAM,QAAQ;AACzC,cAAM,SAAS,KAAK,MAAM,CAAC,EAAE,IAAI,SAAS,EAAE,KAAK,IAAI;AACrD,cAAM,SAAS,sBAAsB;AAAA,UACnC,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX,CAAC;AACD,aAAK,IAAI,WAAW,GAAG,OAAO,CAAC;AAAA,EAAM,MAAM;AAAA,CAAI;AAC/C,cAAM,WAAW,GAAG,MAAM,WAAW,OAAO,KAAK,MAAM,OAAO,WAAW,GAAG,OAAO,CAAC;AACpF,cAAM,YAAY;AAChB,cAAI;AACF,kBAAM,gBAAgB,OAAO,UAAU,OAAO;AAC9C,kBAAM,QAAQ,OAAO,UAAU,MAAM;AAAA,UACvC,SAAS,KAAK;AACZ,oBAAQ,MAAM,sBAAsB,GAAG;AAAA,UACzC;AAAA,QACF,GAAG;AAAA,MACL;AACA;AAAA,IACF;AAEA,UAAM,UAAU,OAAO,YAAY,WAAW,UAAU;AACxD,UAAM,WAAW,OAAO,YAAY,YAAY,UAAU,MAAM,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC;AAC5F,UAAM,UAAU,SAAS,IAAI,SAAS,EAAE,KAAK,IAAI,EAAE,QAAQ,WAAW,GAAG;AACzE,QAAI;AACJ,QAAI;AACJ,QAAI,OAAO,SAAS,CAAC,MAAM,YAAY,OAAO,SAAS,CAAC,MAAM,UAAU;AACtE,eAAS,SAAS,CAAC;AACnB,YAAM,SAAS,CAAC;AAAA,IAClB;AAEA,QAAI,OAAO,YAAY,YAAY,UAAU,KAAK;AAChD,UAAI,MAAM,WAAW,QAAQ,MAAM,QAAQ;AACzC,yBAAiB,SAAS,QAAQ,KAAK,SAAS,OAAO;AAAA,MACzD;AAAA,IACF,WAAW,MAAM,WAAW,QAAQ,MAAM,QAAQ;AAChD,YAAM,cAAc,IAAI,WAAW,GAAG,OAAO,CAAC,KAAK,OAAO;AAAA;AAC1D,WAAK,WAAW;AAChB,uBAAiB,SAAS,QAAQ,KAAK,SAAS,OAAO;AAAA,IACzD;AAAA,EACF;AA/CS;AAiDT,MACE,SACA,OAAO,UAAU,YACjB,MAAM,WAAW,QAAQ,IAAI,QAC7B;AACA,UAAM,OAAO;AAAA,EACf,OAAO;AACL,UAAM,OAAO;AAAA,EACf;AACF;AAnHgB;;;AC3ThB,IAAM,iBAAiB,oBAAI,IAAI,CAAC,UAAU,aAAa,CAAC;AAEjD,IAAM,eAAN,MAAmB;AAAA,EAAnB;AACN,SAAQ,SAAmB,CAAC;AAAA;AAAA,EAN7B,OAK0B;AAAA;AAAA;AAAA,EAGzB,QAAQ,MAAsB;AAC7B,SAAK,SAAS,KAAK,OAAO,CAAC,MAAM,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAAA,EACjG;AAAA,EAEA,QAAQ,IAA4C;AACnD,QAAI,CAAC,MAAM,OAAO,OAAO,SAAU,QAAO;AAC1C,eAAW,SAAS,KAAK,QAAQ;AAChC,UAAI,GAAG,WAAW,KAAK,EAAG,QAAO;AAAA,IAClC;AACA,WAAO;AAAA,EACR;AAAA,EAEA,YAAY,KAAiC;AAC5C,QAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,eAAW,SAAS,KAAK,QAAQ;AAChC,UAAI,IAAI,WAAW,KAAK,EAAG,QAAO;AAAA,IACnC;AACA,WAAO;AAAA,EACR;AACD;AAQO,SAAS,aAAa,KAAsB;AAClD,SAAO,CAAC,CAAC,OAAO,CAAC,eAAe,IAAI,GAAG;AACxC;AAFgB;;;AC5BT,SAAS,mBAAmB,OAA0B;AAC5D,MAAI,CAAC,MAAM,cAAc;AACxB,UAAM,eAAe,IAAI,aAAa;AAAA,EACvC;AACA,SAAO,MAAM;AACd;AALgB;AAOT,SAAS,iBAAiB,OAAkB;AAClD,QAAM,iBAAiB,OAAO,KAAK,MAAM,iBAAiB,CAAC,CAAC;AAC7D;AAFgB;AAIT,SAAS,gBAAgB,OAAkB;AACjD,QAAM,OAAO,OAAO,KAAK,MAAM,gBAAgB,CAAC,CAAC,EAAE,OAAO,YAAY;AACtE,QAAM,gBAAgB;AACtB,qBAAmB,KAAK,EAAE,QAAQ,IAAI;AACvC;AAJgB;AAOT,SAAS,YAAY,OAAY,KAAa,SAA6B;AACjF,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO,CAAC;AAC/B,MAAI,CAAC,MAAM,KAAK,IAAK,OAAM,KAAK,MAAM,CAAC;AACvC,QAAM,KAAK,IAAI,GAAG,IAAI;AACtB,MAAI,MAAM,eAAe;AACxB,UAAM,cAAc,GAAG,IAAI;AAC3B,qBAAiB,KAAK;AAAA,EACvB;AACD;AARgB;AAWT,SAAS,WAAW,OAAY,KAAa,SAA6B;AAChF,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO,CAAC;AAC/B,MAAI,CAAC,MAAM,KAAK,GAAI,OAAM,KAAK,KAAK,CAAC;AACrC,QAAM,KAAK,GAAG,GAAG,IAAI;AACrB,MAAI,MAAM,cAAc;AACvB,UAAM,aAAa,GAAG,IAAI;AAC1B,oBAAgB,KAAK;AAAA,EACtB;AACD;AARgB;AAWT,SAAS,kBAAkB,OAAY,QAAsC,CAAC,GAAS;AAC7F,QAAM,gBAAgB;AAAA,IACrB,GAAI,MAAM,MAAM,OAAO,CAAC;AAAA,IACxB,GAAG;AAAA,EACJ;AACA,mBAAiB,KAAK;AACvB;AANgB;AAST,SAAS,iBAAiB,OAAY,QAAsC,CAAC,GAAQ;AAC3F,QAAM,eAAe,MAAM,MAAM,WAAW,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC;AAC1E,QAAM,eAAe;AAAA,IACpB,GAAI,gBAAgB,CAAC;AAAA,IACrB,GAAI,MAAM,MAAM,MAAM,CAAC;AAAA,IACvB,GAAG;AAAA,EACJ;AACA,kBAAgB,KAAK;AACrB,SAAO;AACR;AATgB;AAYT,SAAS,eAAe,OAAkB;AAChD,QAAM,cAAc,CAAC,KAAa,YAA0B,YAAY,OAAO,KAAK,OAAO;AAC3F,QAAM,aAAa,CAAC,KAAa,YAA0B,WAAW,OAAO,KAAK,OAAO;AAC1F;AAHgB;;;AC9ChB,SAAS,eAAe,OAAqB;AAC5C,QAAM,MAAM,OAAO,YAAY;AAC/B,MAAI,OAAO,OAAO,IAAI,aAAa,SAAU,QAAO,IAAI,aAAa;AACrE,SAAO;AACR;AAJS;AAMF,SAAS,iBAAiB,OAAY,OAAiC;AAC7E,MAAI,CAAC,eAAe,KAAK,EAAG;AAC5B,QAAM,MAAK,oBAAI,KAAK,GAAE,YAAY;AAClC,QAAM,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM,UAAU;AAAA,IAChB,MAAM,QAAQ;AAAA,IACd,MAAM,OAAO,QAAQ,MAAM,IAAI,KAAK;AAAA,IACpC,MAAM,SAAS,OAAO,MAAM,MAAM,KAAK,KAAK;AAAA,IAC5C,MAAM,UAAU;AAAA,IAChB,MAAM,KAAK,MAAM,MAAM,EAAE,KAAK;AAAA,EAC/B,EAAE,OAAO,OAAO;AAChB,QAAM,OAAO,MAAM,KAAK,GAAG;AAC3B,GAAC,OAAO,QAAQ,QAAQ,MAAM,OAAO,IAAI;AAC1C;AAhBgB;AAkBT,SAAS,YAAY,KAAkB;AAC7C,QAAM,YAAY,KAAK,UAAU,iBAAiB;AAClD,MAAI,OAAO,cAAc,YAAY,UAAU,SAAS,GAAG;AAC1D,WAAO,UAAU,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK;AAAA,EACrC;AACA,SAAO,KAAK,QAAQ,iBAAiB;AACtC;AANgB;;;AC3CT,IAAM,sBAAsB,CAAC,eAAe,UAAU,UAAU,aAAa;AAE7E,SAAS,uBAAuB,OAAsB;AAC5D,QAAM,WAAqB,CAAC;AAC5B,QAAM,MAAM,OAAO,YAAY;AAC/B,QAAM,OAAO,OAAO,KAAK,aAAa,aAAa,EAAE,YAAY;AACjE,MAAI,CAAC,oBAAoB,SAAS,IAA4C,GAAG;AAChF,aAAS,KAAK,+CAAY,IAAI,oBAAU;AAAA,EACzC;AACA,MAAI,KAAK,aAAa,OAAO,IAAI,SAAS,IAAI,KAAK;AAClD,aAAS,KAAK,6CAAe,IAAI,SAAS,oCAAW;AAAA,EACtD;AACA,SAAO;AACR;AAXgB;;;ACFhB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAE1B,IAAM,gBAAgB,UAAU,QAAQ;AAExC,eAAsB,eAAe,cAAc,KAAmE;AACrH,MAAI,QAAQ,aAAa,SAAS;AACjC,QAAI;AACH,YAAM,EAAE,OAAO,IAAI,MAAM,cAAc,SAAS,CAAC,UAAU,SAAS,GAAG,EAAE,SAAS,IAAK,CAAC;AACxF,UAAI,sBAAsB,KAAK,MAAM,KAAK,UAAU,KAAK,MAAM,GAAG;AACjE,eAAO,EAAE,IAAI,MAAM,QAAQ,8BAA8B;AAAA,MAC1D;AACA,aAAO,EAAE,IAAI,OAAO,QAAQ,sCAAsC;AAAA,IACnE,QAAQ;AACP,aAAO,EAAE,IAAI,OAAO,QAAQ,oBAAoB;AAAA,IACjD;AAAA,EACD;AACA,MAAI;AACH,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,eAAe,CAAC,QAAQ,MAAM,mBAAmB,SAAS,GAAG,EAAE,SAAS,IAAK,CAAC;AACrH,QAAI,OAAO,KAAK,MAAM,MAAO,QAAO,EAAE,IAAI,MAAM,QAAQ,iCAAiC;AAAA,EAC1F,QAAQ;AAAA,EAER;AACA,MAAI;AACH,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,WAAW,CAAC,MAAM,cAAc,GAAG,EAAE,SAAS,IAAK,CAAC;AAC3F,UAAM,IAAI,OAAO,MAAM,4BAA4B;AACnD,QAAI,GAAG;AACN,YAAM,WAAW,KAAK,IAAI,WAAW,EAAE,CAAC,CAAC,IAAI,GAAI;AACjD,aAAO;AAAA,QACN,IAAI,YAAY;AAAA,QAChB;AAAA,QACA,QAAQ,kBAAkB,QAAQ;AAAA,MACnC;AAAA,IACD;AAAA,EACD,QAAQ;AAAA,EAER;AACA,SAAO,EAAE,IAAI,OAAO,QAAQ,6CAA6C;AAC1E;AAjCsB;;;ACLtB,SAAS,kBAAkB;AAC3B,OAAOC,SAAQ;AACf,OAAO,UAAU;AAEV,SAAS,kBAAkB,YAAmC;AACpE,MAAI;AACH,UAAM,MAAMC,IAAG,aAAa,UAAU;AACtC,WAAO,WAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK;AAAA,EACrD,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAPgB;AAST,SAAS,qBAAqB,YAAqD;AACzF,QAAM,aAAa,KAAK,KAAK,YAAY,0BAA0B;AACnE,QAAM,eAAe,KAAK,KAAK,YAAY,mCAAmC;AAC9E,MAAI,CAACA,IAAG,WAAW,YAAY,GAAG;AACjC,WAAO,EAAE,IAAI,MAAM,QAAQ,yBAAyB;AAAA,EACrD;AACA,MAAI;AACH,UAAM,WAAW,KAAK,MAAMA,IAAG,aAAa,cAAc,MAAM,CAAC;AACjE,UAAM,WAAW,OAAO,SAAS,UAAU,EAAE;AAC7C,UAAM,SAAS,kBAAkB,UAAU;AAC3C,QAAI,CAAC,OAAQ,QAAO,EAAE,IAAI,OAAO,QAAQ,yBAAyB;AAClE,QAAI,YAAY,aAAa,QAAQ;AACpC,aAAO,EAAE,IAAI,OAAO,QAAQ,8BAA8B;AAAA,IAC3D;AACA,WAAO,EAAE,IAAI,MAAM,QAAQ,oBAAoB;AAAA,EAChD,SAAS,GAAQ;AAChB,WAAO,EAAE,IAAI,OAAO,QAAQ,GAAG,WAAW,uBAAuB;AAAA,EAClE;AACD;AAlBgB;;;ACJT,SAAS,mBAAmB,OAAY,MAAiB;AAC/D,MAAI,CAAC,MAAM,YAAY,IAAI;AAC1B,UAAM,WAAW,KAAK,MAAM;AAAA,EAC7B;AACA,QAAM,YAAY,CAAC,KAAa,WAAmB,UAAU,OAAO,KAAK,MAAM;AAC/E,QAAM,kBAAkB,CAAC,SAAiB,YAAoB,gBAAgB,OAAO,SAAS,OAAO;AACrG,QAAM,UAAU,CAAC,YAAoB,WAAW,SAAS,KAAK;AAC9D,QAAM,YAAY,CAAC,OAAuB,UAAU,IAAI,KAAK;AAC7D,QAAM,mBAAmB,MAAM,iBAAiB,KAAK;AACrD,iBAAe,KAAK;AAEpB,cAAY,KAAK;AACjB,UAAQ,KAAK;AAEb,QAAM,WAAW,WAAW,CAAC;AAC7B,QAAM,WAAW,UAAU;AAE3B,MAAI,MAAM,YAAY,KAAK,MAAM,CAAC,MAAM,MAAM,UAAU,OAAO,MAAM,MAAM,UAAU,YAAY;AAChG,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,KAAK,MAAM,KAAK;AACjD,UAAM,KAAK,SAAS;AAAA,MACnB,QAAQ,MAAM,WAAW,IAAI,KAAK;AAAA,MAClC;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,MAAI,qBAAqB,MAAM,YAAY,YAAY,EAAE,GAAG;AAC3D,qBAAiB,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,QAAQ;AAAA,IACT,CAAC;AACD,SAAK,OAAO,qCAA4C,EAAE;AAAA,MAAK,CAAC,EAAE,+BAAAC,+BAA8B,MAC/FA,+BAA8B,OAAO;AAAA,QACpC,SAAS;AAAA,QACT,QAAQ;AAAA,MACT,CAAC;AAAA,IACF,EAAE,MAAM,MAAM,MAAS;AAAA,EACxB;AAEA,6BAA2B,KAAK;AAEhC,aAAW,KAAK,uBAAuB,KAAK,GAAG;AAC9C,qBAAiB,OAAO,EAAE,MAAM,eAAe,QAAQ,EAAE,CAAC;AAAA,EAC3D;AACA,QAAM,OAAO,MAAM,cAAc,QAAQ,IAAI;AAC7C,QAAM,WAAW,qBAAqB,IAAI;AAC1C,MAAI,CAAC,SAAS,IAAI;AACjB,qBAAiB,OAAO,EAAE,MAAM,eAAe,QAAQ,qBAAqB,SAAS,MAAM,GAAG,CAAC;AAAA,EAChG;AACA,OAAK,eAAe,EAAE,KAAK,CAAC,QAAQ;AACnC,QAAI,CAAC,IAAI,GAAI,kBAAiB,OAAO,EAAE,MAAM,eAAe,QAAQ,QAAQ,IAAI,MAAM,GAAG,CAAC;AAAA,EAC3F,CAAC;AACF;AApDgB;AAuDhB,SAAS,2BAA2B,OAAkB;AACrD,QAAM,QAAQ,OAAO,OAAO,YAAY,QAAQ,uBAAuB,KAAK;AAC5E,MAAI,SAAS,EAAG;AAChB,QAAM,KAAK,QAAQ,OAAO;AAC1B,cAAY,MAAM;AACjB,SAAK,OAAO,2BAAkC,EAAE;AAAA,MAAK,CAAC,EAAE,qBAAAC,qBAAoB,MAC3EA,qBAAoB,OAAO,MAAM;AAAA,IAClC,EAAE,MAAM,MAAM,MAAS;AAAA,EACxB,GAAG,EAAE;AACN;AATS;;;AC1DT,YAAY,UAAU;AACtB,YAAY,WAAW;;;ACTvB,SAAS,uBAAkC;;;ACA3C,SAAS,iBAAiB;;;ACAnB,SAAS,mBAAmB,UAAuC,OAA6B;AACtG,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,GAAG;AACpD,WAAO;AAAA,EACR;AACA,MAAI,SAAS,CAAC,GAAG;AAChB,UAAM,KAAK,OAAO,YAAY;AAC9B,QAAI,CAAC,IAAI;AACR,YAAM,KAAK,QAAQ,oDAAoD;AACvE,aAAO;AAAA,IACR;AACA,QAAI;AACH,eAAS,CAAC,IAAI,MAAM,KAAK,OAAO,SAAS,SAAS,CAAC,GAAG,EAAE;AACxD,eAAS,CAAC,IAAI,MAAM,KAAK,OAAO,SAAS,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;AACjE,eAAS,CAAC,IAAI,MAAM,KAAK,OAAO,SAAS,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;AAAA,IAClE,SAAS,KAAK;AACb,YAAM,KAAK,QAAQ,2BAA2B,GAAG;AAAA,IAClD;AAAA,EACD;AACA,SAAO;AACR;AAnBgB;;;ADIT,SAAS,cAAc,KAAU,OAAiB;AACxD,MAAI;AACH,UAAM,MAAM,IAAI,UAAU,wBAAwB;AAClD,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,mBAAmB,IAAI,MAAM,IAAI,GAAG,KAAK;AAAA,EACjD,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AARgB;AAWT,SAAS,kBAAkB,OAAY,SAA4B;AACzE,QAAM,QAAkB,CAAC;AACzB,QAAM,MAAM,MAAM,iBAAiB,CAAC;AACpC,QAAM,OAAO,UAAU,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG;AAClD,aAAW,OAAO,MAAM;AACvB,eAAW,CAAC,IAAIC,GAAE,KAAK,OAAO,QAAQ,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG;AACtD,UAAI,CAAC,MAAM,OAAO,OAAQ;AAC1B,UAAI,gBAAgBA,GAAE,GAAG;AACxB,cAAM,KAAK,EAAE;AAAA,MACd,WAAW,IAAI,GAAG,IAAI,EAAE,MAAMA,KAAI;AACjC,eAAO,IAAI,GAAG,EAAE,EAAE;AAAA,MACnB;AAAA,IACD;AAAA,EACD;AACA,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAC1B;AAfgB;AAkBT,SAAS,iBAAiB,OAAY,IAAY,SAA2B;AACnF,MAAI,CAAC,MAAM,OAAO,OAAQ,QAAO;AACjC,QAAM,MAAM,MAAM,iBAAiB,CAAC;AACpC,QAAM,OAAO,UAAU,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG;AAClD,aAAW,OAAO,MAAM;AACvB,UAAMA,MAAK,IAAI,GAAG,IAAI,EAAE;AACxB,QAAI,CAACA,IAAI;AACT,QAAI,gBAAgBA,GAAE,EAAG,QAAO;AAEhC,QAAI,IAAI,GAAG,IAAI,EAAE,MAAMA,IAAI,QAAO,IAAI,GAAG,EAAE,EAAE;AAAA,EAC9C;AACA,SAAO;AACR;AAZgB;AAeT,SAAS,WAAW,OAAY,IAAY,SAAwB;AAC1E,MAAI,CAAC,MAAM,OAAO,OAAQ;AAC1B,QAAM,MAAM,MAAM,iBAAiB,CAAC;AACpC,QAAM,OAAO,UAAU,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG;AAClD,aAAW,OAAO,MAAM;AACvB,UAAMA,MAAK,IAAI,GAAG,IAAI,EAAE;AACxB,QAAI,CAACA,IAAI;AACT,QAAI;AACH,MAAAA,IAAG,MAAM;AAAA,IACV,QAAQ;AAAA,IAER;AACA,QAAI,IAAI,GAAG,IAAI,EAAE,MAAMA,IAAI,QAAO,IAAI,GAAG,EAAE,EAAE;AAAA,EAC9C;AACD;AAdgB;AAiBhB,eAAe,uBAAuB,OAAY,IAAY,OAAe;AAC5E,MAAI;AACH,UAAM,QAAQ,gBAAgB,KAAK;AACnC,UAAM,WAAW,MAAM,MAAM,YAAY;AACzC,UAAM,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,QAAQ,KAAK;AACjE,QAAI,MAAO,OAAM,MAAM,cAAc,MAAM,EAAE;AAAA,EAC9C,QAAQ;AAAA,EAER;AACD;AATe;AAYf,SAAS,gBAAgBA,KAAkB;AAC1C,MAAI,CAACA,IAAI,QAAO;AAChB,QAAM,QAAQA,IAAG;AACjB,SAAO,UAAU,UAAU,cAAc,UAAU,UAAU;AAC9D;AAJS;AAOT,SAAS,iBAAiBA,KAAS,IAAmC;AACrE,QAAM,UAAU,KAAK,UAAU,EAAE,IAAI,eAAe,IAAI,EAAE,MAAM,GAAG,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;AACzF,MAAI;AACH,IAAAA,IAAG,KAAK,SAAS,MAAM;AACtB,UAAI;AACH,QAAAA,IAAG,MAAM;AAAA,MACV,QAAQ;AAAA,MAER;AAAA,IACD,CAAC;AAAA,EACF,QAAQ;AACP,QAAI;AACH,MAAAA,IAAG,MAAM;AAAA,IACV,QAAQ;AAAA,IAER;AAAA,EACD;AACD;AAjBS;AAmBF,SAAS,OAAO,OAAY,SAAiBA,KAAS,MAAW,SAAuB;AAC9F,QAAM,CAAC,IAAI,EAAE,EAAE,IAAIA,IAAG,YAAY,CAAC;AAEnC,MAAI,CAAC,IAAI;AACR,IAAAA,IAAG,MAAM;AACT,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,UAAU,MAAM,cAAc,OAAO,IAAI,EAAE,GAAG;AACxD,UAAM,aAAa,MAAM,cAAc,OAAO,EAAE,EAAE;AAClD,QAAI,YAAY,WAAW,CAAC,MAAM,IAAI;AAErC,UAAI,gBAAgB,UAAU,GAAG;AAChC,yBAAiBA,KAAI;AAAA,UACpB,MAAM;AAAA,UACN,QAAQ,GAAG,EAAE;AAAA,UACb,KAAK,GAAG,EAAE;AAAA,QACX,CAAC;AACD,eAAO;AAAA,MACR;AACA,UAAI;AACH,mBAAW,MAAM;AAAA,MAClB,QAAQ;AAAA,MAER;AACA,aAAO,MAAM,cAAc,OAAO,EAAE,EAAE;AACtC,aAAO;AAAA,IACR;AAEA,qBAAiBA,KAAI;AAAA,MACpB,MAAM;AAAA,MACN,QAAQ,GAAG,EAAE;AAAA,MACb,KAAK,GAAG,EAAE;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,QAAQ;AAClB,UAAM,cAAc,MAAM,cAAc,OAAO,KAAK,CAAC;AAErD,UAAM,WAAgB,OAAO,OAAO,WAAW,EAAE;AAAA,MAChD,CAAC,SAAc,KAAK,WAAW,CAAC,MAAM,MAAM,KAAK,WAAW,CAAC,MAAM;AAAA,IACpE;AACA,UAAM,YAAY,QAAQ,aAAa;AAEvC,QAAI,UAAU;AACb,uBAAiBA,KAAI;AAAA,QACpB,MAAM;AAAA,QACN,QAAQ,GAAG,EAAE,IAAI,SAAS,SAAS,CAAC,CAAC;AAAA,QACrC,KAAK,GAAG,EAAE,IAAI,SAAS,SAAS,CAAC,CAAC;AAAA,MACnC,CAAC;AACD,aAAO;AAAA,IACR;AACA,QAAI,OAAO,KAAK,WAAW,EAAE,UAAU,WAAW;AACjD,uBAAiBA,KAAI;AAAA,QACpB,MAAM;AAAA,QACN,QAAQ,GAAG,SAAS;AAAA,QACpB,KAAK,OAAO,SAAS;AAAA,MACtB,CAAC;AACD,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AAhEgB;AAkET,SAAS,QACf,OAAY,SAAiBA,KAAS,KAAU,SAChD,eAAqC,cAC9B;AACP,QAAM,CAAC,EAAE,IAAIA,IAAG,YAAY,CAAC;AAC7B,MAAI,CAAC,MAAM,cAAc,OAAO,GAAG;AAClC,UAAM,cAAc,OAAO,IAAI,CAAC;AAAA,EACjC;AAEA,MAAI,MAAM,OAAO,QAAQ;AACxB,QAAI,QAAQ,QAAQ,CAACA,IAAG,QAAS,CAAAA,IAAG,UAAU,CAAC;AAC/C,UAAM,cAAc,OAAO,EAAE,EAAE,IAAIA;AAAA,EACpC;AAEA,EAAAA,IAAG,GAAG,WAAW,CAAC,QAAgB;AACjC,QAAI,aAAc,OAAM,KAAK,MAAM,WAAW,IAAI,SAAS,CAAC;AAC5D,oBAAgB,KAAKA,KAAI,SAAS,GAAG;AAAA,EACtC,CAAC;AAED,EAAAA,IAAG,GAAG,SAAS,MAAM;AACpB,UAAM,QAAQA,IAAG,WAAW,CAAC;AAC7B,QAAI,QAAQ,QAAQA,IAAG,SAAS;AAC/B,aAAO,OAAOA,IAAG,OAAO,EAAE,QAAQ,CAAC,OAAY,MAAM,cAAc,EAAE,CAAC;AACtE,MAAAA,IAAG,UAAU;AAAA,IACd;AAGA,QAAI,MAAM,MAAM,cAAc,OAAO,IAAI,EAAE,MAAMA,IAAI,QAAO,MAAM,cAAc,OAAO,EAAE,EAAE;AAC3F,QAAI,MAAM,SAAS,CAAC,iBAAiB,OAAO,IAAI,OAAO,GAAG;AACzD,WAAK,uBAAuB,OAAO,IAAI,OAAO,KAAK,CAAC;AAAA,IACrD;AACA,QAAIA,IAAG,eAAe,UAAU,UAAUA,IAAG,eAAe,UAAU,QAAS,CAAAA,IAAG,MAAM;AAAA,EACzF,CAAC;AACF;AAjCgB;;;AEzKhB,SAAS,aAAAC,kBAAiB;AAEnB,SAAS,mBAAmB,OAAY,SAAuB;AACrE,QAAM,QAAQ,MAAM,QAAQ,OAAO;AACnC,MAAI,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,OAAO,KAAK,EAAE,QAAQ,CAAC,OAAY;AACzC,UAAI,GAAI,eAAc,EAAoB;AAAA,IAC3C,CAAC;AACD,UAAM,QAAQ,OAAO,IAAI,CAAC;AAAA,EAC3B;AACD;AARgB;AAWT,SAAS,SAAS,KAAU,OAAiB;AACnD,MAAI,QAAQ,UAAU,QAAQ,OAAQ,QAAO;AAC7C,MAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM,QAAO;AACpD,OAAK,KAAK,OAAO,MAAM,KAAK,QAAQ,WAAW,KAAK,MAAM,MAAM,MAAM,QAAQ,QAAQ;AACrF,QAAI,KAAK,MAAM,KAAK,OAAO,OAAO,IAAI,EAAE;AAAA,EACzC;AACA,SAAO,KAAK,UAAU,GAAG;AAC1B;AAPgB;AAST,SAAS,iBAAiB,KAAU,OAAkB;AAC5D,MAAI,SAAS,CAAC,KAAU,MAAc,UAAe;AACpD,UAAM,OAAO,SAAS,KAAK,KAAK;AAChC,QAAI,MAAM;AACT,UAAI,QAAQ,QAAQ,CAAC,WAAgB;AACpC,aAAK,SAAS,KAAK,WAAW,UAAU,OAAO,eAAeC,WAAU,MAAM;AAC7E,iBAAO,KAAK,IAAI;AAAA,QACjB;AAAA,MACD,CAAC;AAAA,IACF,OAAO;AACN,YAAM,KAAK,IAAI;AAAA,IAChB;AAAA,EACD;AACA,MAAI,UAAU,CAAC,QAAa;AAC3B,UAAM,OAAO,SAAS,KAAK,KAAK;AAChC,QAAI,QAAQ,QAAQ,CAAC,WAAgB;AACpC,UAAI,QAAQ,eAAeA,WAAU,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5D,CAAC;AAAA,EACF;AACD;AAnBgB;;;ACnBhB,SAAS,aAAa,eAAe;AAMrC,IAAM,YAAY,oBAAI,IAAoB;AAC1C,IAAM,WAAW,oBAAI,IAAqB;AAC1C,IAAM,eAAe,oBAAI,IAAqB;AAC9C,IAAM,UAAU,oBAAI,IAAqB;AAEzC,SAAS,SAAS,OAAY;AAC7B,SAAO,OAAO,YAAY,UAAU,SAAS,CAAC;AAC/C;AAFS;AAIT,SAAS,UAAU,OAAqB;AACvC,QAAM,IAAI,SAAS,KAAK;AACxB,SAAO,EAAE,YAAY,KAAK,EAAE,YAAY;AACzC;AAHS;AAKT,SAAS,QAAQ,SAAyB;AACzC,SAAO,WAAW;AACnB;AAFS;AAIF,SAAS,eAAe,OAAY,SAAiB,IAA8D;AACzH,MAAI,CAAC,UAAU,KAAK,EAAG,QAAO,EAAE,IAAI,KAAK;AACzC,QAAM,IAAI,SAAS,KAAK;AACxB,QAAM,KAAK,QAAQ,OAAO;AAE1B,QAAM,YAAY,EAAE,oBAAoB;AACxC,QAAM,YAAY,UAAU,IAAI,EAAE,KAAK;AACvC,MAAI,aAAa,WAAW;AAC3B,qBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,QAAQ,QAAQ,oBAAoB,GAAG,CAAC;AAC5F,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,qBAAqB;AAAA,EAC9D;AAEA,QAAM,WAAW,EAAE,eAAe;AAClC,QAAM,QAAQ,SAAS,IAAI,EAAE,KAAK,oBAAI,IAAI;AAC1C,QAAM,QAAQ,MAAM,IAAI,EAAE,KAAK;AAC/B,MAAI,SAAS,UAAU;AACtB,qBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,QAAQ,QAAQ,eAAe,GAAG,CAAC;AACvF,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,oBAAoB;AAAA,EAC7D;AAEA,QAAM,YAAY,EAAE,qBAAqB;AACzC,QAAM,MAAM,KAAK,IAAI;AACrB,MAAI,WAAW,aAAa,IAAI,EAAE;AAClC,MAAI,CAAC,UAAU;AACd,eAAW,oBAAI,IAAI;AACnB,iBAAa,IAAI,IAAI,QAAQ;AAAA,EAC9B;AACA,MAAI,SAAS,SAAS,IAAI,EAAE;AAC5B,MAAI,CAAC,UAAU,OAAO,UAAU,KAAK;AACpC,aAAS,EAAE,OAAO,GAAG,SAAS,MAAM,IAAM;AAC1C,aAAS,IAAI,IAAI,MAAM;AAAA,EACxB;AACA,SAAO,SAAS;AAChB,MAAI,OAAO,QAAQ,WAAW;AAC7B,qBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,QAAQ,QAAQ,qBAAqB,GAAG,CAAC;AAC7F,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,sBAAsB;AAAA,EAC/D;AAEA,YAAU,IAAI,IAAI,YAAY,CAAC;AAC/B,QAAM,IAAI,IAAI,QAAQ,CAAC;AACvB,WAAS,IAAI,IAAI,KAAK;AACtB,SAAO,EAAE,IAAI,KAAK;AACnB;AA1CgB;AA4CT,SAAS,eAAe,SAAiB,IAAkB;AACjE,QAAM,KAAK,QAAQ,OAAO;AAC1B,QAAM,IAAI,UAAU,IAAI,EAAE,KAAK;AAC/B,MAAI,IAAI,EAAG,WAAU,IAAI,IAAI,IAAI,CAAC;AAClC,QAAM,QAAQ,SAAS,IAAI,EAAE;AAC7B,MAAI,OAAO;AACV,UAAM,IAAI,MAAM,IAAI,EAAE,KAAK;AAC3B,QAAI,IAAI,EAAG,OAAM,IAAI,IAAI,IAAI,CAAC;AAAA,EAC/B;AACD;AATgB;AAWT,SAAS,cAAc,OAAY,SAAiB,IAAqB;AAC/E,MAAI,CAAC,UAAU,KAAK,EAAG,QAAO;AAC9B,QAAM,WAAW,SAAS,KAAK,EAAE,cAAc;AAC/C,QAAM,KAAK,QAAQ,OAAO;AAC1B,QAAM,QAAQ,QAAQ,IAAI,EAAE,KAAK,oBAAI,IAAI;AACzC,QAAM,MAAM,MAAM,IAAI,EAAE,KAAK;AAC7B,MAAI,OAAO,UAAU;AACpB,qBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,OAAO,QAAQ,cAAc,GAAG,CAAC;AACrF,WAAO;AAAA,EACR;AACA,QAAM,IAAI,IAAI,MAAM,CAAC;AACrB,UAAQ,IAAI,IAAI,KAAK;AACrB,SAAO;AACR;AAbgB;AAeT,SAAS,cAAc,SAAiB,IAAkB;AAChE,QAAM,KAAK,QAAQ,OAAO;AAC1B,QAAM,QAAQ,QAAQ,IAAI,EAAE;AAC5B,MAAI,CAAC,MAAO;AACZ,QAAM,IAAI,MAAM,IAAI,EAAE,KAAK;AAC3B,MAAI,IAAI,EAAG,OAAM,IAAI,IAAI,IAAI,CAAC;AAC/B;AANgB;AAST,SAAS,qBAAqB,OAAY,SAAsB;AACtE,QAAM,IAAI,SAAS,KAAK;AACxB,QAAM,YAAY,OAAO,EAAE,iBAAiB;AAC5C,MAAI,YAAY,EAAG,QAAO;AAC1B,SAAO,OAAO,SAAS,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,IAAI;AAC7D;AALgB;AAUT,SAAS,yBACf,KACA,UACA,OACA,SACA,SACA,UACS;AACT,QAAM,CAAC,IAAI,EAAE,EAAE,IAAK,YAAY,CAAC;AACjC,MAAI,QAAQ;AACZ,aAAW,UAAU,IAAI,SAAS;AACjC,QAAI,WAAW,SAAU;AACzB,QAAI,OAAO,eAAe,QAAQ,UAAU,OAAO,eAAe,QAAQ,QAAS;AACnF,UAAM,QAAS,OAAgD;AAC/D,UAAM,MAAM,QAAQ,CAAC;AACrB,UAAM,MAAM,QAAQ,CAAC;AAErB,QAAI,MAAM,MAAM,QAAQ,MAAM,QAAQ,GAAI;AAC1C,QAAI,SAAS,QAAQ,MAAM,IAAI;AAC9B,YAAM,WAAW,OAAO,gBAAgB,OAAO,IAAI,EAAE;AACrD,UAAI,aAAa,UAAU,UAAU,WAAW,CAAC,MAAM,GAAI;AAAA,IAC5D;AACA,aAAS;AAAA,EACV;AACA,SAAO;AACR;AAzBgB;;;AJzGT,SAAS,aAAa,OAAY,SAAuB;AAC/D,QAAM,UAAU,WAAW,SAAS,KAAK;AACzC,QAAM,gBAAgB,eAAe,QAAQ;AAC7C,QAAM,eAAe,CAAC,CAAC,MAAM,WAAW,QAAQ,IAAI;AAEpD,MAAI;AACH,QAAI,MAAM,UAAU,OAAO,EAAG;AAE9B,QAAI,QAAQ,QAAQ,CAAC,MAAM,cAAc,OAAO,GAAG;AAClD,YAAM,cAAc,OAAO,IAAI,CAAC;AAAA,IACjC;AACA,QAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,OAAM,QAAQ,OAAO,IAAI,CAAC;AAEvD,UAAM,MAAM,IAAI,gBAAgB,EAAE,QAAQ,MAAM,YAAY,OAAO,GAAG,mBAAmB,MAAM,CAAC;AAChG,qBAAiB,KAAK,KAAK;AAE3B,QAAI,GAAG,SAAS,CAAC,QAAe;AAC/B,yBAAmB,OAAO,OAAO;AACjC,YAAM,KAAK,MAAM,uBAAuB,GAAG;AAC3C,UAAI,QAAQ,MAAM;AACjB,cAAM,KAAK,MAAM,qBAAqB;AACtC,eAAO,MAAM,UAAU,OAAO;AAAA,MAC/B,CAAC;AAAA,IACF,CAAC;AAED,QAAI,GAAG,SAAS,CAAC,MAAc,WAAmB;AACjD,UAAI;AACH,cAAM,KAAK,MAAM,4BAA4B,OAAO,WAAW,IAAI,aAAa,QAAQ,SAAS,CAAC,EAAE;AACpG,2BAAmB,OAAO,OAAO;AAAA,MAClC,SAAS,KAAK;AACb,cAAM,KAAK,MAAM,2BAA2B,GAAG;AAAA,MAChD;AAAA,IACD,CAAC;AAED,QAAI,GAAG,cAAc,CAACC,KAAS,QAAa;AAC3C,YAAM,WAAW,YAAY,GAAG;AAChC,UAAI,CAAC,cAAc,OAAO,SAAS,QAAQ,GAAG;AAC7C,cAAM,QAAQ,KAAK,UAAU;AAAA,UAC5B,IAAI;AAAA,UACJ,IAAI,EAAE,MAAM,GAAG,MAAM,OAAO,MAAM,SAAS,QAAQ,MAAM,KAAK,uBAAuB;AAAA,QACtF,CAAC;AACD,QAAAA,IAAG,KAAK,OAAO,MAAMA,IAAG,MAAM,MAAM,aAAa,CAAC;AAClD;AAAA,MACD;AACA,MAAAA,IAAG,KAAK,SAAS,MAAM,cAAc,SAAS,QAAQ,CAAC;AAEvD,UAAI,WAAW,cAAc,KAAK,KAAK,KAAK,CAAC;AAC7C,MAAAA,IAAG,WAAW,IAAI;AAElB,YAAM,QAAQ,qBAAqB,OAAO,OAAO;AACjD,YAAM,uBAAuB,yBAAyB,KAAKA,KAAI,OAAO,SAAS,SAAS,IAAI,QAAQ;AAEpG,UAAI,wBAAwB,OAAO;AAClC,cAAM,KAAK,MAAM,+BAA+B,oBAAoB,IAAI,KAAK,GAAG;AAChF,yBAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,OAAO,QAAQ,qBAAqB,IAAI,SAAS,CAAC;AACtG,cAAM,QAAQ,KAAK,UAAU;AAAA,UAC5B,IAAI;AAAA,UACJ,IAAI,EAAE,MAAM,GAAG,MAAM,OAAO,MAAM,SAAS,QAAQ,GAAG,KAAK,IAAI,KAAK,oBAAoB,KAAK,YAAY;AAAA,QAC1G,CAAC;AACD,QAAAA,IAAG,KAAK,OAAO,MAAMA,IAAG,MAAM,MAAM,aAAa,CAAC;AAClD;AAAA,MACD;AAEA,YAAM,SAAS,CAAC,QAAQ,QAAQ,OAAO,OAAO,SAASA,KAAI,KAAK,OAAO;AACvE,UAAI,QAAQ;AACX,gBAAQ,OAAO,SAASA,KAAI,KAAK,SAAS,eAAe,YAAY;AAAA,MACtE,OAAO;AACN,QAAAA,IAAG,MAAM;AAAA,MACV;AAAA,IACD,CAAC;AAED,UAAM,UAAU,OAAO,IAAI;AAAA,EAC5B,SAAS,KAAK;AACb,UAAM,KAAK,MAAM,cAAc,KAAK,UAAU,GAAG,CAAC;AAAA,EACnD;AACD;AA3EgB;;;AKThB,YAAYC,SAAQ;AASb,IAAM,kBAAN,MAAsB;AAAA,EAG5B,YACkB,UAAU,KACV,gBAAgB,KAChC;AAFgB;AACA;AAJlB,SAAQ,QAAQ,oBAAI,IAAwB;AAAA,EAKzC;AAAA,EAlBJ,OAY6B;AAAA;AAAA;AAAA,EAQpB,MAAM,KAAa,OAAyB;AACnD,QAAI,KAAK,MAAM,IAAI,GAAG,EAAG,MAAK,MAAM,OAAO,GAAG;AAC9C,SAAK,MAAM,IAAI,KAAK,KAAK;AACzB,WAAO,KAAK,MAAM,OAAO,KAAK,SAAS;AACtC,YAAM,SAAS,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AACxC,UAAI,CAAC,OAAQ;AACb,WAAK,MAAM,OAAO,MAAM;AAAA,IACzB;AAAA,EACD;AAAA,EAEA,IAAI,KAAgC;AACnC,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,MAAM,SAAS,KAAK,IAAI,IAAI,MAAM,WAAW,KAAK,eAAe;AACpE,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACR;AACA,SAAK,MAAM,OAAO,GAAG;AACrB,SAAK,MAAM,IAAI,KAAK,KAAK;AACzB,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,KAAa,UAAkB,SAAuB;AAC5D,SAAK,MAAM,KAAK,EAAE,UAAU,SAAS,UAAU,KAAK,IAAI,EAAE,CAAC;AAAA,EAC5D;AAAA,EAEA,QAAQ,KAAmB;AAC1B,SAAK,MAAM,KAAK,EAAE,UAAU,IAAI,SAAS,GAAG,OAAO,MAAM,UAAU,KAAK,IAAI,EAAE,CAAC;AAAA,EAChF;AAAA,EAEA,OAAO,OAAoC;AAC1C,QAAI,MAAM,SAAS,CAAC,MAAM,SAAU,QAAO;AAC3C,QAAI;AACH,YAAM,OAAU,aAAS,MAAM,QAAQ;AACvC,UAAI,CAAC,KAAK,OAAO,KAAK,KAAK,YAAY,MAAM,QAAS,QAAO;AAC7D,aAAO;AAAA,IACR,QAAQ;AACP,aAAO;AAAA,IACR;AAAA,EACD;AACD;;;ACtDA,IAAM,cACL;AAEM,SAAS,qBAAqB,KAAU,UAAU,OAAO,YAAwB;AACvF,MAAI,UAAU,0BAA0B,SAAS;AACjD,MAAI,UAAU,mBAAmB,YAAY;AAC7C,MAAI,UAAU,mBAAmB,iCAAiC;AAClE,MAAI,UAAU,sBAAsB,0CAA0C;AAC9E,MAAI,UAAU,oBAAoB,GAAG;AACrC,MAAI,UAAU,8BAA8B,aAAa;AACzD,MAAI,UAAU,gCAAgC,aAAa;AAC3D,MAAI,SAAS;AACZ,QAAI,UAAU,6BAA6B,qCAAqC;AAAA,EACjF;AACA,QAAM,MAAM,YAAY;AACxB,MAAI,KAAK,KAAK;AACb,UAAM,MAAM,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,SAAS,IAAI,IAAI,YAAY;AAC5F,QAAI,UAAU,2BAA2B,GAAG;AAAA,EAC7C;AACD;AAhBgB;AAkBT,SAAS,gBAAgB,KAAU,OAAiB;AAC1D,MAAI;AACH,UAAM,WAAW,IAAI,UAAU,UAAU,GAAG,MAAM,IAAI;AACtD,WAAO,mBAAmB,UAAU,KAAK;AAAA,EAC1C,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAPgB;AAST,SAAS,gBAAgB,KAAU,OAAqB;AAC9D,MAAI,WAAW,gBAAgB,KAAK,KAAK;AACzC,SAAO;AACR;AAHgB;;;AC9BT,SAAS,gBAAgB,KAAsB;AACrD,SAAO,eAAe,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO,KAAK,OAAO,GAAG;AACzE;AAFgB;AAIT,SAAS,iBAAiB,QAAqC;AACrE,SAAO,WAAW;AACnB;AAFgB;AAIT,SAAS,qBAAqB,KAAiC;AACrE,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,IAAI,IAAI,QAAQ,GAAG;AACzB,QAAM,IAAI,IAAI,QAAQ,GAAG;AACzB,MAAI,MAAM,IAAI;AACd,MAAI,KAAK,EAAG,OAAM,KAAK,IAAI,KAAK,CAAC;AACjC,MAAI,KAAK,EAAG,OAAM,KAAK,IAAI,KAAK,CAAC;AACjC,SAAO,IAAI,MAAM,GAAG,GAAG;AACxB;AARgB;AAaT,SAAS,kBAAkB,OAAyB;AAC1D,QAAM,OAAO,MAAM,YAAY,QAAQ;AACvC,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,EAAG,QAAO,MAAM;AAE5D,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,WAAqB,CAAC;AAC5B,aAAW,QAAQ,MAAM;AACxB,QAAI,OAAO,SAAS,YAAY,CAAC,KAAM;AACvC,QAAI,KAAK,SAAS,GAAG,EAAG,UAAS,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,QAClD,OAAM,IAAI,IAAI;AAAA,EACpB;AACA,MAAI,MAAM,SAAS,KAAK,SAAS,WAAW,EAAG,QAAO,MAAM;AAE5D,SAAO,CAAC,QAA4B;AACnC,UAAMC,QAAO,qBAAqB,GAAG;AACrC,QAAI,CAACA,MAAM,QAAO;AAClB,QAAI,MAAM,IAAIA,KAAI,EAAG,QAAO;AAC5B,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACzC,UAAIA,MAAK,WAAW,SAAS,CAAC,CAAC,EAAG,QAAO;AAAA,IAC1C;AACA,WAAO;AAAA,EACR;AACD;AAtBgB;AAwBT,SAAS,QACf,OACA,MACA,QACA,KACA,aACA,KACA,KACO;AACP,MAAI,CAAC,iBAAiB,MAAM,KAAK,YAAY,GAAG,EAAG;AACnD,QAAM,KAAK,MAAM,QAAQ,GAAG;AAC5B,MAAI,OAAO,OAAO,OAAO,MAAM,oBAAoB,YAAY;AAC9D,oBAAgB,OAAO,KAAK,KAAK,IAAI;AAAA,EACtC;AACD;AAdgB;AAiBT,SAAS,gBAAgB,OAAY,KAAU,KAAU,SAAuB;AACtF,MAAI,IAAI,mBAAoB;AAC5B,MAAI,qBAAqB;AACzB,QAAM,WAAW,6BAAM;AACtB,QAAI;AACH,YAAM,QAAQ,iBAAiB,KAAK,KAAK,OAAO;AAChD,WAAK,MAAM,gBAAgB,UAAU,KAAK,GAAG,sBAAsB,KAAK,CAAC;AAAA,IAC1E,QAAQ;AAAA,IAER;AAAA,EACD,GAPiB;AAQjB,MAAI,IAAI,iBAAiB,IAAI,SAAU,UAAS;AAAA,MAC3C,KAAI,KAAK,UAAU,QAAQ;AACjC;AAbgB;;;ACjEhB,YAAYC,SAAQ;AACpB,YAAYC,eAAc;;;ACD1B,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AAEf,SAAS,sBAAsB,eAAuB,cAAgC;AAC5F,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACxD,UAAM,IAAI,MAAM,cAAc;AAAA,EAC/B;AACA,MAAI,cAAc,SAAS,IAAI,GAAG;AACjC,UAAM,IAAI,MAAM,cAAc;AAAA,EAC/B;AAEA,QAAM,UAAU,cAAc,QAAQ,OAAO,GAAG,EAAE,KAAK;AACvD,MAAI,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAW,IAAI,GAAG;AAC3D,UAAM,IAAI,MAAM,gCAAgC;AAAA,EACjD;AAEA,QAAM,aAAkB,gBAAU,QAAQ,QAAQ,QAAQ,EAAE,CAAC;AAE7D,aAAW,QAAQ,cAAc;AAChC,QAAI,CAAC,KAAM;AACX,UAAM,UAAe,cAAQ,IAAI;AACjC,UAAM,YAAiB,cAAQ,SAAS,UAAU;AAClD,UAAM,MAAW,eAAS,SAAS,SAAS;AAC5C,QAAI,QAAQ,MAAO,CAAC,IAAI,WAAW,IAAI,KAAK,CAAM,iBAAW,GAAG,GAAI;AACnE,aAAO;AAAA,IACR;AAAA,EACD;AAEA,QAAM,IAAI,MAAM,kBAAkB;AACnC;AA1BgB;AA6BT,SAAS,2BACf,eACA,cAC8C;AAC9C,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,YAAY,cAAc,SAAS,IAAI,GAAG;AACxF,WAAO;AAAA,EACR;AAEA,QAAM,UAAU,cAAc,QAAQ,OAAO,GAAG,EAAE,KAAK;AACvD,MAAI,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAW,IAAI,GAAG;AAC3D,WAAO;AAAA,EACR;AAEA,QAAM,aAAkB,gBAAU,QAAQ,QAAQ,QAAQ,EAAE,CAAC;AAE7D,aAAW,QAAQ,cAAc;AAChC,QAAI,CAAC,KAAM;AACX,QAAI;AACH,YAAM,UAAe,cAAQ,IAAI;AACjC,YAAM,YAAiB,cAAQ,SAAS,UAAU;AAClD,YAAM,MAAW,eAAS,SAAS,SAAS;AAC5C,UAAI,IAAI,WAAW,IAAI,KAAU,iBAAW,GAAG,EAAG;AAClD,YAAM,OAAU,aAAS,SAAS;AAClC,UAAI,KAAK,OAAO,GAAG;AAClB,eAAO,EAAE,UAAU,WAAW,KAAK;AAAA,MACpC;AAAA,IACD,QAAQ;AAAA,IAER;AAAA,EACD;AAEA,SAAO;AACR;AAhCgB;AAmCT,SAAS,oBAAoB,YAA2B;AAC9D,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,OAAO,wBAAC,QAAiB;AAC9B,QAAI,OAAO,QAAQ,YAAY,CAAC,IAAI,KAAK,EAAG;AAC5C,QAAI;AACH,YAAM,MAAW,cAAQ,OAAO,IAAI,QAAQ,OAAO,GAAG,CAAC;AACvD,UAAO,eAAW,GAAG,EAAG,OAAM,IAAI,GAAG;AAAA,IACtC,QAAQ;AAAA,IAER;AAAA,EACD,GARa;AASb,aAAW,OAAO,YAAY,YAAY,CAAC,EAAG,MAAK,GAAG;AACtD,OAAK,SAAS;AACd,OAAK,QAAQ;AACb,MAAI,YAAY,SAAS,OAAQ,MAAK,WAAW,QAAQ,MAAM;AAC/D,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAQ,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AACnC,SAAO;AACR;AAlBgB;;;AClEhB,YAAYC,SAAQ;AACpB,YAAY,cAAc;AAGnB,SAAS,kBAAkB,OAAsB;AACtD,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAM,wBAAC,MAA0B;AACrC,QAAI,CAAC,EAAG;AACR,UAAM,MAAe,iBAAQ,CAAC;AAC9B,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,WAAK,IAAI,GAAG;AACZ,YAAM,KAAK,GAAG;AAAA,IAChB;AAAA,EACF,GAPY;AASZ,MAAI,MAAM,QAAQ,MAAM,eAAe,GAAG;AACxC,eAAW,KAAK,MAAM,gBAAiB,KAAI,CAAC;AAAA,EAC9C;AACA,MAAI,MAAM,WAAY,KAAI,MAAM,UAAU;AAC1C,MAAI,MAAM,eAAgB,KAAI,MAAM,cAAc;AAElD,SAAO;AACT;AAnBgB;AAsBhB,SAAS,oBAAoB,OAAqB;AAChD,MAAI,MAAM,eAAgB,QAAO;AACjC,SAAO,MAAM,YAAY,KAAK,SAAS;AACzC;AAHS;AAKF,SAAS,sBAAsB,SAAc,OAAsB;AACxE,QAAM,QAAQ,kBAAkB,KAAK;AACrC,QAAM,UAAoB,CAAC;AAC3B,QAAM,OAAO,oBAAI,IAAY;AAE7B,QAAM,UAAU,wBAAC,QAAgB;AAC/B,QAAI,CAAC,OAAO,KAAK,IAAI,GAAG,EAAG;AAC3B,QAAI,oBAAoB,KAAK,GAAG;AAC9B,WAAK,IAAI,GAAG;AACZ,cAAQ,KAAK,GAAG;AAChB;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,YAAO,aAAkB,iBAAQ,MAAM,GAAG,CAAC,EAAE,YAAY,GAAG;AAC1D,eAAK,IAAI,GAAG;AACZ,kBAAQ,KAAK,GAAG;AAChB;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,GAlBgB;AAoBhB,aAAW,OAAO,QAAQ,YAAY,CAAC,EAAG,SAAQ,GAAG;AACrD,MAAI,QAAQ,SAAS,OAAQ,SAAQ,QAAQ,QAAQ,MAAM;AAC3D,SAAO;AACT;AA5BgB;AA8BT,SAAS,iBAAiB,MAAgB,OAAsB;AACrE,QAAM,QAAQ,kBAAkB,KAAK;AACrC,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,OAAO;AACxB,eAAW,KAAK,MAAM;AACpB,YAAM,MAAe,iBAAQ,MAAM,CAAC;AACpC,UAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,aAAK,IAAI,GAAG;AACZ,cAAM,KAAK,GAAG;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAdgB;;;AFvDhB,IAAM,kBAAkB,IAAI,OAAO;AAE5B,SAAS,aAAa,QAAwB;AACnD,MAAI;AACF,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,UAAU,OAAO,WAAW,MAAM,IAAI,SAAS,UAAU,MAAM;AACrE,WAAO,IAAI,IAAI,SAAS,kBAAkB,EAAE;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AARgB;AAUhB,IAAM,wBAAwB,CAAC,YAAY,cAAc,kBAAkB,gBAAgB;AAE3F,SAAS,kBAAkB,SAAiB,WAA4B;AACtE,QAAM,IAAI,aAAa,OAAO;AAC9B,QAAM,OAAO,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AACnC,MAAI,SAAS,UAAW,QAAO;AAE/B,MAAI,sBAAsB,KAAK,CAAC,WAAW,EAAE,WAAW,MAAM,CAAC,EAAG,QAAO;AACzE,SAAO,+EAA+E,KAAK,CAAC;AAC9F;AAPS;AAST,SAAS,iBAAiB,KAAU,KAAU,MAAc,UAAkB,SAAiB,OAAkB;AAC/G,QAAM,OAAO,IAAI,KAAK,MAAM,IAAI,OAAO;AACvC,MAAI,IAAI,QAAQ,eAAe,MAAM,MAAM;AACzC,QAAI,UAAU,GAAG;AACjB,QAAI,IAAI;AACR;AAAA,EACF;AACA,MAAI;AACF,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,kBAAkB,KAAK;AAAA,MACvB,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,iBAAiB,IAAI,KAAK,OAAO,EAAE,YAAY;AAAA,IACjD,CAAC;AACD,QAAI,IAAI,IAAI;AAAA,EACd,SAAS,KAAK;AACZ,UAAM,KAAK,QAAQ,+BAA+B,gBAAgB,GAAG,CAAC;AACtE,QAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAI,uBAAuB;AAAA,IACjC;AAAA,EACF;AACF;AAvBS;AAyBF,SAAS,gBAAgB,KAAU,KAAU,WAAmB,UAAkB,MAAgB,OAAkB;AACzH,MAAI,KAAK,QAAQ,iBAAiB;AAChC,IAAG,aAAS,WAAW,CAAC,KAAK,SAAS;AACpC,UAAI,KAAK;AACP,cAAM,KAAK,QAAQ,2BAA2B,gBAAgB,GAAG,CAAC;AAClE,YAAI,CAAC,IAAI,aAAa;AACpB,cAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,cAAI,IAAI,uBAAuB;AAAA,QACjC;AACA;AAAA,MACF;AACA,uBAAiB,KAAK,KAAK,MAAM,UAAU,KAAK,SAAS,KAAK;AAAA,IAChE,CAAC;AACD;AAAA,EACF;AAEA,QAAM,aAAgB,qBAAiB,SAAS;AAChD,QAAM,OAAO,IAAI,KAAK,IAAI,IAAI,KAAK,OAAO;AAC1C,MAAI,IAAI,QAAQ,eAAe,MAAM,MAAM;AACzC,eAAW,QAAQ;AACnB,QAAI,UAAU,GAAG;AACjB,QAAI,IAAI;AACR;AAAA,EACF;AAEA,aAAW,GAAG,SAAS,CAAC,QAAQ;AAC9B,UAAM,KAAK,UAAU,iBAAiB,gBAAgB,GAAG,CAAC;AAC1D,QAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAI,uBAAuB;AAAA,IACjC,WAAW,CAAC,IAAI,cAAe,KAAI,QAAQ;AAAA,EAC7C,CAAC;AAED,MAAI,GAAG,WAAW,MAAM;AACtB,QAAI,CAAC,WAAW,UAAW,YAAW,QAAQ;AAAA,EAChD,CAAC;AAED,MAAI;AACF,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,iBAAiB,KAAK,MAAM,YAAY;AAAA,IAC1C,CAAC;AACD,eAAW,KAAK,GAAG;AAAA,EACrB,SAAS,KAAK;AACZ,UAAM,KAAK,QAAQ,+BAA+B,gBAAgB,GAAG,CAAC;AACtE,QAAI,CAAC,WAAW,UAAW,YAAW,QAAQ;AAC9C,QAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAI,uBAAuB;AAAA,IACjC;AAAA,EACF;AACF;AArDgB;AA+DT,SAAS,oBAAoB,KAAoE;AACtG,QAAM,EAAE,SAAS,SAAS,WAAW,OAAO,gBAAgB,IAAI;AAChE,QAAM,aAAa,CAAC,EAAE,QAAQ,SAAS,WAAW,QAAQ,SAAS,UAAU,QAAQ,SAAS,MAAM;AACpG,QAAM,cAAwB,aAAa,QAAQ,SAAS,QAAQ,CAAC,IAAI,CAAC;AAE1E,QAAM,eAAe,wBAAC,SAA0B;AAC9C,QAAI,CAAC,cAAc,CAAC,KAAM,QAAO;AACjC,aAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAI,KAAK,WAAW,YAAY,CAAC,CAAC,EAAG,QAAO;AAAA,IAC9C;AACA,WAAO;AAAA,EACT,GANqB;AAQrB,QAAM,eAAe,wBACnB,KACA,KACA,WACA,MACA,aACA,MAAc,MACL;AACT,UAAM,WAAW,aAAa,IAAI;AAClC,UAAM,eAAe,SAAS,SAAS,GAAG,IAAI,WAAW,YAAY;AACrE,UAAM,WAAW,GAAG,OAAO,IAAI,UAAU,KAAK,GAAG,CAAC,IAAI,YAAY;AAClE,UAAM,QAAQ,UAAU,KAAK,GAAG,MAAM,YAAY,KAAK,GAAG,IACtD,iBAAiB,aAAa,KAAK,IACnC,iBAAiB,WAAW,KAAK;AAErC,UAAM,gBAAgB,wBAAC,YAAiE;AACtF,YAAM,MAAM,gBAAgB,IAAI,QAAQ;AACxC,UAAI,KAAK,MAAO,QAAO;AACvB,UAAI,OAAO,CAAC,IAAI,OAAO;AACrB,cAAM,WAAW,gBAAgB,OAAO,GAAG;AAC3C,YAAI,SAAU,QAAO,EAAE,UAAU,IAAI,UAAU,MAAM,SAAS;AAAA,MAChE;AAEA,YAAM,MAAM,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AACzD,YAAM,UAAU,2BAA2B,KAAK,KAAK;AACrD,UAAI,SAAS;AACX,wBAAgB,OAAO,UAAU,QAAQ,UAAU,QAAQ,KAAK,OAAO;AACvE,eAAO;AAAA,MACT;AAEA,sBAAgB,QAAQ,QAAQ;AAChC,aAAO;AAAA,IACT,GAjBsB;AAmBtB,UAAM,QAAQ,cAAc,YAAY;AACxC,QAAI,CAAC,OAAO;AACV,UAAI,MAAM,KAAK,CAAC,cAAc,kBAAkB,cAAc,SAAS,GAAG;AACxE,YAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,YAAI,IAAI,iBAAiB;AACzB;AAAA,MACF;AACA,mBAAa,KAAK,KAAK,CAAC,QAAQ,QAAS,MAAO,GAAG,MAAM,WAAW,aAAa,MAAM,CAAC;AACxF;AAAA,IACF;AAEA,UAAM,WAAW,QAAQ,YAAqB,kBAAQ,MAAM,QAAQ,CAAC,KAAK;AAC1E,oBAAgB,KAAK,KAAK,MAAM,UAAU,UAAU,MAAM,MAAM,KAAK;AAAA,EACvE,GA/CqB;AAiDrB,SAAO,CAAC,KAAU,KAAU,QAAgB;AAC1C,QAAI,UAAU,gCAAgC,cAAc;AAC5D,QAAI,UAAU,8BAA8B,cAAc;AAE1D,UAAM,UAAU,sBAAsB,SAAS,KAAK;AACpD,QAAI,CAAC,QAAQ,QAAQ;AACnB,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAI,4BAA4B;AACpC;AAAA,IACF;AAEA,QAAI,aAAa,GAAG,GAAG;AACrB,mBAAa,KAAK,KAAK,CAAC,QAAQ,QAAS,MAAO,GAAG,MAAM,WAAW,OAAO;AAAA,IAC7E,OAAO;AACL,mBAAa,KAAK,KAAK,SAAS,KAAK,OAAO;AAAA,IAC9C;AAAA,EACF;AACF;AA/EgB;;;AGpHT,SAAS,2BAA2B,OAAY,SAAiB,QAAa,SAAoB;AACxG,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,kBAAkB,YAAY,MAAM;AACzC,UAAM,YAAY,MAAM,gBAAgB,OAAO,GAAG,QAAQ;AAC1D,QAAI,YAAY,UAAU,KAAK;AAC9B,YAAM,KAAK,QAAQ,yBAAyB,SAAS,IAAI,OAAO,GAAG;AAAA,IACpE;AACA,QAAI,YAAY,UAAU,MAAM;AAC/B,YAAM,KAAK,QAAQ,2CAA2C;AAC9D,UAAI,MAAM,gBAAgB,OAAO,GAAG;AACnC,cAAM,gBAAgB,OAAO,EAAE,QAAQ,CAAC,SAAc;AACrD,cAAI,KAAK,aAAa,KAAK,IAAI,IAAI,KAAK,YAAY,KAAQ;AAC3D,iBAAK,QAAQ;AAAA,UACd;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD,GAAG,GAAM;AAET,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,OAAM,QAAQ,OAAO,IAAI,CAAC;AACvD,QAAM,QAAQ,OAAO,EAAE,cAAc;AAErC,SAAO,GAAG,cAAc,CAAC,eAAoB;AAC5C,QAAI,CAAC,MAAM,gBAAgB,OAAO,GAAG;AACpC,YAAM,gBAAgB,OAAO,IAAI,oBAAI,IAAI;AAAA,IAC1C;AACA,UAAM,YAAY,MAAM,gBAAgB,OAAO,EAAE;AACjD,QAAI,aAAa,SAAS;AACzB,UAAI;AACH,cAAM,KAAK,QAAQ,iCAAiC,SAAS,IAAI,OAAO,GAAG;AAC3E,mBAAW,QAAQ;AAAA,MACpB,SAAS,KAAK;AACb,cAAM,KAAK,QAAQ,2BAA2B,GAAG;AAAA,MAClD;AACA;AAAA,IACD;AACA,UAAM,gBAAgB,OAAO,EAAE,IAAI,UAAU;AAC7C,eAAW,GAAG,SAAS,MAAM;AAC5B,YAAM,gBAAgB,OAAO,EAAE,OAAO,UAAU;AAAA,IACjD,CAAC;AACD,eAAW,WAAW,GAAM;AAAA,EAC7B,CAAC;AACF;AA1CgB;;;ACFhB,SAAS,gBAAgB;AACzB,OAAOC,cAAa;AAGpB,IAAM,UAAUC,SAAQ;AAExB,SAAS,QAAQ,IAAkB;AAClC,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAAA,EAE9B;AACD;AALS;AAQF,SAAS,kBAAkB,MAAwB;AACzD,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,MAAO,QAAO,CAAC;AACjE,MAAI;AACH,QAAIA,SAAQ,aAAa,SAAS;AACjC,YAAM,MAAM,SAAS,kCAAkC,IAAI,MAAM;AAAA,QAChE,UAAU;AAAA,QACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ;AAAA,MACjC,CAAC;AACD,YAAM,OAAO,oBAAI,IAAY;AAC7B,iBAAW,QAAQ,IAAI,MAAM,OAAO,GAAG;AACtC,cAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,KAAK;AACrC,YAAI,MAAM,SAAS,KAAK,MAAM,CAAC,MAAM,YAAa;AAClD,cAAM,YAAY,MAAM,CAAC,KAAK;AAC9B,cAAM,YAAY,UAAU,MAAM,SAAS;AAC3C,cAAM,MAAM,SAAS,MAAM,MAAM,SAAS,CAAC,GAAI,EAAE;AACjD,YAAI,aAAa,SAAS,UAAU,CAAC,GAAI,EAAE,MAAM,QAAQ,MAAM,GAAG;AACjE,eAAK,IAAI,GAAG;AAAA,QACb;AAAA,MACD;AACA,aAAO,CAAC,GAAG,IAAI;AAAA,IAChB;AACA,QAAI;AACH,YAAM,MAAM,SAAS,kBAAkB,IAAI,oBAAoB;AAAA,QAC9D,UAAU;AAAA,QACV,OAAO,CAAC,QAAQ,QAAQ,QAAQ;AAAA,MACjC,CAAC;AACD,aAAO,IACL,MAAM,OAAO,EACb,IAAI,CAAC,MAAM,SAAS,EAAE,KAAK,GAAG,EAAE,CAAC,EACjC,OAAO,CAAC,MAAM,IAAI,CAAC;AAAA,IACtB,QAAQ;AACP,aAAO,CAAC;AAAA,IACT;AAAA,EACD,QAAQ;AACP,WAAO,CAAC;AAAA,EACT;AACD;AApCgB;AAsChB,SAAS,QAAQ,KAAsB;AACtC,MAAI,CAAC,OAAO,QAAQ,WAAW,OAAO,EAAG,QAAO;AAChD,MAAI;AACH,QAAIA,SAAQ,aAAa,SAAS;AACjC,eAAS,iBAAiB,GAAG,OAAO,EAAE,OAAO,SAAS,CAAC;AAAA,IACxD,OAAO;AACN,eAAS,WAAW,GAAG,IAAI,EAAE,OAAO,SAAS,CAAC;AAAA,IAC/C;AACA,WAAO;AAAA,EACR,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAZS;AAeF,SAAS,YACf,MACA,MACU;AACV,QAAM,UAAU,MAAM,cAAc;AACpC,QAAM,YAAY,kBAAkB,IAAI,EAAE,OAAO,CAAC,MAAM,MAAM,WAAW,MAAM,OAAO;AACtF,MAAI,CAAC,UAAU,OAAQ,QAAO;AAE9B,QAAM,QAAQ,MAAM,QAAQ,IAAI,KAAK,KAAK,OAAO;AACjD,UAAQ,KAAK,oBAAoB,KAAK,gBAAM,IAAI,kEAAgB,UAAU,KAAK,IAAI,CAAC,EAAE;AACtF,aAAW,OAAO,WAAW;AAC5B,YAAQ,GAAG;AAAA,EACZ;AACA,UAAQ,GAAG;AAEX,QAAM,YAAY,kBAAkB,IAAI,EAAE,OAAO,CAAC,MAAM,MAAM,WAAW,MAAM,OAAO;AACtF,SAAO,UAAU,WAAW;AAC7B;AAjBgB;AAoBT,SAAS,oBAAoB,OAAsB;AACzD,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,QAAQ,MAAM,YAAY;AAChC,MAAI,OAAO;AACV,eAAW,MAAM,OAAO,KAAK,KAAK,GAAG;AACpC,UAAI,OAAO,UAAW;AACtB,UAAI,OAAO,UAAU,CAAC,gBAAgB,EAAE,EAAG;AAC3C,YAAM,MAAM,WAAW,IAAI,KAAK;AAChC,UAAI,KAAK,MAAO;AAChB,UAAI,KAAK,KAAM,OAAM,IAAI,OAAO,IAAI,IAAI,CAAC;AAAA,IAC1C;AAAA,EAED;AACA,QAAM,aAAa,MAAM,YAAY;AACrC,MAAI,YAAY;AACf,eAAW,MAAM,OAAO,KAAK,UAAU,GAAG;AACzC,UAAI,OAAO,UAAW;AACtB,UAAI,CAAC,gBAAgB,EAAE,EAAG;AAC1B,YAAM,MAAM,gBAAgB,IAAI,KAAK;AACrC,UAAI,KAAK,UAAW,OAAM,IAAI,OAAO,IAAI,SAAS,CAAC;AAAA,IACpD;AAAA,EACD;AACA,SAAO,CAAC,GAAG,KAAK;AACjB;AAvBgB;AA0BT,SAAS,uBAAuB,OAAkB;AACxD,aAAW,QAAQ,oBAAoB,KAAK,GAAG;AAC9C,gBAAY,MAAM,EAAE,YAAYA,SAAQ,IAAI,CAAC;AAAA,EAC9C;AACD;AAJgB;;;Ab7FhB,SAAS,kBAAkB,OAAY,SAAuB;AAC7D,MAAI,MAAM,WAAW,SAAS;AAC7B,iBAAa,MAAM,WAAW,OAAO;AACrC,UAAM,WAAW,UAAU;AAAA,EAC5B;AACA,QAAM,WAAW,UAAU,WAAW,MAAM;AAC3C,oBAAgB,OAAO,OAAO;AAC9B,QAAI,MAAM,WAAW,SAAS;AAC7B,mBAAa,MAAM,WAAW,OAAO;AACrC,YAAM,WAAW,UAAU;AAAA,IAC5B;AAAA,EACD,GAAG,MAAM,WAAW,IAAI,KAAK,GAAI;AAClC;AAZS;AAcT,SAAS,oBAAoB,OAAY,SAAiBC,KAAoB;AAC7E,SAAO,MAAM,YAAY,OAAO;AAChC,MAAIA,IAAI,QAAO,MAAM,UAAU,OAAO;AACvC;AAHS;AAKF,SAAS,cAAc,WAAmB,IAAI,KAAU,OAAiB;AAC/E,MAAI;AACH,QAAI,SAAS,WAAW,OAAO,GAAG;AAEjC,aAAO;AAAA,QACN,gBAAgB,wBAAC,aAAkB;AAClC,iBAAa,mBAAa,KAAK,aAAa,MAAM,WAAW,WAAW,QAAQ;AAAA,QACjF,GAFgB;AAAA,QAGhB,OAAa;AAAA,QACb,SAAe;AAAA,MAChB;AAAA,IACD,OAAO;AACN,aAAO;AAAA,QACN,gBAAqB;AAAA,QACrB,OAAY;AAAA,QACZ,SAAc;AAAA,MACf;AAAA,IACD;AAAA,EACD,SAAS,KAAK;AACb,UAAM,KAAK,QAAQ,sBAAsB,eAAe,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO;AAAA,EAAK,IAAI,KAAK,KAAK,KAAK,UAAU,GAAG,CAAC;AACjI,WAAO;AAAA,MACN,gBAAqB;AAAA,MACrB,OAAY;AAAA,MACZ,SAAc;AAAA,IACf;AAAA,EACD;AACD;AA1BgB;AA4BT,SAAS,gBAAgB,OAAY,SAAsB;AACjE,QAAM,UAAU,WAAW,SAAS,KAAK;AACzC,MAAI,CAAC,WAAW,QAAQ,MAAO;AAE/B,MAAI;AACH,QAAI,CAAC,MAAM,YAAY,OAAO,GAAG;AAChC,UAAI,QAAQ,cAAc,QAAW;AACpC,gBAAQ,YAAY,EAAE,GAAI,MAAM,WAAW,aAAa,CAAC,GAAI,GAAI,QAAQ,aAAa,CAAC,EAAG;AAAA,MAC3F,OAAO;AACN,gBAAQ,YAAY,EAAE,GAAI,MAAM,WAAW,aAAa,CAAC,EAAG;AAAA,MAC7D;AAEA,YAAM,UAAU,cAAc,QAAQ,UAAU,SAAS,KAAK;AAC9D,YAAM,YAAY,MAAM,WAAW,SAAS;AAC5C,YAAM,kBAAkB,IAAI,gBAAgB,KAAM,GAAM;AACxD,YAAM,cAAc,kBAAkB,KAAK;AAC3C,YAAM,WAAW,QAAQ,YAAY,IAAI,WAAW,OAAO;AAE3D,YAAM,cAAc,eAAe,aAAa;AAChD,YAAM,UAAU,eAAe,SAAS;AACxC,YAAM,UAAU,eAAe,SAAS;AACxC,YAAM,YAAY,eAAe,WAAW;AAC5C,YAAM,eAAe,oBAAoB,EAAE,SAAS,SAAS,WAAW,OAAO,gBAAgB,CAAC;AAEhG,YAAM,SAAU,QAAgB,eAAe,CAAC,KAAU,QAAa;AACtE,YAAI;AACH,cAAI,CAAC,gBAAgB,KAAK,KAAK,GAAG;AACjC,oBAAQ,OAAO,QAAQ,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AACjE,gBAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,gBAAI,IAAI,KAAK;AACb;AAAA,UACD;AACA,+BAAqB,KAAK,SAAS,MAAM,UAAU;AAEnD,cAAI,IAAI,KAAK,WAAW,MAAM,KAAK,SAAS;AAC3C,oBAAQ,OAAO,OAAO,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AAChE,oBAAQ,KAAK,KAAK,OAAO;AAAA,UAC1B,WAAW,IAAI,KAAK,WAAW,MAAM,KAAK,SAAS;AAClD,oBAAQ,OAAO,OAAO,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AAChE,oBAAQ,KAAK,KAAK,OAAO;AAAA,UAC1B,WAAW,IAAI,KAAK,WAAW,QAAQ,KAAK,WAAW;AACtD,oBAAQ,OAAO,SAAS,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AAClE,sBAAU,KAAK,KAAK,OAAO;AAAA,UAC5B,WAAW,cAAc;AACxB,oBAAQ,OAAO,aAAa,IAAI,QAAQ,IAAI,KAAK,aAAa,KAAK,GAAG;AACtE,yBAAa,KAAK,KAAK,IAAI,GAAI;AAAA,UAChC,OAAO;AACN,kBAAM,KAAK,QAAQ,IAAI,QAAQ,IAAI,GAAG;AACtC,gBAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,gBAAI,IAAI,KAAK;AAAA,UACd;AAAA,QACD,SAAS,KAAK;AACb,gBAAM,KAAK,QAAQ,uBAAuB,gBAAgB,GAAG,CAAC;AAC9D,cAAI,CAAC,IAAI,aAAa;AACrB,gBAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,gBAAI,IAAI,uBAAuB;AAAA,UAChC,WAAW,CAAC,IAAI,eAAe;AAC9B,gBAAI,IAAI;AAAA,UACT;AAAA,QACD;AAAA,MACD,CAAC;AAED,YAAM,YAAY,OAAO,IAAI;AAE7B,UAAI,QAAQ,IAAI;AACf,qBAAa,OAAO,OAAO;AAAA,MAC5B;AAEA,aAAO,GAAG,SAAS,CAAC,QAAa;AAChC,YAAI,IAAI,SAAS,cAAc;AAC9B,gBAAM,WAAW,SAAS,KAAK,QAAQ,IAAI;AAC3C,gBAAM,KAAK,QAAQ,gBAAgB,QAAQ,IAAI,2BAA2B;AAC1E,8BAAoB,OAAO,SAAS,QAAQ,EAAE;AAC9C,oBAAU,OAAO,OAAO;AAAA,QACzB,OAAO;AACN,gBAAM,KAAK,QAAQ,iBAAiB,eAAe,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO;AAAA,EAAK,IAAI,KAAK,KAAK,GAAG;AAAA,QAC7G;AAAA,MACD,CAAC;AAED,kBAAY,QAAQ,MAAM,EAAE,YAAY,QAAQ,KAAK,OAAO,QAAQ,CAAC;AAErE,UAAI,MAAM,WAAW,OAAO,UAAW,CAAC,QAAQ,MAAM,CAAC,MAAM,WAAW,IAAK;AAC5E,eAAO,OAAO,QAAQ,MAAM,MAAM;AACjC,kBAAQ,IAAI,IAAI,OAAO,cAAc,WAAW,CAAC,GAAG;AACpD,cAAI,QAAQ,IAAI;AACf,oBAAQ,IAAI,0BAA0B,QAAQ,UAAU,OAAO,aAAa,QAAQ,IAAI,SAAS;AAAA,UAClG;AACA,kBAAQ,IAAI,0BAA0B,QAAQ,QAAQ,aAAa,QAAQ,IAAI,SAAS;AACxF,kBAAQ,IAAI,kDAAkD;AAAA,QAC/D,CAAC;AAAA,MACF,OAAO;AACN,cAAM,QAAgB,UAAU,QAAQ,IAAI,KAAK;AACjD,eAAO,OAAO,QAAQ,MAAM,OAAO,MAAM;AACxC,kBAAQ,IAAI,IAAI,OAAO,cAAc,WAAW,CAAC,GAAG;AACpD,cAAI,QAAQ,IAAI;AACf,oBAAQ,IAAI,0BAA0B,QAAQ,UAAU,OAAO,GAAG,KAAK,IAAI,QAAQ,IAAI,SAAS;AAAA,UACjG;AACA,kBAAQ,IAAI,0BAA0B,QAAQ,QAAQ,GAAG,KAAK,IAAI,QAAQ,IAAI,SAAS;AACvF,kBAAQ,IAAI,kDAAkD;AAAA,QAC/D,CAAC;AAAA,MACF;AAEA,UAAI,QAAQ,QAAQ;AACnB,mCAA2B,OAAO,SAAS,QAAQ,OAAO;AAAA,MAC3D;AAAA,IACD;AAAA,EACD,SAAS,KAAK;AACb,UAAM,KAAK,QAAQ,sBAAsB,eAAe,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO;AAAA,EAAK,IAAI,KAAK,KAAK,KAAK,UAAU,GAAG,CAAC;AAAA,EAClI;AAEA,SAAO,MAAM,YAAY,OAAO;AACjC;AA/GgB;AAiHhB,SAAS,yBAAyB,OAAY,MAAc,gBAAuC;AAClG,aAAW,WAAW,OAAO,KAAK,MAAM,eAAe,CAAC,CAAC,GAAG;AAC3D,QAAI,YAAY,eAAgB;AAChC,UAAM,MAAM,WAAW,SAAS,KAAK;AACrC,QAAI,KAAK,SAAS,KAAM,QAAO;AAAA,EAChC;AACA,SAAO;AACR;AAPS;AASF,SAAS,UAAU,OAAY,gBAAwB,QAAc;AAC3E,QAAM,gBAA0B,MAAM,WAAW,YAAY,CAAC;AAC9D,QAAM,UAAU,WAAW,eAAe,KAAK;AAC/C,QAAM,OAAO,SAAS;AACtB,MAAI,CAAC,QAAQ,CAAC,cAAc,SAAS,IAAI,GAAG;AAC3C,sBAAkB,OAAO,aAAa;AACtC;AAAA,EACD;AAEA,QAAM,mBAAmB,yBAAyB,OAAO,MAAM,aAAa;AAC5E,MAAI,kBAAkB;AACrB,YAAQ;AAAA,MACP,iCAAuB,IAAI,gDAAa,gBAAgB,wBAAS,aAAa;AAAA,IAC/E;AACA;AAAA,EACD;AAEA,QAAM,WAAW,YAAY,MAAM,EAAE,YAAY,QAAQ,KAAK,OAAO,cAAc,CAAC;AACpF,QAAM,WAAW,WAAW,cAAc,OAAO,CAAC,MAAc,MAAM,IAAI;AAC1E,MAAI,UAAU;AACb,YAAQ,KAAK,iCAAuB,IAAI,kEAAgB,aAAa,GAAG;AACxE,sBAAkB,OAAO,aAAa;AACtC;AAAA,EACD;AAEA,UAAQ,MAAM,iCAAuB,IAAI,wFAAsC,IAAI,QAAG;AACtF,UAAQ,KAAK,CAAC;AACf;AA3BgB;;;AcrLhB,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EAAqB;AAAA,EAAc;AAAA,EACnC;AAAA,EAAsB;AAAA,EAAuB;AAAA,EAAM;AAAA,EAAY;AACjE,CAAC;AAEM,SAAS,iBAAiB,OAAY,cAA4B;AACvE,QAAM,WAAW,gBAAgB,cAAc,KAAK;AACpD,MAAI,CAAC,SAAS,IAAK;AACnB,MAAI,MAAM,eAAe,YAAY,EAAG;AAExC,MAAI;AACF,UAAM,aAAa,cAAc,SAAS,eAAe,UAAU,KAAK;AACxE,UAAM,aAAa,cAAc,SAAS,KAAM,UAAU,KAAK;AAE/D,UAAM,gBAAgB,IAAI,IAAI,SAAS,GAAI;AAC3C,UAAM,gBAAgB,cAAc,aAAa;AACjD,UAAM,oBAAoB,gBAAgB,MAAM;AAGhD,UAAM,cAAc,IAAI,WAAW,MAAM;AAAA,MACvC,WAAW,SAAS,aAAa;AAAA,MACjC,SAAS,SAAS,WAAW;AAAA,MAC7B,gBAAgB,SAAS,kBAAkB;AAAA,MAC3C,YAAY,SAAS,cAAc;AAAA,MACnC,gBAAgB,SAAS,kBAAkB;AAAA,MAC3C,oBAAoB,SAAS,sBAAsB;AAAA,MACnD,gBAAgB,SAAS,kBAAkB;AAAA,IAC7C,CAAC;AAED,UAAM,cAAe,WAAmB,eAAe,CAAC,KAAU,QAAa;AAC7E,UAAI,SAAS,UAAU;AACrB,YAAI,UAAU,KAAK;AAAA,UACjB,UAAU,SAAS,MAAM,IAAI;AAAA,UAC7B,6BAA6B;AAAA,QAC/B,CAAC;AACD,YAAI,IAAI;AACR;AAAA,MACF;AAEA,YAAM,YAAY,IAAI,IAAI,IAAI,OAAO,KAAK,aAAa;AAIvD,YAAM,iBAAsC,CAAC;AAC7C,iBAAW,OAAO,OAAO,KAAK,IAAI,OAAO,GAAG;AAC1C,YAAI,CAAC,mBAAmB,IAAI,IAAI,YAAY,CAAC,GAAG;AAC9C,yBAAe,GAAG,IAAI,IAAI,QAAQ,GAAG;AAAA,QACvC;AAAA,MACF;AAEA,YAAM,YAAiB;AAAA,QACrB,OAAO;AAAA,QACP,QAAQ,IAAI;AAAA,QACZ,UAAU,UAAU;AAAA,QACpB,MAAM,UAAU,QAAQ;AAAA,QACxB,MAAM,UAAU,WAAW,UAAU;AAAA,QACrC,SAAS;AAAA,MACX;AACA,UAAI,eAAe;AACjB,kBAAU,aAAa,UAAU;AAAA,MACnC;AAGA,YAAM,eAAe,SAAS,gBAAgB;AAE9C,YAAM,iBAAiB,WAAW,QAAQ,WAAW,CAAC,eAAoB;AACxE,eAAO,KAAK,WAAW,OAAO,EAAE,QAAQ,CAAC,QAAQ;AAC/C,cAAI,CAAC,mBAAmB,IAAI,IAAI,YAAY,CAAC,GAAG;AAC9C,gBAAI,UAAU,KAAK,WAAW,QAAQ,GAAG,CAAE;AAAA,UAC7C;AAAA,QACF,CAAC;AACD,YAAI,aAAa,WAAW;AAC5B,YAAI,cAAc;AAChB,gBAAM,WAAW,gBAAgB,KAAK,KAAK;AAC3C,cAAI,SAAU,KAAI,UAAU,YAAY,MAAM,QAAQ,QAAQ,IAAI,SAAS,KAAK,IAAI,IAAI,QAAQ;AAAA,QAClG;AACA,mBAAW,KAAK,KAAK,EAAE,KAAK,KAAK,CAAC;AAAA,MACpC,CAAC;AAED,UAAI,KAAK,gBAAgB,EAAE,KAAK,KAAK,CAAC;AAEtC,UAAI,GAAG,SAAS,CAAC,QAAa;AAC5B,cAAM,KAAK,SAAS,yBAAyB,GAAG;AAChD,uBAAe,QAAQ;AAAA,MACzB,CAAC;AAED,qBAAe,GAAG,SAAS,CAAC,QAAe;AACzC,cAAM,KAAK,SAAS,0BAA0B,GAAG;AACjD,cAAM,KAAK,SAAS,WAAW,UAAU,IAAI,YAAY,aAAa,EAAE;AACxE,YAAI,CAAC,IAAI,aAAa;AACpB,cAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAAA,QACpE;AACA,YAAI,IAAI,kBAAkB,IAAI,OAAO;AAAA,MACvC,CAAC;AAED,qBAAe,WAAW,MAAQ,MAAM;AACtC,cAAM,KAAK,SAAS,yBAAyB;AAC7C,uBAAe,QAAQ;AACvB,YAAI,CAAC,IAAI,aAAa;AACpB,cAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAAA,QACpE;AACA,YAAI,IAAI,iBAAiB;AAAA,MAC3B,CAAC;AAAA,IACH,CAAC;AAED,gBAAY,GAAG,SAAS,CAAC,QAAa;AACpC,UAAI,IAAI,SAAS,cAAc;AAC7B,cAAM,KAAK,SAAS,gBAAgB,SAAS,SAAS,2BAA2B;AACjF,eAAO,MAAM,eAAe,YAAY;AACxC,cAAM,WAAW,YAAY,SAAS,WAAW;AAAA,UAC/C,YAAY,QAAQ;AAAA,UACpB,OAAO;AAAA,QACT,CAAC;AACD,YAAI,UAAU;AACZ,kBAAQ,KAAK,6CAAyB,SAAS,SAAS,kEAAgB,YAAY,GAAG;AACvF,qBAAW,MAAM,iBAAiB,OAAO,YAAY,GAAG,MAAM,WAAW,IAAI,KAAK,GAAI;AAAA,QACxF;AAAA,MACF,OAAO;AACL,cAAM,KAAK,SAAS,uBAAuB,GAAG;AAAA,MAChD;AAAA,IACF,CAAC;AAED,QAAI,CAAC,MAAM,aAAc,OAAM,eAAe,CAAC;AAC/C,UAAM,aAAa,YAAY,IAAI;AAEnC,gBAAY,SAAS,WAAW,EAAE,YAAY,QAAQ,KAAK,OAAO,aAAa,CAAC;AAEhF,UAAM,WAAW,UAAU,SAAS,SAAS,KAAK;AAClD,UAAM,iBAAiB,6BAAM;AAC3B,cAAQ,IAAI,IAAI,YAAY,cAAc,WAAW,CAAC,GAAG;AACzD,cAAQ,IAAI,4BAA4B,SAAS,aAAa,GAAG,YAAY,WAAW,IAAI,SAAS,SAAS,SAAS;AACvH,cAAQ,IAAI,4BAA4B,SAAS,GAAG,SAAS;AAC7D,cAAQ,IAAI,kDAAkD;AAAA,IAChE,GALuB;AAOvB,QAAI,UAAU;AACZ,kBAAY,OAAO,SAAS,WAAW,UAAU,cAAc;AAAA,IACjE,OAAO;AACL,kBAAY,OAAO,SAAS,WAAW,cAAc;AAAA,IACvD;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,KAAK,SAAS,uBAAuB,KAAK,UAAU,GAAG,CAAC;AAAA,EAChE;AACF;AA1IgB;;;A1BHhB,IAAM,eAAe,oBAAI,IAAsB;AACxC,SAAS,eAAe,MAAoC;AACjE,SAAO,aAAa,IAAI,IAAI;AAC9B;AAFgB;AAID,SAAR,YAAkB,OAAY,KAAU;AAE7C,eAAa,IAAI,WAAW,IAAI,OAAO;AACvC,eAAa,IAAI,WAAW,IAAI,OAAO;AACvC,eAAa,IAAI,UAAU,IAAI,MAAM;AACrC,eAAa,IAAI,aAAa,IAAI,SAAS;AAE3C,WAAS,sBAA4B;AACnC,uBAAmB,OAAO,GAAG;AAE7B,YAAQ,IAAI,kSAAkD;AAE9D,2BAAuB,KAAK;AAE5B,QAAI,MAAM,YAAY,OAAO;AAC3B,YAAM,kBAAkB,CAAC,YACvB,gBAAgB,OAAO,OAAO;AAChC,aAAO,KAAK,MAAM,WAAW,KAAK,EAAE,QAAQ,CAAC,OAAe;AAC1D,YAAI,gBAAgB,EAAE,GAAG;AACvB,0BAAgB,OAAO,EAAE;AAAA,QAC3B;AAAA,MACF,CAAC;AAED,UAAI,MAAM,WAAW,MAAM,MAAM;AAC/B,wBAAgB,OAAO,MAAM;AAAA,MAC/B;AAAA,IACF;AAEA,QAAI,MAAM,YAAY,YAAY;AAChC,aAAO,KAAK,MAAM,WAAW,UAAU,EAAE,QAAQ,CAAC,OAAe;AAC/D,YAAI,gBAAgB,EAAE,GAAG;AACvB,2BAAiB,OAAO,EAAE;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AA5BS;AA8BT,SAAO,EAAE,qBAAqB,QAAQ,GAAG;AAC3C;AAtCO;;;A2BlBP;AAAA;AAAA;AAAA;AAAA;;;ACCO,SAAS,OAAO,OAAY;AAClC,WAAS,aAAa,SAAc,SAAkB;AACrD,WAAO,cAAc,WAAW,MAAM,OAAO,SAAS,MAAM,SAAS,KAAK,MAAM,SAAS;AAAA,EAC1F;AAFS;AAIT,WAAS,UAAU,SAAc;AAChC,UAAM,EAAE,SAAS,SAAS,IAAI;AAC9B,UAAM,OAAO,UAAU,KAAK,MAAM,SAAS,KAAK,SAAS,EAAE,IAAI;AAC/D,QAAI,KAAM,QAAO,KAAK,EAAE,SAAS,OAAO,UAAU,SAAS,GAAG,CAAC;AAC/D,WAAO,EAAE,GAAG,SAAS,GAAI,YAAY,CAAC,EAAG;AAAA,EAC1C;AALS;AAOT,WAAS,UAAU,SAAc;AAChC,UAAM,UAAU,QAAQ,OAAO,GAAG,SAAS,QAAQ,eAAe,UAAU,OAAO,IAAI,QAAQ,SAAS,GAAG,QAAQ,EAAE;AAAA,EACtH;AAFS;AAIT,WAAS,aAAa,SAAc,QAAa;AAChD,QAAI,QAAQ,SAAS,KAAK;AACzB,UAAI,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,GAAG;AAC3C,sBAAc,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,CAAC;AACpD,cAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,IAAI;AAAA,MAC1C;AACA;AAAA,IACD;AACA,QAAI,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,EAAG;AAE5C,UAAM,cAAc,UAAU,OAAO;AACrC,UAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,IAAI,YAAY,MAAM;AAC1D,YAAM,UAAU,EAAE,GAAG,UAAU,OAAO,GAAG,IAAI,KAAK,IAAI,EAAE;AACxD,YAAM,UAAU,QAAQ,OAAO,EAAE,OAAO,SAAS,QAAQ,MAAM,GAAG,QAAQ,EAAE;AAC5E,UAAI,CAAC,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,GAAG;AAC5C,sBAAc,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,CAAC;AAAA,MACrD;AAAA,IACD,GAAG,aAAa,MAAM,GAAI;AAE1B,YAAQ,IAAI,OAAO,SAAS,MAAM;AACjC,UAAI,MAAM,QAAQ,QAAQ,OAAO,IAAI,MAAM,GAAG;AAC7C,sBAAc,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM,CAAC;AACpD,eAAO,MAAM,QAAQ,QAAQ,OAAO,EAAE,MAAM;AAAA,MAC7C;AAAA,IACD,CAAC;AAAA,EACF;AAzBS;AA2BT,WAAS,WAAW,SAAc;AACjC,YAAQ,WAAY,QAAQ,gBAAgB,MAAM,UAAU,KAAK,QAAQ,OAAO,IAAI,QAAQ,SAAS,EAAE,KAAM,CAAC;AAC9G,QAAI,QAAQ,UAAU,IAAI;AACzB,mBAAa,SAAS,aAAa,QAAQ,SAAS,QAAQ,OAAO,CAAC;AAAA,IACrE,OAAO;AACN,gBAAU,OAAO;AAAA,IAClB;AAAA,EACD;AAPS;AAST,SAAO,EAAE,cAAc,WAAW,YAAY,cAAc,UAAU;AACvE;AArDgB;;;ACShB,eAAsB,sBAAsB,KAAU,OAA2B;AAChF,QAAM,WAAW,KAAK;AACtB,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,SAAS,CAAC,EAAG;AAC9C,QAAM,KAAK,OAAO,SAAS,CAAC,CAAC;AAC7B,MAAI;AACH,UAAM,EAAE,iBAAAC,iBAAgB,IAAI,MAAM,OAAO,6BAAyC;AAClF,UAAM,OAAO,MAAMA,iBAAgB,KAAK,EAAE,eAAe,EAAE;AAC3D,QAAI,QAAQ,KAAK,WAAW,UAAU;AACrC,UAAI,cAAc,EAAE,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,QAAQ,KAAK,OAAO;AAClE,UAAI,SAAS,CAAC,IAAI,OAAO,KAAK,EAAE;AAAA,IACjC,OAAO;AACN,UAAI,cAAc;AAAA,IACnB;AAAA,EACD,QAAQ;AACP,QAAI,cAAc;AAAA,EACnB;AACD;AAhBsB;AAkBf,SAAS,oBAAoB,KAAkB;AACrD,MAAI,KAAK,aAAa,MAAM,KAAM,QAAO,OAAO,IAAI,YAAY,EAAE;AAClE,QAAM,IAAI,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AACzC,SAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AACjC;AAJgB;AAMT,SAAS,mBAAmB,KAA8B;AAChE,MAAI,KAAK,aAAa,GAAI,QAAO,OAAO,IAAI,YAAY,EAAE;AAC1D,QAAM,KAAK,KAAK,WAAW,CAAC;AAC5B,SAAO,KAAK,OAAO,EAAE,IAAI;AAC1B;AAJgB;;;ACrBhB,SAAS,kBAAkB,OAAqC;AAC/D,SAAQ,OAAO,YAAY,YAAwC,CAAC;AACrE;AAFS;AAIT,SAAS,mBAAmBC,OAAc,SAA0B;AACnE,MAAI,QAAQ,SAAS,GAAG,GAAG;AAC1B,WAAOA,MAAK,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC;AAAA,EAC5C;AACA,SAAOA,UAAS;AACjB;AALS;AAQF,SAAS,cAAc,OAAY,UAA2B;AACpE,QAAM,MAAM,kBAAkB,KAAK;AACnC,QAAM,YAAa,IAAI,iBAA8B;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACA,SAAO,UAAU,KAAK,CAAC,MAAM,mBAAmB,UAAU,CAAC,CAAC;AAC7D;AAXgB;AAaT,SAAS,eAAe,OAAY,UAA2B;AACrE,QAAM,MAAM,kBAAkB,KAAK;AACnC,MAAI,CAAC,IAAI,YAAa,QAAO;AAC7B,MAAI,cAAc,OAAO,QAAQ,EAAG,QAAO;AAC3C,SAAO;AACR;AALgB;AAaT,SAAS,iBAAiB,KAAU,OAAY,UAAmC;AACzF,MAAI,CAAC,eAAe,OAAO,QAAQ,GAAG;AACrC,WAAO,EAAE,IAAI,KAAK;AAAA,EACnB;AAEA,QAAM,WAAW,KAAK;AACtB,QAAM,KAAK,YAAY,GAAG;AAE1B,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,KAAK,CAAC,SAAS,CAAC,GAAG;AACpE,qBAAiB,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,QAAQ;AAAA,IACT,CAAC;AACD,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,0BAA0B;AAAA,EACnE;AAEA,QAAM,CAAC,EAAE,IAAI;AACb,QAAM,MAAM,kBAAkB,KAAK;AACnC,QAAM,WAAW,OAAO,IAAI,iBAAiB,WAAW,IAAI,eAAe;AAC3E,QAAM,YAAY,oBAAoB,GAAG;AAEzC,MAAI,YAAY,UAAU;AACzB,qBAAiB,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ,KAAK;AAAA,MACb,MAAM,OAAO,EAAE;AAAA,MACf,OAAO;AAAA,MACP;AAAA,MACA,QAAQ,YAAY,QAAQ;AAAA,IAC7B,CAAC;AACD,WAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,0BAA0B;AAAA,EACnE;AAEA,SAAO,EAAE,IAAI,KAAK;AACnB;AAtCgB;AAyChB,eAAsB,sBAAsB,KAAU,OAAY,UAA4C;AAC7G,MAAI,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,SAAS,CAAC,GAAG;AACpD,UAAM,sBAAsB,KAAK,KAAK;AACtC,QAAI,CAAC,IAAI,eAAe,eAAe,OAAO,QAAQ,GAAG;AACxD,uBAAiB,OAAO;AAAA,QACvB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,MAAM,OAAO,IAAI,SAAS,CAAC,CAAC;AAAA,QAC5B,IAAI,YAAY,GAAG;AAAA,QACnB,QAAQ;AAAA,MACT,CAAC;AACD,aAAO,EAAE,IAAI,OAAO,MAAM,KAAK,SAAS,uBAAuB;AAAA,IAChE;AAAA,EACD;AACA,SAAO,iBAAiB,KAAK,OAAO,QAAQ;AAC7C;AAhBsB;AAkBf,SAAS,cAAc,KAAU,QAA+B;AACtE,MAAI,UAAU,OAAO,QAAQ,KAAK,EAAE,gBAAgB,kCAAkC,CAAC;AACvF,MAAI,IAAI,KAAK,UAAU,EAAE,OAAO,OAAO,WAAW,eAAe,CAAC,CAAC;AACpE;AAHgB;;;AC9FT,SAAS,OAAO,OAAyB;AAC/C,SAAO,UAAU,KAAK,UAAU;AACjC;AAFgB;AAKT,SAAS,sBAAsB,SAAqE;AAC1G,QAAM,MAAM,WAAW,CAAC;AACxB,SAAO;AAAA,IACN,OAAO,OAAO,IAAI,KAAK;AAAA,IACvB,IAAI,OAAO,IAAI,EAAE;AAAA,IACjB,QAAQ,OAAO,IAAI,MAAM;AAAA,IACzB,MAAM,OAAO,IAAI,IAAI;AAAA,IACrB,QAAQ,OAAO,IAAI,MAAM;AAAA,IACzB,SAAS,YAAY,IAAI,SAAS,GAAI;AAAA,IACtC,OAAO,YAAY,IAAI,OAAO,GAAI;AAAA,IAClC,WAAW,YAAY,IAAI,WAAW,GAAG;AAAA,EAC1C;AACD;AAZgB;AAchB,SAAS,YAAY,OAAgB,UAA0B;AAC9D,QAAM,IAAI,OAAO,KAAK;AACtB,SAAO,OAAO,UAAU,CAAC,KAAK,IAAI,IAAI,IAAI;AAC3C;AAHS;AAMF,SAAS,0BAA0B,MAAqC;AAC9E,MAAI,KAAK,SAAS,KAAM,MAAK,QAAQ;AACrC,MAAI,KAAK,MAAM,KAAM,MAAK,KAAK;AAC/B,MAAI,KAAK,UAAU,KAAM,MAAK,SAAS;AACvC,MAAI,KAAK,QAAQ,KAAM,MAAK,OAAO;AACnC,MAAI,KAAK,UAAU,KAAM,MAAK,SAAS;AACvC,MAAI,KAAK,WAAW,KAAM,MAAK,UAAU;AACzC,MAAI,KAAK,SAAS,KAAM,MAAK,QAAQ;AACrC,MAAI,KAAK,aAAa,KAAM,MAAK,YAAY;AAC7C,MAAI,CAAC,MAAM,QAAQ,KAAK,IAAI,EAAG,MAAK,OAAO,CAAC;AAC7C;AAVgB;AAaT,SAAS,qBACf,KACA,SACA,WACgB;AAChB,QAAM,SAAS,sBAAsB,OAAO;AAC5C,MAAI,CAAC,OAAO,OAAQ,QAAO;AAE3B,MAAI,SAAS,UAAU,KAAK,QAAQ;AACpC,MAAI,CAAC,QAAQ;AACZ,UAAM,UAAU,UAAU,KAAK,SAAS;AACxC,QAAI,SAAS;AACZ,UAAI;AACH,iBAAS,IAAI,IAAI,OAAO,EAAE;AAAA,MAC3B,QAAQ;AACP,cAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,YAAI,MAAM,UAAU,EAAG,UAAS,GAAG,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;AAAA,MACzD;AAAA,IACD;AAAA,EACD;AACA,SAAO,UAAU;AAClB;AArBgB;AAuBT,SAAS,iBACf,QACA,SACA,YACU;AACV,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,WAAW,IAAK,QAAO;AAC3B,QAAM,WAAW,SAAS;AAC1B,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,SAAS,OAAQ,QAAO;AACzD,MAAI,SAAS,SAAS,MAAM,EAAG,QAAO;AACtC,MAAI,cAAc,OAAO,SAAS,UAAU,EAAG,QAAO;AACtD,SAAO;AACR;AAZgB;;;ACnEhB,SAAS,gBAAgB,KAAU,SAAkC;AACnE,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAC1B,QAAI,WAAW;AACf,QAAI,UAAU;AACd,UAAM,SAAS,wBAAC,KAAmB,SAAkB;AACnD,UAAI,QAAS;AACb,gBAAU;AACV,UAAI,IAAK,QAAO,GAAG;AAAA,UACd,CAAAA,SAAQ,QAAQ,EAAE;AAAA,IACzB,GALe;AAMf,QAAI,GAAG,QAAQ,CAAC,UAAkB;AAChC,UAAI,QAAS;AACb,kBAAY,MAAM;AAClB,UAAI,WAAW,SAAS;AACtB,YAAI,QAAQ;AACZ,eAAO,IAAI,MAAM,mBAAmB,CAAC;AACrC;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AACD,QAAI,GAAG,OAAO,MAAM,OAAO,MAAM,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM,CAAC,CAAC;AACxE,QAAI,GAAG,SAAS,CAAC,QAAe,OAAO,GAAG,CAAC;AAAA,EAC7C,CAAC;AACH;AAxBS;AA0BT,SAAS,mBAAmB,OAAY,KAAU,UAAkB,IAA2D;AAC7H,MAAI,QAAQ;AACZ,MAAI,MAAM;AACV,MAAI,MAAM,KAAK,UAAU,KAAK,aAAa,SAAS,GAAG;AACrD,YAAQ;AACR,UAAM,UAAe,KAAK,MAAM,GAAG;AACnC,UAAM,MAAM,KAAK,OAAO,OAAO,EAAE,MAAM,QAAQ,CAAC;AAChD,QAAI,SAAS,QAAQ,KAAK,OAAO,QAAQ,UAAU;AACjD,UAAI;AACF,cAAM,KAAK,MAAM,GAAG;AAAA,MACtB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACA,QAAM,YAAY,OAAO,QAAQ,YAAY,IAAI,UAAU,EAAE,WAAW,GAAG;AAC3E,MAAI,KAAK,WAAW,CAAC,KAAK,CAAC,WAAW;AACpC,SAAK,IAAI,SAAS,CAAC;AACnB,UAAM,MAAM,KAAK,OAAO,SAAS,KAAK,EAAE;AAAA,EAC1C;AACA,SAAO,EAAE,UAAU,KAAK,IAAI,MAAM;AACpC;AArBS;AAuBT,IAAO,cAAQ,wBAAC,OAAY,MAAW,CAAC,MAAM;AAC5C,OAAK,KAAK,KAAK;AAGf,WAAS,UAAU,KAAU,KAAqB;AAChD,WAAO,IAAI,QAAQ,IAAI,YAAY,CAAC,KAAK;AAAA,EAC3C;AAFS;AAIT,MAAI,gBAAwD;AAC5D,MAAI,mBAAmB;AAEvB,WAAS,eAAeC,QAAY,UAAkB;AACpD,UAAM,OAAOA,OAAM;AACnB,QAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,QAAI,CAAC,iBAAiB,qBAAqB,KAAK,QAAQ;AACtD,sBAAgB,KAAK,IAAI,CAAC,SAAiB,EAAE,KAAK,KAAK,MAAM,QAAQ,GAAG,GAAG,EAAE;AAC7E,yBAAmB,KAAK;AAAA,IAC1B;AACA,QAAI,CAAC,cAAe,QAAO;AAC3B,aAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC7C,YAAM,QAAQ,cAAc,CAAC;AAC7B,UAAI,aAAa,MAAM,QAAQ,SAAS,WAAW,MAAM,IAAI,GAAG;AAC9D,eAAO,MAAM;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAfS;AAiBT,WAAS,UAAU,KAAU,MAAc,SAAiB;AAC1D,QAAI,UAAU,MAAM;AAAA,MAClB,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC5C;AALS;AAMT,WAAS,QAAQ,KAAU,KAAU,SAAiB;AACpD,UAAM,UAAe,MAAM,QAAQ,OAAO;AAC1C,UAAM,SAAS,qBAAqB,KAAK,SAAS,SAAS;AAC3D,UAAM,OAAY,UAAU,KAAK,MAAM;AACvC,QAAI,iBAAiB,QAAQ,SAAS,IAAI,GAAG;AAC3C,UAAI,UAAU,+BAA+B,WAAW,MAAM,MAAM,MAAO;AAC3E,UAAI,UAAU,gCAAgC,oBAAoB;AAClE,UAAI,UAAU,gCAAgC,iDAAiD;AAG/F,UAAI,IAAI,WAAW,WAAW;AAC5B,YAAI,aAAa;AACjB,eAAO,IAAI,IAAI;AAAA,MACjB;AACA,UAAI,KAAa;AACjB,UAAI,QAAiB;AACrB,UAAI,UAAe,UAAkB;AAMrC,iBAAW,IAAI,IAAI,IAAI,KAAK,UAAU,UAAU,KAAK,MAAM,CAAC,EAAE;AAC9D,iBAAW,SAAS;AACpB,UAAI,MAAM,KAAK,UAAU,SAAS,OAAO,WAAW,OAAO,GAAG;AAC5D,gBAAQ;AACR,iBAAS,SAAS,MAAM,KAAK,OAAO,OAAO,EAAE,MAAM,KAAK,MAAM,mBAAmB,SAAS,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;AAAA,MACnH;AACA,UAAI,SAAS,OAAO,WAAW,MAAM,GAAG;AACtC,gBAAQ;AAAA,UACN,IAAI,mBAAmB,SAAS,OAAO,UAAU,CAAC,CAAC;AAAA,QACrD;AACA,YAAI,IAAI,IAAI,QAAQ,QAAQ,MAAM,IAAI;AAEpC,cAAI,KAAK,YAAY,KAAK,SAAS,CAAC,KAAK,OAAO,IAAI;AAClD,iBAAK,IAAI,SAAS,CAAC;AAEnB,oBAAQ,MAAM,KAAK,OAAO,SAAS,OAAO,IAAI,EAAE;AAChD,oBAAQ,OAAO,YAAY,IAAI,gBAAgB,MAAM,KAAK,EAAE,QAAQ,CAAC;AAAA,UACvE;AAAA,QACF;AAAA,MACF,OAAO;AACL,gBAAQ,OAAO,YAAY,IAAI,gBAAgB,SAAS,MAAM,EAAE,QAAQ,CAAC;AAAA,MAC3E;AAIA,YAAM,gBAAgB,eAAe,OAAO,QAAQ;AACpD,UAAI,CAAC,eAAe;AAClB,eAAO,UAAU,KAAK,KAAK,WAAW;AAAA,MACxC;AACA,YAAM,WAAW,YAAY,GAAG;AAChC,YAAM,UAAU,eAAe,OAAO,SAAS,QAAQ;AACvD,UAAI,CAAC,QAAQ,IAAI;AACf,eAAO,UAAU,KAAK,QAAQ,QAAQ,KAAK,QAAQ,WAAW,gBAAgB;AAAA,MAChF;AACA,YAAM,cAAc,6BAAM,eAAe,SAAS,QAAQ,GAAtC;AACpB,UAAI,KAAK,UAAU,WAAW;AAC9B,UAAI,KAAK,SAAS,WAAW;AAE7B,YAAM,UAAU,MAAM,YAAY,WAAW,MAAM,OAAO;AAC1D,YAAM,aAAa,IAAI,WAAW,UAAU,IAAI,IAAI,QAAQ,QAAQ,MAAM;AAC1E,YAAM,cAAc,aAAa,gBAAgB,KAAK,OAAO,IAAI;AAEjE,YAAM,YAAY;AAChB,YAAI;AACJ,YAAI,UAAU;AACd,YAAI;AACF,WAAC,YAAY,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,YACxC,sBAAsB,KAAK,OAAO,QAAQ;AAAA,YAC1C,eAAe,QAAQ,QAAQ,EAAE;AAAA,UACnC,CAAC;AAAA,QACH,SAAS,KAAU;AACjB,sBAAY;AACZ,cAAI,KAAK,YAAY,qBAAqB;AACxC,mBAAO,UAAU,KAAK,KAAK,mBAAmB;AAAA,UAChD;AACA,iBAAO,UAAU,KAAK,KAAK,KAAK,WAAW,aAAa;AAAA,QAC1D;AACA,YAAI,CAAC,WAAW,IAAI;AAClB,sBAAY;AACZ,iBAAO,cAAc,KAAK,UAAU;AAAA,QACtC;AAEF,YAAI,QAAa,MAAM,cAAc,aAAa,IAAI,OAAO,KAAK;AAClE,YAAI,CAAC,OAAO;AACV,iBAAO,UAAU,KAAK,KAAK,iBAAiB;AAAA,QAC9C;AAEA,YAAI,UAAU,gBAAgB,iCAAiC;AAE/D,cAAM,KAAK,OAAO,IAAI,QAAQ,SAAS,UAAU,KAAK;AAEtD,YAAI;AACJ,YAAI;AACJ,YAAI,IAAI,IAAI,QAAQ,QAAQ,MAAM,IAAI;AACpC,mBAAS;AACT,cAAI,IAAI,WAAW,QAAQ;AACzB,gBAAI;AACF,oBAAM,YAAY,mBAAmB,OAAO,KAAK,SAAS,EAAE;AAC5D,yBAAW,UAAU;AACrB,mBAAK,UAAU;AACf,sBAAQ,UAAU;AAAA,YACpB,QAAQ;AACN,qBAAO,UAAU,KAAK,KAAK,oBAAoB;AAAA,YACjD;AACA,gBAAI,OAAO,QAAQ,OAAO,OAAO,SAAS,YAAY;AACpD,oBAAM,SAAc,EAAE,QAAQ,MAAM,UAAU,GAAG;AACjD,kBAAI,SAAS,MAAM,KAAK,QAAQ,QAAQ;AACtC,uBAAO,SAAS,MAAM,KAAK,QAAQ;AAAA,cACrC;AACA,oBAAM,KAAK,KAAK,KAAK,SAAS,MAAM;AAAA,YACtC,OAAO;AACL,kBAAI,IAAI,OAAO,aAAa,WAAW,WAAW,KAAK,UAAU,YAAY,EAAE,CAAC;AAAA,YAClF;AAAA,UACF,WAAW,IAAI,WAAW,OAAO;AAE/B,gBAAI,OAAO,OAAO,OAAO,OAAO,QAAQ,YAAY;AAElD,oBAAM,SAAc,EAAE,QAAQ,MAAM,QAAQ,GAAG;AAE/C,kBAAI,SAAS,MAAM,KAAK,QAAQ,QAAQ;AACtC,uBAAO,SAAS,MAAM,KAAK,QAAQ;AAAA,cACrC;AAEA,oBAAM,IAAI,KAAK,KAAK,SAAS,MAAM;AAAA,YACrC,OAAO;AACL,kBAAI,IAAI,KAAK,UAAU,MAAM,CAAC;AAAA,YAChC;AAAA,UACF;AAAA,QACF,OAAO;AAEL,cAAI,OAAO,KAAK,KAAK,GAAG,QAAQ;AAC9B,qBAAS;AAAA,UACX;AACA,cAAI,IAAI,WAAW,QAAQ;AACzB,kBAAM,KAAK,WAAW,SAAS,GAAG,EAC/B,KAAK,CAACC,cAAkB;AAEvB,kBAAI,OAAO,QAAQ,OAAO,OAAO,SAAS,YAAY;AACpD,sBAAM,KAAK,KAAK,KAAK,SAAS;AAAA,kBAC5B;AAAA,kBACA,MAAMA;AAAA,gBACR,CAAC;AAAA,cACH,OAAO;AACL,oBAAI,IAAIA,SAAQ;AAAA,cAClB;AAAA,YACF,CAAC,EACA,MAAM,CAAC,QAAa;AACnB,qBAAO,UAAU,KAAK,KAAK,sBAAsB;AAAA,YACnD,CAAC;AAAA,UACL;AAAA,QACF;AAAA,MACA,GAAG;AAAA,IACL,OAAO;AACL,YAAM,KAAK,OAAO,IAAI,QAAQ,IAAI,GAAG;AAAA,IACvC;AAAA,EACF;AA7JS;AA+JT,SAAO,EAAE,QAAQ;AACnB,GAlMe;;;ACrDf,IAAO,aAAQ,wBAAC,OAAY,MAAW,CAAC,MAAM;AAC5C,OAAK,KAAK,KAAK;AAGf,QAAM,iBAAiB,oBAAI,IAAiB;AAC5C,QAAM,aAAa,mBAAmB,KAAK;AAE3C,WAAS,aAAa,YAAoB;AACxC,QAAI,CAAC,eAAe,IAAI,UAAU,GAAG;AACnC,qBAAe,IAAI,YAAY,MAAM,aAAa,UAAU,IAAI,KAAK,CAAC;AAAA,IACxE;AACA,WAAO,eAAe,IAAI,UAAU;AAAA,EACtC;AALS;AAQT,WAAS,aAAa,KAAU;AAC9B,QAAI,OAAO,SAAS,GAAG,GAAG;AACxB,YAAM,IAAI,SAAS;AAAA,IACrB;AACA,QAAI,QAAQ,QAAQ;AAAA,IACpB,WAAW,OAAO,QAAQ,UAAU;AAClC,UAAI;AACF,cAAM,KAAK,MAAM,GAAG;AAAA,MACtB,SAAS,KAAK;AAAA,MAAC;AAAA,IACjB;AACA,WAAO,YAAY,GAAG;AAAA,EACxB;AAXS;AAcT,WAAS,OAAO,KAAUC,KAAS,SAAiB,KAAU;AAC5D,QAAI;AACF,UAAI,UAAU,aAAa,GAAG;AAE9B,UAAI;AACJ,UAAI,YAAY,QAAQ;AAEtB,QAAAA,IAAG,OAAO,MAAM;AAChB;AAAA,MACF,OAAO;AACL,cAAM,eAAwB,OAAO,YAAY,YAAY,YAAY;AACzE,qBAAa,eACT,WAAW,QAAQ,SAAS,EAAE,IAC9B,WAAW,YAAY,OAAO;AAElC,YAAI,CAAC,cAAc,MAAM,eAAe,QAAQ;AAC9C,uBAAa,MAAM,cAAc,KAAK,CAAC,QAAgB;AACrD,gBAAI,cAAc;AAChB,qBAAO,SAAS,IAAI,WAAW,GAAG;AAAA,YACpC;AACA,mBAAO,OAAO,YAAY,YAAY,QAAQ,WAAW,GAAG;AAAA,UAC9D,CAAC;AAAA,QACH;AAEA,YAAI,CAAC,YAAY;AACf,gBAAM,UAAU,WAAW;AAAA,YACzB;AAAA,YACA,IAAAA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,WAAY;AACjB,mBAAa,UAAU,GAAG,OAAO,SAASA,KAAI,SAAS,GAAG;AAAA,IAC5D,SAAS,KAAK;AACZ,OAAC,MAAM,QAAQ,QAAQ,SAAS,MAAM,iBAAiB,eAAe,QAAQ,IAAI,UAAU,GAAG;AAAA,IACjG;AAAA,EACF;AAzCS;AA0CT,WAAS,YAAY,KAAU;AAC7B,QAAI,KAAK,IAAI,OAAO,MAAM,MAAM,QAAQ,QAAQ;AAC9C,UAAI,KAAK,MAAM,KAAK,OAAO,OAAO,EAAE,MAAM,IAAI,GAAG,CAAC;AAAA,IACpD;AACA,WAAO;AAAA,EACT;AALS;AAQT,WAAS,YAAYC,QAAY;AAE/B,QAAI,CAACA,OAAM,SAAS;AAClB,MAAAA,OAAM,UAAU;AAAA,QACd,eAAe;AAAA,UACb,UAAU,CAAC;AAAA,QACb;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,aAAa,6BAAM;AAEjB,cAAM,MAAMA,OAAM,QAAQ,QAAQ;AAClC,YAAI,MAAM,0BAA0B;AAAA,MACtC,GAJa;AAAA,IAKf;AAAA,EACF;AAhBS;AAkBT,SAAO,EAAE,QAAQ,YAAY;AAC/B,GAlGe;;;ACDf,IAAO,cAAQ,wBAAC,OAAY,MAAW,CAAC,MAAM;AAC1C,OAAK,KAAK,KAAK;AAEf,MAAI,gBAAyD;AAC7D,MAAI,mBAAmB;AAEvB,WAAS,kBAAkB,KAAe;AACtC,UAAM,SAAS,MAAM;AACrB,QAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,QAAI,CAAC,iBAAiB,qBAAqB,OAAO,QAAQ;AACtD,sBAAgB,OAAO,IAAI,CAAC,SAAiB,EAAE,KAAK,KAAK,OAAO,IAAI,GAAG,GAAG,EAAE;AAC5E,yBAAmB,OAAO;AAAA,IAC9B;AACA,QAAI,CAAC,cAAe,QAAO;AAC3B,UAAM,MAAM,IAAI,OAAO;AACvB,aAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC3C,YAAM,OAAO,cAAc,CAAC;AAC5B,UAAI,IAAI,WAAW,KAAK,KAAK,KAAK,MAAM,cAAc,KAAK,GAAG,GAAG;AAC7D,eAAO,KAAK;AAAA,MAChB;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAhBS;AAmBT,QAAM,YAAY,wBAAC,KAAU,MAAc,YAAoB;AAC3D,QAAI,UAAU,MAAM;AAAA,MAChB,gBAAgB;AAAA,IACpB,CAAC;AACD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9C,GALkB;AAMlB,WAAS,QAAQ,KAAU,KAAU,SAAiB;AAElD,UAAM,aAAa,kBAAkB,GAAG;AAExC,QAAI,CAAC,YAAY;AACb,aAAO,UAAU,KAAK,KAAK,WAAW;AAAA,IAC1C;AAEA,UAAM,WAAW,IAAI,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AAC5C,UAAM,YAAY;AAClB,YAAM,aAAa,MAAM,sBAAsB,KAAK,OAAO,OAAO;AAClE,UAAI,CAAC,WAAW,IAAI;AAChB,eAAO,cAAc,KAAK,UAAU;AAAA,MACxC;AAGA,YAAM,UAAU,MAAM,cAAc,UAAU,IAAI,KAAK;AACvD,UAAI,CAAC,SAAS;AACV,eAAO,UAAU,KAAK,KAAK,+BAA+B;AAAA,MAC9D;AAEA,UAAI,SAAS,QAAQ,OAAO,SAAS,SAAS,YAAY;AACtD,gBAAQ,KAAK,KAAK,KAAK,OAAO;AAAA,MAClC,OAAO;AACH,YAAI,IAAI,UAAU;AAAA,MACtB;AACA,UAAI,CAAC,SAAS;AACV,YAAI,UAAU,KAAK;AAAA,UACf,gBAAgB;AAAA,QACpB,CAAC;AACD,YAAI,IAAI,IAAI,GAAG;AAAA,MACnB,OAAO;AAAA,MAEP;AAAA,IACA,GAAG;AAAA,EACP;AAnCS;AAqCT,SAAO,EAAE,QAAQ;AACrB,GArEe;;;ACLf,IAAO,mBAAQ,wBAAC,OAAY,WAAmB;AAC3C,MAAI,CAAC,OAAO,UAAU;AAClB,UAAM,WAAW,CAAC;AAAA,EACtB;AACA,MAAI,CAAC,MAAM,SAAS,MAAM,GAAG;AACzB,UAAM,SAAS,MAAM,IAAI,EAAE,OAAO,oBAAI,IAAI,EAAE;AAAA,EAChD;AACA,WAAS,aAAa,SAAsB;AACxC,WAAO,SAAS,MAAM,SAAS;AAAA,EACnC;AAFS;AAGT,WAAS,eAAe;AACpB,WAAO,IAAI,QAAQ,CAACC,UAAc,WAAgB;AAC9C,YAAM,SAAS,MAAM,EAAE,SAAS,IAAI,MAAM;AAAA,QACtC,MAAM,QAAQ,cAAc,SAAS,MAAM;AAAA,MAC/C;AAEA,YAAM,SAAS,MAAM,EAAE,OAAO,YAAY,CAAC,UAAe;AACtD,0BAAkB,MAAM,IAAI;AAAA,MAChC;AAEA,YAAM,SAAS,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,QAAa;AACpD,cAAM,SAAS,MAAM,EAAE,OAAO;AAC9B,cAAM,WAAW,QAAQ,IAAI,QACzB,QAAQ;AAAA,UACJ;AAAA,UACA,GAAG,MAAM,IAAI,MAAM,QAAQ,cAAc,SAAS,MAAM,CAAC;AAAA,UACzD;AAAA,QACJ;AACJ,eAAO;AAAA,MACX,CAAC;AAED,YAAM,SAAS,MAAM,EAAE,OAAO,GAAG,SAAS,MAAM;AAC5C,cAAM,SAAS,MAAM,EAAE,OAAO;AAC9B,cAAM,WAAW,QAAQ,IAAI,QACzB,QAAQ;AAAA,UACJ;AAAA,UACA,GAAG,MAAM,IAAI,MAAM,QAAQ,cAAc,SAAS,MAAM,CAAC;AAAA,QAC7D;AACJ,eAAO;AAAA,MACX,CAAC;AAED,YAAM,SAAS,MAAM,EAAE,OAAO,SAAS,MAAM;AACzC,cAAM,WAAW,QAAQ,IAAI,QACzB,QAAQ;AAAA,UACJ;AAAA,UACA,GAAG,MAAM,IAAI,MAAM,QAAQ,cAAc,SAAS,MAAM,CAAC;AAAA,QAC7D;AACJ,cAAM,SAAS,MAAM,EAAE,OAAO;AAC9B,QAAAA,SAAQ;AAAA,MACZ;AAAA,IACJ,CAAC;AAAA,EACL;AAzCS;AA2CT,WAAS,aAAa,SAAiB;AACnC,QAAI,MAAM,SAAS,MAAM,EAAE,MAAM;AAC7B,YAAM,SAAS,MAAM,EAAE,OAAO,KAAK,OAAO;AAAA,IAC9C;AAAA,EACJ;AAJS;AAKT,WAAS,kBAAkB,SAAiB;AACxC,QAAI,MAAM,SAAS,MAAM,EAAE,MAAM;AAC7B,UAAI;AACA,cAAM,cAAmB,KAAK,MAAM,OAAO;AAC3C,cAAM,MAAc,aAAa,WAAW;AAC5C,cAAM,OAAO,MAAM,SAAS,MAAM,EAAE,MAAM,IAAI,GAAG;AACjD,YAAI,MAAM;AACN,gBAAM,SAAS,WAAW;AAC1B,cAAI,YAAY,MAAM,CAAC,YAAY,IAAI;AAAA,UAEvC,OAAO;AACH,kBAAM,SAAS,MAAM,EAAE,MAAM,OAAO,GAAG;AAAA,UAC3C;AAAA,QACJ;AAAA,MACJ,SAAS,GAAG;AAAA,MAAC;AAAA,IACjB;AAAA,EACJ;AAhBS;AAiBT,WAAS,YAAY,aAAkB;AACnC,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACpC,UAAI,MAAM,SAAS,MAAM,EAAE,MAAM;AAC7B,YAAI;AACA,gBAAM,UAAe,CAAC;AACtB,kBAAQ,YAAY,KAAK,IAAI;AAC7B,cAAI,CAAC,YAAY,IAAI;AACjB,wBAAY,KAAK,MAAM,KAAK,GAAG,KAAK,IAAI;AAAA,UAC5C;AACA,gBAAM,SAAS,MAAM,EAAE,MAAM;AAAA,YACzB,aAAa,WAAW;AAAA,YACxB;AAAA,cACI,UAAU,wBAAC,QAAa;AACpB,gBAAAA,SAAQ,GAAG;AAAA,cACf,GAFU;AAAA,cAGV,GAAG;AAAA,cACH,GAAG;AAAA,YACP;AAAA,UACJ;AACA,uBAAa,KAAK,UAAU,WAAW,CAAC;AAAA,QAC5C,SAAS,KAAK;AACV,iBAAO,GAAG;AAAA,QACd;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAzBS;AA0BT,WAAS,cAAc,aAAkB,IAAS;AAC9C,QAAI,MAAM,SAAS,MAAM,EAAE,MAAM;AAC7B,UAAI;AACA,cAAM,SAAS,MAAM,EAAE,MAAM,IAAI,aAAa,WAAW,GAAG;AAAA,UACxD,UAAU,wBAAC,QAAa;AACpB,eAAG,GAAG;AAAA,UACV,GAFU;AAAA,UAGV,GAAG;AAAA,QACP,CAAC;AACD,qBAAa,KAAK,UAAU,WAAW,CAAC;AAAA,MAC5C,SAAS,KAAK;AAAA,MAAC;AAAA,IACnB;AAAA,EACJ;AAZS;AAaT,WAAS,iBAAiB,aAAkB;AACxC,QAAI,aAAa,OAAO,SAAS;AAC7B,YAAM,SAAS,MAAM,EAAE,QAAQ,oBAAI,IAAI;AAAA,IAE3C,OAAO;AACH,YAAM,MAAc,aAAa,WAAW;AAC5C,YAAM,OAAO,MAAM,SAAS,MAAM,EAAE,MAAM,IAAI,GAAG;AACjD,UAAI,MAAM;AACN,cAAM,SAAS,MAAM,EAAE,MAAM,OAAO,GAAG;AAAA,MAC3C;AAAA,IACJ;AAAA,EACJ;AAXS;AAaT,SAAO;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AACJ,GAtIe;;;ACKf,IAAO,gBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACVA,IAAO,eAAQ,wBAAC,UAAe;AAC3B,WAAS,KAAK,SAAcC,KAAS,SAAiB,KAAU;AAC5D,UAAM,UAAU,OAAO,EAAE,OAAO,QAAQ,GAAGA,GAAE;AAAA,EACjD;AAFS;AAGT,SAAO,EAAE,KAAK;AAClB,GALe;;;ACAf,IAAO,cAAQ,wBAAC,UAAe;AAE3B,WAAS,UAAU,SAAcC,KAAS,SAAiB,KAAU;AACjE,QAAI;AACJ,QAAI,QAAQ,IAAI,QAAQ,OAAO,QAAQ,GAAG,SAAS,UAAU;AACzD,aAAO,QAAQ,GAAG;AAClB,aAAO,QAAQ,GAAG;AAAA,IACtB,OAAO;AACH,aAAO;AAAA,IACX;AACA,QAAI,CAAC,MAAM,IAAI,KAAK,MAAM,IAAI,GAAG;AAC7B,YAAM,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,MAAM,IAAI,KAAK,IAAI;AAAA,IAC/D;AACA,UAAM,IAAI,KAAK,MAAM,IAAI,EAAE,GAAG,KAAK,QAAQ,EAAE;AAC7C,UAAM,KAAK,GAAG,SAAS,MAAM;AACzB,cAAQ,KAAK,QAAQ,GAAG,MAAM,GAAG,EAAE,IAAI;AACvC,cAAQ,KAAK,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AACxC,aAAO,QAAQ;AACf,YAAM,KAAK,SAAS,aAAa,OAAO;AACxC,YAAM,UAAU,OAAO,EAAE,OAAO,SAAS,GAAGA,GAAE;AAC9C,YAAM,IAAI,KAAK,MAAM,IAAI,EAAE,KAAK,CAAC;AAAA,IACrC,GAAG,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE,EAAE;AAAA,EACpC;AApBS;AAqBT,WAAS,KAAK,SAAcA,KAAS,SAAiB,KAAU;AAC5D,QAAI,QAAQ,GAAG,SAAS,MAAM,GAAG;AAE7B,gBAAU,SAASA,KAAI,SAAS,GAAG;AAEnC,YAAM,UAAU,OAAO,EAAE;AAAA,QACrB,EAAE,IAAI,QAAQ,IAAI,IAAI,EAAE;AAAA,QACxB;AAAA,QACAA;AAAA,MACJ;AAAA,IACJ;AACA,UAAM,KAAK,QAAQ,YAAY,OAAO;AAAA,EAC1C;AAZS;AAaT,SAAO,EAAE,KAAK;AAClB,GArCe;;;ACGf,IAAO,aAAQ;AAAA,EACb;AAAA,EACA,YAAY;AACd;;;ACNA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAWjB,eAAe,SAAS,KAAU,OAAY,KAA+B;AAC3E,QAAM,sBAAsB,KAAK,KAAK;AACtC,SAAO,oBAAoB,GAAG,KAAK;AACrC;AAHe;AAKf,IAAO,oBAAQ,wBAAC,UAAe;AAC7B,QAAM;AAAA,IACJ,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,sBAAAC;AAAA,EACF,IAAI,MAAM,KAAK;AACf,QAAM,EAAE,aAAa,UAAU,MAAM,IAAI,MAAM,MAAM,UAAU,KAAK;AAEpE,WAAS,SAAS,KAAU;AAC1B,UAAM,OAAO,GAAG,GAAG;AAAA,EACrB;AAFS;AAOT,WAAS,OAAO,KAAkB;AAChC,QAAI,SAAiB,IAAI,QAAQ,OAAO,IAAI,MAAM;AAClD,QAAI,QAAQ;AACV,eAAS,mBAAmB,MAAM;AAAA,IACpC,OAAO;AACL,eAAS,IAAI,QAAQ,MAAM,IAAI,MAAM;AACrC,UAAI,QAAQ;AACV,iBAAS,mBAAmB,MAAM;AAClC,YAAI,WAAW,gBAAgB,WAAW,cAAc;AACtD,mBAAS,MAAM,WAAW,QAAQ,MAAM,UAAU;AAAA,QACpD,OAAO;AACL,mBAAS,MAAM,WAAW,QAAQ,OAAO,MAAM,KAAK;AAAA,QACtD;AAAA,MACF,OAAO;AACL,iBAAS,MAAM,WAAW,QAAQ,MAAM,UAAU;AAAA,MACpD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAlBS;AAuBT,iBAAe,KAAK,KAAU,KAAU,SAAiB,KAAU;AACjE,UAAM,MAAM,IAAI;AAEhB,QAAI,IAAI,WAAW,gCAAgC,GAAG;AACpD,UAAI;AACF,cAAM,MAAM,KAAK,GAAG,IAAI,IAAI;AAC5B,oBAAY,KAAK,MAAM,GAAG;AAAA,MAC5B,SAAS,KAAK;AACZ,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC9C,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAClH,UAAI;AACF,cAAM,OAAO,WAAW,IAAI,IAAI;AAChC,cAAM,MAAM,KAAK,OAAO,OAAO,IAAI,IAAI;AACvC,oBAAY,KAAK,MAAM,GAAG;AAAA,MAC5B,SAAS,KAAK;AACZ,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AACjD,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC3E,UAAI;AACF,cAAM,UAAU,OAAO,GAAG;AAC1B,cAAM,UAAU,mBAAmB,IAAI,QAAQ,QAAQ,IAAI,MAAM,IAAI;AACrE,cAAM,WAAWA,sBAAqB,SAAS,OAAO;AACtD,cAAMJ,YAAW,QAAQ;AACzB,cAAM,UAAU,QAAQ;AACxB,cAAM,UACJ,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,OAAO,IAAI,QAAQ,EAAE;AACjE,cAAMK,IAAG,UAAU,UAAU,SAAS,MAAM;AAC5C,cAAM,UAAU,QAAQ;AACxB,oBAAY,KAAK,UAAU,GAAG;AAAA,MAChC,SAAS,KAAK;AACZ,cAAM,SAAS,UAAU,GAAG;AAC5B,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAAA,EACF;AA9Ce;AAmDf,iBAAe,IAAI,KAAU,KAAU,SAAiB,KAAU;AAChE,UAAM,MAAM,IAAI;AAGhB,QAAI,IAAI,WAAW,iCAAiC,GAAG;AACrD,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAClH,UAAI;AACF,cAAM,KAAK,mBAAmB,IAAI,QAAQ,MAAM,IAAI,MAAM,MAAM,QAAQ;AACxE,YAAI,CAAC,qBAAqB,KAAK,KAAK,kBAAkB,KAAK,MAAM,OAAO,YAAY,OAAO,YAAY,OAAO,QAAQ;AACpH,gBAAM,OAAO,OAAO,QAAQ,QAAQ;AACpC,gBAAM,SAAS,MAAM,kBAAkB,OAAO,EAAE,MAAmB,QAAQ,OAAO,QAAQ,QAAQ,GAAG,CAAC;AACtG,gBAAM,WAAW,uBAAuB,MAAM;AAC9C,cAAI,SAAS,QAAQ;AACnB,kBAAM,QAAQ,SAAS,EAAE,IAAI,SAAS,MAAM;AAC5C,mBAAO,YAAY,KAAK,EAAE,UAAU,WAAW,KAAK,GAAG,GAAG;AAAA,UAC5D;AAAA,QACF;AACA,cAAM,MAAMC,MAAK,QAAQ,OAAO,GAAG,CAAC;AACpC,YAAI,CAAC,KAAK;AACR,gBAAM,QAAQ,oBAAoB;AAClC,iBAAO,SAAS,KAAK,aAAa,GAAG;AAAA,QACvC;AACA,cAAM,QAAQ,GAAG;AACjB,cAAM,QAAQ,MAAMJ,YAAW,GAAG;AAClC,cAAM,QAAQ,GAAG,MAAM,SAAS,MAAM,QAAQ;AAC9C,oBAAY,KAAK,OAAO,GAAG;AAAA,MAC7B,SAAS,KAAK;AACZ,cAAM,SAAS,cAAc,GAAG;AAChC,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AACjD,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAClH,UAAI;AACF,cAAM,KAAK,mBAAmB,IAAI,QAAQ,MAAM,IAAI,MAAM,MAAM,QAAQ;AACxE,cAAM,UAAU,mBAAmB,IAAI,QAAQ,QAAQ,IAAI,MAAM,IAAI;AACrE,YAAI,CAAC,qBAAqB,KAAK,KAAK,kBAAkB,KAAK,MAAM,OAAO,YAAY,OAAO,YAAY,OAAO,QAAQ;AACpH,gBAAMK,QAAO,MAAM,oBAAoB,OAAO,IAAI,OAAO;AACzD,cAAIA,OAAM;AACR,kBAAM,QAAQ,SAAS,EAAE,IAAI,OAAO,EAAE;AACtC,mBAAO,YAAY,KAAKA,OAAM,GAAG;AAAA,UACnC;AAAA,QACF;AACA,cAAM,UAAU,OAAO,GAAG;AAC1B,cAAM,WAAWH,sBAAqB,SAAS,OAAO;AACtD,cAAM,SAAS,MAAMH,YAAW,QAAQ;AACxC,YAAI,CAAC,QAAQ;AACX,gBAAM,QAAQ,QAAQ;AACtB,iBAAO,SAAS,KAAK,aAAa,GAAG;AAAA,QACvC;AACA,cAAM,QAAQ,QAAQ;AACtB,cAAM,OAAO,MAAMI,IAAG,SAAS,UAAU,MAAM;AAC/C,oBAAY,KAAK,MAAM,GAAG;AAAA,MAC5B,SAAS,KAAK;AACZ,cAAM,SAAS,UAAU,GAAG;AAC5B,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AACjD,UAAI,CAAE,MAAM,SAAS,KAAK,OAAO,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC3E,UAAI;AACF,cAAM,UAAU,OAAO,GAAG;AAC1B,cAAM,UAAU,mBAAmB,IAAI,QAAQ,QAAQ,IAAI,MAAM,IAAI;AACrE,cAAM,WAAW,QAAQ,MAAM,OAAO,EAAE,IAAI,KAAK;AACjD,YAAI,kBAAkB,KAAK,GAAG;AAC5B,gBAAM,yBAAyB,OAAO,QAAQ,EAAE,MAAM,MAAM,MAAS;AAAA,QACvE;AACA,cAAM,WAAWD,sBAAqB,SAAS,OAAO;AACtD,cAAM,UAAU,QAAQ;AACxB,cAAMD,YAAW,QAAQ;AACzB,cAAM,UAAU,YAAY;AAC5B,oBAAY,KAAK,UAAU,GAAG;AAAA,MAChC,SAAS,KAAK;AACZ,cAAM,SAAS,UAAU,GAAG;AAC5B,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AACA;AAAA,IACF;AAAA,EACF;AApFe;AAsFf,SAAO,EAAE,MAAM,IAAI;AACrB,GAlLe;;;ACZR,SAAS,cAAc,OAAqB;AAClD,QAAM,MAAM,OAAO,YAAY,QAAQ;AACvC,SAAO,CAAC,EAAE,KAAK,WAAW,aAAa,KAAK;AAC7C;AAHgB;AAKT,SAAS,aAAa,OAAoB;AAChD,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,EAAG,QAAO,QAAQ,KAAK;AACvE,QAAM,UAAU,OAAO,YAAY,QAAQ,MAAM;AACjD,SAAO,OAAO,YAAY,WAAW,QAAQ,KAAK,IAAI;AACvD;AALgB;AAOT,SAAS,iBAAiB,OAAY,KAAmB;AAC/D,MAAI,CAAC,cAAc,KAAK,EAAG,QAAO;AAClC,QAAM,WAAW,aAAa,KAAK;AACnC,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,SAAS,KAAK,UAAU,cAAc,KAAK,KAAK,UAAU,WAAW;AAC3E,MAAI,OAAO,WAAW,YAAY,WAAW,SAAU,QAAO;AAC9D,QAAM,IAAI,KAAK,SAAS,CAAC;AACzB,QAAM,SAAS,EAAE,cAAc,EAAE;AACjC,SAAO,OAAO,WAAW,YAAY,WAAW;AACjD;AATgB;AAchB,eAAsB,oBAAoB,KAAU,OAAY,QAAQ,GAA2B;AAClG,MAAI,iBAAiB,OAAO,GAAG,EAAG,QAAO;AACzC,QAAM,sBAAsB,KAAK,KAAK;AACtC,SAAO,oBAAoB,GAAG,KAAK,QAAQ,SAAS;AACrD;AAJsB;AAMtB,eAAsB,qBAAqB,KAAU,OAAY,OAAiC;AACjG,MAAI,iBAAiB,OAAO,GAAG,EAAG,QAAO;AACzC,QAAM,sBAAsB,KAAK,KAAK;AACtC,SAAO,oBAAoB,GAAG,KAAK;AACpC;AAJsB;;;ACtBtB,SAAS,MAAM,KAA2B;AACxC,SAAO,QAAQ,SAAS,SAAS;AACnC;AAFS;AAIT,eAAe,iBAAiB,KAAU,OAA2B;AACnE,MAAI,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,SAAS,CAAC,GAAG;AACnD,UAAM,sBAAsB,KAAK,KAAK;AAAA,EACxC;AACF;AAJe;AAMf,IAAO,0BAAQ,wBAAC,UAAe;AAC7B,QAAM,EAAE,aAAa,SAAS,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AACnE,QAAM,KAAK,MAAM,KAAK;AAEtB,iBAAe,IAAI,KAAU,KAAU,SAAiB,KAAU;AAChE,UAAM,MAAM,IAAI,OAAO;AAEvB,QAAI,IAAI,WAAW,uCAAuC,GAAG;AAC3D,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACF,cAAM,KAAK,MAAM,IAAI,QAAQ,MAAM,IAAI,MAAM,EAAE;AAC/C,YAAI,OAAO,MAAM,GAAG,sBAAsB,OAAO,EAAE;AACnD,YAAI,kBAAkB,KAAK,KAAK,CAAC,qBAAqB,KAAK,GAAG;AAC5D,gBAAM,SAAS,MAAM,kBAAkB,OAAO,EAAE,MAAM,gBAAgB,GAAG,CAAC;AAC1E,gBAAM,YAAY,0BAA0B,QAAQ,EAAE;AACtD,gBAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,MAAW,EAAE,IAAI,CAAC;AAClD,qBAAW,KAAK,WAAW;AACzB,gBAAI,CAAC,MAAM,IAAI,EAAE,IAAI,EAAG,MAAK,KAAK,CAAC;AAAA,UACrC;AAAA,QACF;AACA,eAAO,YAAY,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG,GAAG;AAAA,MAClD,SAAS,KAAU;AACjB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC/C;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,mCAAmC,GAAG;AACvD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACF,cAAM,OAAO,mBAAmB,IAAI,QAAQ,QAAQ,IAAI,MAAM,QAAQ,EAAE;AACxE,cAAM,KAAK,MAAM,IAAI,QAAQ,MAAM,IAAI,MAAM,EAAE;AAC/C,YAAI,CAAC,KAAM,QAAO,SAAS,KAAK,iBAAiB,GAAG;AACpD,cAAM,UAAU,MAAM,GAAG,qBAAqB,OAAO,MAAM,EAAE;AAC7D,eAAO,YAAY,KAAK,EAAE,IAAI,GAAG,QAAQ,GAAG,GAAG;AAAA,MACjD,SAAS,KAAU;AACjB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC/C;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,kCAAkC,GAAG;AACtD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACF,eAAO,YAAY,KAAK,GAAG,wBAAwB,KAAK,GAAG,GAAG;AAAA,MAChE,SAAS,KAAU;AACjB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AA3Ce;AA6Cf,iBAAe,KAAK,KAAU,KAAU,SAAiB,KAAU;AACjE,UAAM,MAAM,IAAI,OAAO;AAEvB,QAAI,IAAI,WAAW,mCAAmC,GAAG;AACvD,UAAI,CAAE,MAAM,qBAAqB,KAAK,OAAO,uBAAuB,OAAO,YAAY,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AACjI,YAAM,iBAAiB,KAAK,KAAK;AACjC,YAAM,KAAK,oBAAoB,GAAG;AAClC,YAAM,KAAK,mBAAmB,GAAG;AACjC,UAAI;AACF,cAAM,OAAO,OAAO,IAAI,SAAS,WAAW,KAAK,MAAM,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,CAAC;AACxF,cAAM,OAAO,OAAO,KAAK,QAAQ,EAAE;AACnC,cAAM,KAAK,MAAM,KAAK,EAAE;AACxB,YAAI,CAAC,KAAM,QAAO,SAAS,KAAK,iBAAiB,GAAG;AACpD,cAAM,SAAS,MAAM,GAAG;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA,YACE,IAAI,KAAK,OAAO,EAAE,IAAI;AAAA,YACtB;AAAA,YACA,QAAQ,KAAK,SAAS,OAAO,KAAK,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI;AAAA,YAC1D,OAAO,CAAC,CAAC,KAAK;AAAA,UAChB;AAAA,UACA;AAAA,QACF;AACA,eAAO,YAAY,KAAK,EAAE,IAAI,GAAG,OAAO,GAAG,GAAG;AAAA,MAChD,SAAS,KAAU;AACjB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AA7Be;AA+Bf,SAAO,EAAE,KAAK,KAAK;AACrB,GAjFe;;;ACHf,SAAS,WAAW,KAAkC;AACrD,QAAM,IAAI,IAAI,UAAU,IAAI,QAAQ,CAAC;AACrC,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,CAAC,GAAG;AACvC,QAAI,KAAK,QAAQ,MAAM,GAAI,KAAI,CAAC,IAAI,OAAO,CAAC;AAAA,EAC7C;AACA,SAAO;AACR;AAPS;AAST,SAAS,UAAU,KAAmC;AACrD,MAAI,CAAC,KAAK,KAAM,QAAO,CAAC;AACxB,MAAI,OAAO,IAAI,SAAS,UAAU;AACjC,QAAI;AAAE,aAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IAAG,QAAQ;AAAE,aAAO,CAAC;AAAA,IAAG;AAAA,EACzD;AACA,SAAO,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,CAAC;AACnD;AANS;AAQT,IAAO,qBAAQ,wBAAC,UAAe;AAC9B,QAAM,EAAE,aAAa,SAAS,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AACnE,QAAM,KAAK,MAAM,KAAK;AAEtB,iBAAe,IAAI,KAAU,KAAU,SAAiB,KAAU;AACjE,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,IAAI,WAAW,GAAG;AAExB,QAAI,IAAI,WAAW,4BAA4B,GAAG;AACjD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,eAAO,YAAY,KAAK,gBAAgB,KAAK,GAAG,GAAG;AAAA,MACpD,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,2BAA2B,GAAG;AAChD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI,CAAC,kBAAkB,KAAK,GAAG;AAC9B,eAAO,YAAY,KAAK,EAAE,OAAO,YAAY,SAAS,+BAA+B,QAAQ,gBAAgB,KAAK,EAAE,GAAG,GAAG;AAAA,MAC3H;AACA,UAAI;AACH,cAAM,YAAY,sBAAsB,KAAK;AAC7C,cAAM,QAAQ,MAAM,gBAAgB,KAAK;AACzC,eAAO,YAAY,KAAK,EAAE,OAAO,WAAW,OAAO,QAAQ,gBAAgB,KAAK,EAAE,GAAG,GAAG;AAAA,MACzF,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,gCAAgC,GAAG;AACrD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,cAAM,KAAK,EAAE,OAAO,SAAS,SAAS;AACtC,cAAM,SAAS,MAAM,oBAAoB,OAAO,EAAE;AAClD,eAAO,YAAY,KAAK,QAAQ,GAAG;AAAA,MACpC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,4BAA4B,GAAG;AACjD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI,CAAC,kBAAkB,KAAK,EAAG,QAAO,SAAS,KAAK,yBAAyB,GAAG;AAChF,UAAI;AACH,cAAM,SAAS,MAAM,kBAAkB,OAAO;AAAA,UAC7C,MAAM,EAAE,OAAQ,EAAE,OAAmB;AAAA,UACrC,IAAI,EAAE,KAAM,EAAE,KAA8B;AAAA,UAC5C,QAAQ,EAAE,UAAU,EAAE,MAAM;AAAA,UAC5B,SAAS,EAAE,WAAW,EAAE,KAAK;AAAA,UAC7B,YAAY,EAAE,cAAc;AAAA,UAC5B,cAAc,EAAE,gBAAgB,OAAO,OAAO,EAAE,YAAY,IAAI;AAAA,UAChE,WAAW,EAAE,aAAa;AAAA,UAC1B,SAAS,EAAE,WAAW;AAAA,UACtB,SAAS,EAAE,WAAW;AAAA,UACtB,OAAO,EAAE,SAAS,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,UAC3C,QAAQ,EAAE,UAAU,OAAO,OAAO,EAAE,MAAM,IAAI;AAAA,QAC/C,CAAC;AACD,eAAO,YAAY,KAAK,QAAQ,GAAG;AAAA,MACpC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,4BAA4B,GAAG;AACjD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,cAAM,OAAQ,EAAE,QAAQ;AACxB,cAAM,SAAU,EAAE,UAAU;AAC5B,cAAM,WAAW,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,EAAE;AAC1D,cAAM,KAAK,EAAE,OAAO,SAAS,SAAS;AACtC,cAAM,SAAS,EAAE,UAAU,EAAE,MAAM;AACnC,YAAI,CAAC,YAAY,SAAS,eAAgB,QAAO,SAAS,KAAK,iBAAiB,GAAG;AACnF,cAAM,UAAU,MAAM,iBAAiB,OAAO;AAAA,UAC7C;AAAA,UACA,IAAI,SAAS,iBAAiB,KAAK;AAAA,UACnC,UAAU,YAAY;AAAA,UACtB;AAAA,UACA;AAAA,QACD,CAAC;AACD,eAAO,YAAY,KAAK,SAAS,GAAG;AAAA,MACrC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,8BAA8B,GAAG;AACnD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,eAAO,YAAY,KAAK,GAAG,wBAAwB,KAAK,GAAG,GAAG;AAAA,MAC/D,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AAClD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI;AACH,cAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,8BAA8B;AAC5E,eAAO,YAAY,KAAK,qBAAqB,KAAK,GAAG,GAAG;AAAA,MACzD,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,gCAAgC,GAAG;AACrD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI,CAAC,kBAAkB,KAAK,EAAG,QAAO,SAAS,KAAK,yBAAyB,GAAG;AAChF,UAAI;AACH,cAAM,OAAO,EAAE,OAAO,OAAO,EAAE,IAAI,IAAI;AACvC,cAAM,KAAK,EAAE,KAAK,OAAO,EAAE,EAAE,IAAI;AACjC,cAAM,SAAS,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI;AAC7D,cAAM,SAAS,MAAM,kBAAkB,OAAO,EAAE,MAAmB,IAAI,OAAO,CAAC;AAC/E,YAAI,SAAS,kBAAkB,IAAI;AAClC,iBAAO,YAAY,KAAK,EAAE,OAAO,0BAA0B,QAAQ,MAAM,MAAM,GAAG,IAAI,MAAM,OAAO,GAAG,GAAG;AAAA,QAC1G;AACA,YAAI,SAAS,SAAS,SAAS,SAAS,SAAS,YAAY,QAAQ;AACpE,gBAAM,WAAW,SAAS,WACvB,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,IAAI,CAAC,OAAO;AAAA,YACvD,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,YAAY,EAAE;AAAA,YACd,QAAQ,EAAE;AAAA,YACV,WAAW;AAAA,UACZ,EAAE,IACA,uBAAuB,MAAM;AAChC,iBAAO,YAAY,KAAK,EAAE,UAAU,OAAO,GAAG,GAAG;AAAA,QAClD;AACA,eAAO,YAAY,KAAK,EAAE,OAAO,GAAG,GAAG;AAAA,MACxC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,4BAA4B,GAAG;AACjD,UAAI,CAAE,MAAM,oBAAoB,KAAK,OAAO,uBAAuB,OAAO,SAAS,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AAC7H,UAAI,CAAC,kBAAkB,KAAK,EAAG,QAAO,SAAS,KAAK,yBAAyB,GAAG;AAChF,UAAI;AACH,cAAM,KAAK,EAAE;AACb,YAAI,MAAM,MAAM;AACf,gBAAM,MAAM,MAAM,gBAAgB,OAAO,EAAE;AAC3C,cAAI,CAAC,IAAK,QAAO,SAAS,KAAK,aAAa,GAAG;AAC/C,iBAAO,YAAY,KAAK,EAAE,OAAO,IAAI,GAAG,GAAG;AAAA,QAC5C;AACA,cAAM,OAAO,OAAO,EAAE,QAAQ,EAAE;AAChC,cAAM,WAAW,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,EAAE;AAC1D,cAAM,KAAK,EAAE,KAAK,OAAO,EAAE,EAAE,IAAI;AACjC,cAAM,SAAS,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI;AAE7D,YAAI,SAAS,SAAS,SAAS,SAAU,CAAC,QAAQ,SAAS,WAAW,MAAM,GAAI;AAC/E,gBAAM,UAAU,MAAM,oBAAoB,OAAO,QAAQ,QAAQ;AACjE,iBAAO,YAAY,KAAK,SAAS,GAAG;AAAA,QACrC;AAEA,YAAI,SAAS,kBAAkB,SAAS,SAAS,UAAU,GAAG;AAC7D,gBAAM,UAAU,MAAM,GAAG,qBAAqB,OAAO,UAAU,OAAO,SAAS,SAAS,MAAM;AAC9F,iBAAO,YAAY,KAAK,EAAE,IAAI,MAAM,QAAQ,GAAG,SAAS,WAAW,KAAK,GAAG,GAAG;AAAA,QAC/E;AAEA,cAAM,OAAO,MAAM,iBAAiB,OAAO;AAAA,UAC1C;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,OAAO,OAAO,EAAE,KAAK,KAAK;AAAA,QAC3B,CAAC;AACD,eAAO,YAAY,KAAK,EAAE,SAAS,KAAK,GAAG,GAAG;AAAA,MAC/C,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAAA,EACD;AAzKe;AA2Kf,iBAAe,KAAK,KAAU,KAAU,SAAiB,KAAU;AAClE,UAAM,MAAM,IAAI,OAAO;AACvB,QAAI,CAAC,IAAI,WAAW,6BAA6B,EAAG;AACpD,QAAI,CAAE,MAAM,qBAAqB,KAAK,OAAO,uBAAuB,OAAO,YAAY,CAAC,EAAI,QAAO,SAAS,KAAK,aAAa,GAAG;AACjI,QAAI;AACH,YAAM,OAAO,UAAU,GAAG;AAC1B,YAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,UAAI,CAAC,QAAQ,OAAO,OAAQ,OAAO,KAAM,QAAO,SAAS,KAAK,gBAAgB,GAAG;AACjF,YAAM,KAAK,KAAK,OAAO,SAAS,SAAS;AACzC,YAAM,SAAS,MAAM,wBAAwB,OAAO;AAAA,QACnD;AAAA,QACA;AAAA,QACA,QAAQ,CAAC,CAAC,KAAK;AAAA,QACf,UAAU,mBAAmB,GAAG;AAAA,MACjC,CAAC;AACD,aAAO,YAAY,KAAK,QAAQ,GAAG;AAAA,IACpC,SAAS,KAAU;AAClB,aAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,IAC9C;AAAA,EACD;AAnBe;AAqBf,SAAO,EAAE,KAAK,KAAK;AACpB,GArMe;;;ACvCf,YAAYK,SAAQ;AACpB,YAAYC,eAAc;AAiB1B,IAAI,WAAkC;AAEtC,SAAS,gBAAgB,OAAoB;AAC3C,QAAM,OAAO,OAAO,cAAc,QAAQ,IAAI;AAC9C,SAAgB,eAAK,MAAM,4BAA4B;AACzD;AAHS;AAKF,SAAS,eAAe,OAA4B;AACzD,MAAI,SAAU,QAAO;AACrB,QAAM,WAAW,gBAAgB,KAAK;AACtC,MAAI;AACF,UAAM,MAAS,iBAAa,UAAU,MAAM;AAC5C,eAAW,KAAK,MAAM,GAAG;AAAA,EAC3B,QAAQ;AACN,eAAW,EAAE,SAAS,KAAK,QAAQ,CAAC,EAAE;AAAA,EACxC;AACA,MAAI,MAAO,OAAM,aAAa;AAC9B,SAAO;AACT;AAXgB;AAaT,SAAS,SAAS,IAAmC;AAC1D,SAAO,UAAU,SAAS,EAAE,KAAK;AACnC;AAFgB;AAIT,SAAS,SAAS,IAAqB;AAC5C,SAAO,CAAC,CAAC,SAAS,EAAE;AACtB;AAFgB;AAIT,SAAS,SAAS,OAAY,IAAY,QAAyB;AACxE,QAAM,QAAQ,SAAS,EAAE;AACzB,QAAM,QAAQ,OAAO,QAAQ,QAAQ;AACrC,MAAI,OAAO;AACT,UAAM,OAAO,EAAE,KAAK,MAAM,MAAM,IAAI,MAAM,UAAU,IAAI,QAAQ,SAAS,SAAS,EAAE;AAAA,EACtF,OAAO;AACL,UAAM,OAAO,EAAE,KAAK,kBAAkB,QAAQ,SAAS,SAAS,EAAE;AAAA,EACpE;AACF;AARgB;AAUT,SAAS,oBAAoB,KAA6D;AAC/F,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,UAAM,IAAI;AACV,QAAI,OAAO,EAAE,OAAO,UAAU;AAC5B,YAAM,KAAK,MAAM,QAAQ,EAAE,EAAE,IACzB,EAAE,GAAG,IAAI,MAAM,IACf,EAAE,MAAM,OACN,CAAC,OAAO,EAAE,EAAE,CAAC,IACb;AACN,aAAO,EAAE,IAAI,EAAE,IAAI,GAAG;AAAA,IACxB;AAAA,EACF;AACA,MAAI,OAAO,QAAQ,YAAY,SAAS,GAAG,GAAG;AAC5C,WAAO,EAAE,IAAI,IAAI;AAAA,EACnB;AACA,SAAO,EAAE,KAAK,IAAI;AACpB;AAhBgB;AAkBhB,IAAO,oBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC7EA,IAAO,qBAAQ,wBAAC,UAAe;AAC9B,QAAM,EAAE,aAAa,SAAS,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AAEnE,WAAS,IAAI,KAAU,KAAU,UAAkB,KAAU;AAC5D,UAAM,MAAM,IAAI,OAAO;AACvB,QAAI,IAAI,WAAW,sBAAsB,GAAG;AAC3C,UAAI;AACH,eAAO,YAAY,KAAK,eAAe,KAAK,GAAG,GAAG;AAAA,MACnD,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAAA,EACD;AATS;AAWT,SAAO,EAAE,IAAI;AACd,GAfe;;;ACHf,IAAO,uBAAQ,wBAAC,UAAe;AAC7B,QAAM,EAAE,aAAa,UAAU,MAAM,IAAI,OAAO,MAAM,UAAU,KAAK,KAAK,CAAC;AAC3E,WAAS,SAAS,KAAY;AAC5B,YAAQ,UAAU,GAAG,GAAG;AAAA,EAC1B;AAFS;AAIT,SAAO,MAAM,KAAK,KAAK,OAAO;AAAA,IAC5B,MAAM;AAAA,IACN,KAAK;AAAA,MACH,UAAU;AAAA,MACV,QAAQ;AAAA,IACV;AAAA,IACA,OAAO;AAAA,MACL,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM,CAAC,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,OAAO;AAAA,IAC1G;AAAA,IACA,MAAM,8BAAO,KAAU,KAAU,SAAiB,KAAU,gBAAqB;AAC/E,UAAI,IAAI,IAAI,WAAW,6BAA6B,GAAG;AACrD,YAAI;AACF,gBAAM,QAAQ,0BAA0B;AACxC,wBAAc,KAAK,EAAE,MAAM,OAAO,GAAG,GAAG;AAAA,QAC1C,SAAS,KAAK;AACZ,gBAAM,SAAS,gBAAgB,GAAG;AAAA,QACpC;AACA,eAAO;AAAA,MACT;AAAA,IACF,GAVM;AAAA,IAWN,KAAK,8BAAO,KAAU,KAAU,SAAiB,KAAU,eAAoB;AAC7E,UAAI,IAAI,IAAI,WAAW,4BAA4B,GAAG;AACpD,YAAI;AACF,gBAAM,UAAe,IAAI;AACzB,gBAAM,UAAU,QAAQ,KAAK;AAC7B,gBAAM,QAAQ,MAAM,WAAW,MAAM;AAAA,YACnC,MAAM;AAAA,YACN,OAAO,QAAQ;AAAA,UACjB,CAAC;AACD,gBAAM,UAAU,WAAW;AAC3B,wBAAc,KAAK,OAAO,GAAG;AAAA,QAC/B,SAAS,OAAO;AACd,gBAAM,SAAS,UAAU,KAAK;AAC9B,qBAAW,KAAK,OAAO,GAAG;AAAA,QAC5B;AACA,eAAO;AAAA,MACT;AAAA,IACF,GAjBK;AAAA,EAkBP,CAAC;AACH,GA/Ce;;;ACGf,OAAOC,SAAQ;AAEf,SAAS,SAAS,MAAc,OAAwB,QAAyC;AAChG,QAAM,MAAM,SACT,IAAI,OAAO,QAAQ,MAAM,EACxB,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,OAAO,CAAC,EAAE,QAAQ,MAAM,KAAK,CAAC,GAAG,EAC1D,KAAK,GAAG,CAAC,MACV;AACH,SAAO,GAAG,IAAI,GAAG,GAAG,IAAI,KAAK;AAC9B;AAPS;AAST,IAAO,iBAAQ,wBAAC,UAAe;AAC9B,QAAM,EAAE,aAAa,SAAS,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AAEnE,iBAAe,IAAI,KAAU,KAAU,UAAkB,KAAU;AAClE,UAAM,MAAM,IAAI,OAAO;AAEvB,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC/C,UAAI;AACH,cAAM,MAAM,QAAQ,YAAY;AAChC,YAAI,YAAY;AAChB,YAAI,UAAU;AACd,mBAAW,OAAO,OAAO,OAAO,MAAM,mBAAmB,CAAC,CAAC,GAAG;AAC7D,uBAAc,KAAsB,QAAQ;AAAA,QAC7C;AACA,mBAAW,OAAO,OAAO,OAAO,MAAM,iBAAiB,CAAC,CAAC,GAAG;AAC3D,qBAAY,KAAsB,QAAQ;AAAA,QAC3C;AACA,cAAM,QAAQ;AAAA,UACb;AAAA,UACA;AAAA,UACA,SAAS,uBAAuB,KAAK,MAAM,QAAQ,OAAO,CAAC,CAAC;AAAA,UAC5D;AAAA,UACA;AAAA,UACA,SAAS,yBAAyB,IAAI,GAAG;AAAA,UACzC;AAAA,UACA;AAAA,UACA,SAAS,yBAAyB,SAAS;AAAA,UAC3C;AAAA,UACA;AAAA,UACA,SAAS,uBAAuB,OAAO;AAAA,UACvC;AAAA,UACA;AAAA,UACA,SAAS,mBAAmBC,IAAG,QAAQ,EAAE,CAAC,KAAK,CAAC;AAAA,QACjD;AACA,YAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,eAAO,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,MACvC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,yBAAyB,GAAG;AAC9C,aAAO;AAAA,QACN;AAAA,QACA;AAAA,UACC,QAAQ,QAAQ,OAAO;AAAA,UACvB,MAAM,QAAQ;AAAA,UACd,UAAU,QAAQ;AAAA,UAClB,QAAQ,QAAQ,YAAY;AAAA,UAC5B,OAAO;AAAA,YACN,MAAM,OAAO;AAAA,cACZ,OAAO,QAAQ,MAAM,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAI,GAAoB,QAAQ,CAAC,CAAC;AAAA,YAChG;AAAA,YACA,IAAI,OAAO;AAAA,cACV,OAAO,QAAQ,MAAM,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAI,GAAoB,QAAQ,CAAC,CAAC;AAAA,YAC9F;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,EACD;AA1De;AA4Df,SAAO,EAAE,IAAI;AACd,GAhEe;;;ACTf,SAAS,gBAAgB,OAAwB;AAChD,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,UAAM,IAAI,MAAM,WAAW,CAAC;AAC5B,QAAI,MAAM,IAAM,QAAO;AACvB,QAAI,KAAK,MAAQ,MAAM,KAAQ,MAAM,MAAQ,MAAM,GAAM,QAAO;AAAA,EACjE;AACA,SAAO;AACR;AAPS;AASF,SAAS,mBAAmB,OAAe,QAAQ,SAAiB;AAC1E,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,gBAAgB,KAAK,GAAG;AAC3B,UAAM,IAAI,MAAM,WAAW,KAAK,kCAAkC;AAAA,EACnE;AACA,SAAO;AACR;AANgB;AAQT,SAAS,eAAe,OAAgB,SAAS,MAAc;AACrE,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,MAAM,OAAO,KAAK;AACxB,qBAAmB,GAAG;AACtB,SAAO,IAAI,SAAS,SAAS,IAAI,MAAM,GAAG,MAAM,IAAI;AACrD;AALgB;;;ACtBhB,SAAS,YAAY,WAAW,kBAAkB;AAa3C,SAAS,gBAAgB,OAAoB;AACnD,QAAM,QAAQ,OAAO,YAAY,UAAU,mBAAmB;AAC9D,SAAO,OAAO,KAAK,IAAI,OAAO;AAC/B;AAHgB;AAKhB,IAAM,eAAe;AAQrB,SAAS,eAAe,SAAS,IAAY;AAC5C,QAAM,MAAM,aAAa,MAAM,EAAE;AACjC,WAAS,IAAI,IAAI,SAAS,GAAG,IAAI,GAAG,KAAK;AACxC,UAAM,IAAI,UAAU,IAAI,CAAC;AACzB,KAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AAAA,EACnC;AACA,SAAO,IAAI,MAAM,GAAG,KAAK,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE;AAC1D;AAPS;AASF,SAAS,kBAAkB,OAA6D;AAC9F,QAAM,YAAY,WAAW;AAC7B,QAAM,MAAM,eAAe;AAC3B,QAAM,KAAK,OAAO,YAAY;AAC9B,MAAI,CAAC,GAAI,OAAM,IAAI,MAAM,0CAA2B;AAIpD,QAAM,MAAM,MAAM,KAAK,OAAO,SAAS,KAAK,EAAE;AAC9C,SAAO,EAAE,KAAK,KAAK,UAAU;AAC9B;AAVgB;AAgBT,SAAS,mBAAmB,OAAY,IAAY,IAA2B;AACrF,QAAM,EAAE,KAAK,KAAK,UAAU,IAAI,kBAAkB,KAAK;AACvD,QAAM,MAAM,KAAK,IAAI;AACrB,SAAO;AAAA,IACN,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,WAAW,MAAM,gBAAgB,KAAK;AAAA,IACtC,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,EACD;AACD;AAbgB;;;AChDhB,IAAM,qBAAqB,CAAC,wBAAwB;AAE7C,SAAS,sBAAsB,UAAkB,OAAqB;AAC5E,MAAI,mBAAmB,KAAK,CAAC,MAAM,SAAS,WAAW,CAAC,CAAC,GAAG;AAC3D,QACC,SAAS,SAAS,eAAe,KACjC,SAAS,SAAS,aAAa,KAC/B,SAAS,SAAS,eAAe,KACjC,SAAS,SAAS,kBAAkB,GACnC;AACD,aAAO,QAAQ,uBAAuB,OAAO,YAAY,IAAI,QAAQ;AAAA,IACtE;AACA,WAAO,QAAQ,uBAAuB,OAAO,WAAW,IAAI,QAAQ;AAAA,EACrE;AACA,SAAO;AACR;AAbgB;AAeT,SAAS,SAAS,WAAmB,UAA2B;AACtE,SAAO,OAAO,SAAS,SAAS,KAAK,aAAa;AACnD;AAFgB;;;ACnBT,SAAS,cAAc,MAAwC;AACrE,SACC,OAAO,KAAK,SAAS,YACrB,OAAO,KAAK,OAAO,YACnB,OAAO,KAAK,SAAS,YACrB,KAAK,OAAO,QACZ,KAAK,MAAM,QACX,KAAK,QAAQ,QACb,KAAK,YAAY;AAEnB;AAVgB;AAYhB,SAAS,iBAAiB,OAAyB;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,OAAO,MAAM,KAAK;AACxB,MAAI,CAAC,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO;AAC3D,MAAI;AACH,WAAO,KAAK,MAAM,IAAI;AAAA,EACvB,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AATS;AAWF,SAAS,cAAc,KAAkD;AAC/E,MAAI,MAAM,KAAK;AACf,MAAI,OAAO,QAAQ,QAAQ,GAAI,QAAO,CAAC;AACvC,MAAI,OAAO,QAAQ,UAAU;AAC5B,UAAM,OAAO,IAAI,KAAK;AACtB,QAAI,CAAC,KAAM,QAAO,CAAC;AACnB,QAAI;AACH,YAAM,KAAK,MAAM,IAAI;AAAA,IACtB,QAAQ;AACP,UAAI,KAAK,SAAS,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,GAAG;AACzE,cAAM,OAAO,YAAY,IAAI,gBAAgB,IAAI,CAAC;AAAA,MACnD,OAAO;AACN,eAAO,CAAC;AAAA,MACT;AAAA,IACD;AAEA,UAAM,iBAAiB,GAAG;AAAA,EAC3B;AACA,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,EAAG,QAAO,CAAC;AACnE,QAAM,OAAO;AACb,MAAI,cAAc,IAAI,EAAG,QAAO,CAAC;AACjC,SAAO;AACR;AAtBgB;AAwBT,SAAS,cAAc,SAAkC,MAAwB;AACvF,aAAW,OAAO,MAAM;AACvB,UAAM,MAAM,KAAK,GAAG;AACpB,QAAI,OAAO,QAAQ,OAAO,GAAG,EAAE,SAAS,EAAG,QAAO,OAAO,GAAG;AAAA,EAC7D;AACA,SAAO;AACR;AANgB;;;AC5CT,SAAS,sBACf,OACA,SACA,aACkB;AAClB,QAAM,cAAc,IAAI,IAAI,kBAAkB,OAAO,OAAO,CAAC;AAC7D,MAAI,CAAC,YAAY,KAAM,QAAO,CAAC;AAE/B,QAAM,SAAS,oBAAI,IAA2B;AAC9C,aAAW,KAAK,aAAa;AAC5B,QAAI,CAAC,YAAY,IAAI,EAAE,EAAE,EAAG;AAC5B,UAAM,OAAO,OAAO,IAAI,EAAE,EAAE;AAC5B,UAAM,QAAQ,EAAE,kBAAkB,EAAE;AACpC,UAAM,WAAW,OAAQ,KAAK,kBAAkB,KAAK,YAAa;AAClE,QAAI,CAAC,QAAQ,QAAQ,SAAU,QAAO,IAAI,EAAE,IAAI,CAAC;AAAA,EAClD;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AACrE;AAjBgB;AAmBT,SAAS,oBAAoB,OAAY,IAAY,SAA0B;AACrF,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,iBAAiB,OAAO,IAAI,OAAO;AAC3C;AAHgB;AAMhB,eAAsB,oBACrB,OACA,SACA,OACkB;AAClB,QAAM,MAAM,MAAM,MAAM,YAAY;AACpC,SAAO,sBAAsB,OAAO,SAAS,GAAG,EAAE;AACnD;AAPsB;AAUtB,eAAsB,0BACrB,OACA,SACA,OACA,IACkB;AAClB,QAAM,MAAM,MAAM,MAAM,YAAY;AACpC,SAAO,sBAAsB,OAAO,SAAS,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;AAC9E;AARsB;AAWtB,eAAsB,qBACrB,OACA,SACA,OACkB;AAClB,QAAM,cAAc,IAAI,IAAI,kBAAkB,OAAO,OAAO,CAAC;AAC7D,QAAM,MAAM,MAAM,MAAM,YAAY;AACpC,MAAI,SAAS;AACb,aAAW,KAAK,KAAK;AACpB,QAAI,YAAY,IAAI,EAAE,EAAE,EAAG;AAC3B,UAAM,MAAM,cAAc,EAAE,EAAE;AAC9B,cAAU;AAAA,EACX;AACA,SAAO;AACR;AAdsB;;;ACPtB,SAAS,YAAY,OAAY;AAChC,SAAO,OAAO,YAAY,YAAY,CAAC;AACxC;AAFS;AAIT,SAASC,UAAS,OAAY;AAC7B,QAAM,MAAM,YAAY,KAAK;AAC7B,SAAO,IAAI,SAAS,CAAC;AACtB;AAHS,OAAAA,WAAA;AAKT,eAAe,SACd,OACA,IACA,SAC6C;AAC7C,QAAM,QAAQA,UAAS,KAAK;AAC5B,MAAI,CAAC,MAAM,QAAS,QAAO,EAAE,IAAI,KAAK;AAEtC,QAAM,QAAQ,gBAAgB,KAAK;AACnC,QAAM,QAAQ,MAAM,oBAAoB,OAAO,SAAS,KAAK;AAC7D,QAAM,WAAW,MAAM,oBAAoB,OAAO,YAAY,OAAO,SAAS,aAAa;AAC3F,MAAI,SAAS,UAAU;AACtB,WAAO,EAAE,IAAI,OAAO,SAAS,mBAAmB;AAAA,EACjD;AAEA,QAAM,UAAU,MAAM,0BAA0B,OAAO,SAAS,OAAO,EAAE;AACzE,QAAM,aAAa,MAAM,sBAAsB;AAC/C,MAAI,WAAW,YAAY;AAC1B,WAAO,EAAE,IAAI,OAAO,SAAS,qBAAqB;AAAA,EACnD;AACA,SAAO,EAAE,IAAI,KAAK;AACnB;AArBe;AAuBf,SAAS,WAAW,OAAY,MAAW;AAC1C,QAAM,OAAO,KAAK,QAAQ,oBAAoB,OAAO,KAAK,EAAE,EAAE;AAC9D,SAAO;AAAA,IACN,IAAI,KAAK;AAAA,IACT,IAAI,KAAK;AAAA,IACT;AAAA,IACA,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,oBAAoB,CAAC,CAAC,KAAK;AAAA,EAC5B;AACD;AAVS;AAYT,IAAI,mBAAyC;AAE7C,SAAS,YAAY,OAA2B;AAC/C,MAAI,CAAC,kBAAkB;AACtB,uBAAmB,QAAQ,IAAI,CAAC,qBAAqB,KAAK,GAAG,oBAAoB,KAAK,CAAC,CAAC,EAAE,KAAK,MAAM,MAAS;AAAA,EAC/G;AACA,SAAO;AACR;AALS;AAOT,IAAO,gBAAQ,wBAAC,UAAe;AAC9B,QAAM,EAAE,aAAa,UAAU,QAAQ,IAAI,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC;AAC5E,QAAM,QAAQ,gBAAgB,KAAK;AAEnC,iBAAe,WAAW,KAAU,UAAkB,aAAwC;AAC7F,UAAM,sBAAsB,KAAK,KAAK;AACtC,UAAM,QAAQ,eAAe,sBAAsB,UAAU,KAAK;AAClE,WAAO,SAAS,oBAAoB,GAAG,GAAG,KAAK;AAAA,EAChD;AAJe;AAMf,iBAAe,KAAK,KAAU,KAAU,SAAiB,KAAU;AAClE,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,KAAK,YAAY,GAAG;AAC1B,UAAM,OAAO,cAAc,GAAG;AAE9B,QAAI,IAAI,WAAW,6BAA6B,GAAG;AAClD,YAAM,YAAY,KAAK;AACvB,UAAI;AACH,cAAM,KAAK,eAAe,cAAc,MAAM,MAAM,UAAU,GAAG,EAAE;AACnE,cAAM,OAAO,eAAe,cAAc,MAAM,QAAQ,YAAY,KAAK,GAAG,GAAG;AAC/E,cAAM,UAAU,eAAe,cAAc,MAAM,WAAW,eAAe,SAAS,GAAG,GAAG;AAC5F,YAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAS,QAAO,QAAQ,KAAK,6BAA6B,QAAW,GAAG;AAE7F,cAAM,OAAO,MAAM,MAAM,eAAe,EAAE;AAC1C,YAAI,CAAC,QAAQ,CAAC,eAAe,MAAM,KAAK,UAAU,KAAK,QAAQ,GAAG;AACjE,iBAAO,QAAQ,KAAK,4BAA4B,QAAW,GAAG;AAAA,QAC/D;AAEA,cAAM,SAAS,kBAAkB,KAAK;AACtC,cAAM,YAAY,uBAAuB,SAAS,OAAO,KAAK,WAAW;AACzE,YAAI,cAAc,sBAAsB;AACvC,iBAAO,QAAQ,KAAK,WAAW,CAAC,OAAO,OAAO,SAAS,CAAC,GAAG,GAAG;AAAA,QAC/D;AACA,YAAI,UAAW,QAAO,QAAQ,KAAK,WAAW,QAAW,GAAG;AAE5D,cAAM,EAAE,UAAU,SAAS,IAAI,aAAa,OAAO;AACnD,cAAM,cAAc,gBAAgB,MAAM,KAAK,aAAa,OAAO,YAAY;AAC/E,cAAM,MAAM,WAAW,IAAI;AAAA,UAC1B;AAAA,UACA;AAAA,UACA,oBAAoB;AAAA,UACpB,mBAAmB,KAAK,IAAI;AAAA,UAC5B;AAAA,QACD,CAAC;AAED,yBAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,mBAAmB,CAAC;AAClH,eAAO,YAAY,KAAK,EAAE,IAAI,KAAK,GAAG,GAAG;AAAA,MAC1C,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,2BAA2B,GAAG;AAChD,YAAM,YAAY,KAAK;AACvB,YAAM,MAAM,YAAY,KAAK;AAC7B,UAAI,IAAI,kBAAkB,GAAG;AAC5B,eAAO,QAAQ,KAAK,qBAAqB,QAAW,GAAG;AAAA,MACxD;AACA,UAAI;AACH,cAAM,KAAK,eAAe,cAAc,MAAM,MAAM,UAAU,GAAG,EAAE;AACnE,cAAM,OAAO,eAAe,cAAc,MAAM,QAAQ,YAAY,KAAK,GAAG,GAAG;AAC/E,cAAM,WAAW,cAAc,MAAM,OAAO;AAC5C,cAAM,QAAQ,WAAW,eAAe,UAAU,GAAG,IAAI;AACzD,YAAI,CAAC,MAAM,CAAC,KAAM,QAAO,QAAQ,KAAK,6BAA6B,QAAW,GAAG;AACjF,cAAM,YAAY,uBAAuB,MAAM,KAAK;AACpD,YAAI,cAAc,sBAAsB;AACvC,iBAAO,QAAQ,KAAK,WAAW,CAAC,OAAO,kBAAkB,KAAK,EAAE,SAAS,CAAC,GAAG,GAAG;AAAA,QACjF;AACA,YAAI,UAAW,QAAO,QAAQ,KAAK,WAAW,QAAW,GAAG;AAC5D,cAAM,EAAE,UAAU,SAAS,IAAI,aAAa,IAAI;AAChD,cAAM,OAAO,MAAM,MAAM,WAAW;AAAA,UACnC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,IAAI;AAAA,UACJ,mBAAmB,KAAK,IAAI;AAAA,UAC5B,aAAa;AAAA,QACd,CAAC;AACD,yBAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,cAAc,CAAC;AAC7G,eAAO,YAAY,KAAK,EAAE,MAAM,WAAW,OAAO,IAAI,EAAE,GAAG,GAAG;AAAA,MAC/D,SAAS,KAAU;AAClB,cAAM,MAAM,KAAK,WAAW,OAAO,GAAG;AACtC,YAAI,IAAI,SAAS,QAAQ,KAAK,IAAI,SAAS,oBAAK,GAAG;AAClD,iBAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAAA,QAC1D;AACA,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,uBAAuB,GAAG;AAC5C,YAAM,YAAY,KAAK;AACvB,UAAI;AACH,cAAM,KAAK,eAAe,cAAc,MAAM,MAAM,UAAU,GAAG,EAAE;AACnE,cAAM,OAAO,eAAe,cAAc,MAAM,QAAQ,YAAY,KAAK,GAAG,GAAG;AAC/E,YAAI,CAAC,MAAM,CAAC,KAAM,QAAO,QAAQ,KAAK,6BAA6B,QAAW,GAAG;AAEjF,cAAM,OAAO,MAAM,MAAM,eAAe,EAAE;AAC1C,YAAI,CAAC,QAAQ,CAAC,eAAe,MAAM,KAAK,UAAU,KAAK,QAAQ,GAAG;AACjE,cAAI,MAAM;AACT,kBAAM,MAAM,YAAY,KAAK;AAC7B,kBAAM,aAAa,IAAI,mBAAmB;AAC1C,kBAAM,aAAa,IAAI,kBAAkB;AACzC,kBAAM,aAAa,KAAK,aAAa,KAAK;AAC1C,kBAAM,QAAa,EAAE,UAAU;AAC/B,gBAAI,aAAa,YAAY;AAC5B,oBAAM,SAAS;AACf,oBAAM,cAAc,KAAK,IAAI,IAAI,aAAa,KAAK;AAAA,YACpD;AACA,kBAAM,MAAM,WAAW,IAAI,KAAK;AAAA,UACjC;AACA,2BAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,GAAG,CAAC;AACtF,iBAAO,QAAQ,KAAK,4BAA4B,QAAW,GAAG;AAAA,QAC/D;AAEA,YAAI,KAAK,WAAW,YAAY;AAC/B,iBAAO,QAAQ,KAAK,yBAAyB,QAAW,GAAG;AAAA,QAC5D;AAEA,YAAI,KAAK,WAAW,YAAY,KAAK,eAAe,KAAK,cAAc,KAAK,IAAI,GAAG;AAClF,iBAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAAA,QAC1D;AAEA,cAAM,SAAS,kBAAkB,KAAK;AACtC,cAAM,aACL,CAAC,CAAC,KAAK,sBACP,kBAAkB,KAAK,mBAAmB,OAAO,UAAU;AAE5D,cAAM,UAAU,MAAM,UAAU,OAAO,KAAK,CAAC;AAC7C,YAAI,QAAQ,QAAQ,iBAAiB,OAAO,IAAI,OAAO,GAAG;AAEzD,qBAAW,OAAO,IAAI,OAAO;AAAA,QAC9B;AAEA,cAAM,aAAa,MAAM,SAAS,OAAO,IAAI,OAAO;AACpD,YAAI,CAAC,WAAW,IAAI;AACnB,2BAAiB,OAAO,EAAE,MAAM,cAAc,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,WAAW,QAAQ,CAAC;AACnH,iBAAO,QAAQ,KAAK,WAAW,WAAW,oBAAoB,QAAW,GAAG;AAAA,QAC7E;AAEA,cAAM,MAAM,WAAW,IAAI,EAAE,WAAW,GAAG,QAAQ,UAAU,aAAa,OAAU,CAAC;AACrF,cAAM,UAAU,mBAAmB,OAAO,IAAI,EAAE;AAChD,gBAAQ,iBAAiB,KAAK,IAAI;AAClC,cAAM,MAAM,WAAW,OAAO;AAE9B,yBAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,WAAW,CAAC;AAE1G,eAAO;AAAA,UACN;AAAA,UACA;AAAA,YACC,MAAM,EAAE,GAAG,WAAW,OAAO,IAAI,GAAG,oBAAoB,WAAW;AAAA,YACnE,MAAM,aAAa,OAAO,CAAC,QAAQ,KAAK,QAAQ,GAAG;AAAA,YACnD,WAAW,aAAa,OAAO,QAAQ;AAAA,YACvC,oBAAoB;AAAA,UACrB;AAAA,UACA;AAAA,QACD;AAAA,MACD,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,yBAAyB,GAAG;AAC9C,UAAI;AACH,cAAM,UAAU,KAAK,YAAY,eAAe,KAAK,WAAW,EAAE,IAAI;AACtE,YAAI,QAAS,OAAM,MAAM,cAAc,OAAO;AAC9C,cAAM,KAAK,KAAK,WAAW,CAAC;AAC5B,YAAI,GAAI,kBAAiB,OAAO,EAAE,MAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,MAAM,OAAO,EAAE,GAAG,IAAI,QAAQ,SAAS,CAAC;AACxH,eAAO,YAAY,KAAK,MAAM,GAAG;AAAA,MAClC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AAClD,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,YAAY,CAAC,GAAI;AAC/E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,YAAY,eAAe,KAAK,WAAW,EAAE;AACnD,YAAI,CAAC,UAAW,QAAO,QAAQ,KAAK,6BAA6B,QAAW,GAAG;AAC/E,cAAM,WAAW,MAAM,MAAM,YAAY;AACzC,cAAM,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AACtD,YAAI,CAAC,OAAQ,QAAO,QAAQ,KAAK,0BAA0B,QAAW,GAAG;AACzE,YAAI,CAAC,oBAAoB,OAAO,OAAO,IAAI,OAAO,GAAG;AACpD,iBAAO,QAAQ,KAAK,sBAAsB,QAAW,GAAG;AAAA,QACzD;AACA,mBAAW,OAAO,OAAO,IAAI,OAAO;AACpC,cAAM,MAAM,cAAc,SAAS;AACnC,cAAM,WAAW,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAChD,cAAM,oBAAoB,OAAO;AAAA,UAChC;AAAA,UACA;AAAA,UACA,UAAU,OAAO;AAAA,UACjB;AAAA,QACD,CAAC;AACD,eAAO,YAAY,KAAK,EAAE,IAAI,KAAK,GAAG,GAAG;AAAA,MAC1C,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,+BAA+B,GAAG;AACpD,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,YAAY,CAAC,GAAI;AAC/E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,WAAW,eAAe,KAAK,IAAI,EAAE;AAC3C,YAAI,CAAC,YAAY,aAAa,QAAS,QAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAC3F,cAAM,KAAK,MAAM,MAAM,WAAW,QAAQ;AAC1C,YAAI,CAAC,GAAI,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAClE,cAAM,WAAW,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAChD,cAAM,gBAAgB,OAAO,EAAE,UAAU,UAAU,GAAG,CAAC;AACvD,eAAO,YAAY,KAAK,EAAE,IAAI,KAAK,GAAG,GAAG;AAAA,MAC1C,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,+BAA+B,GAAG;AACpD,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,YAAY,CAAC,GAAI;AAC/E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,SAAS,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK,SAAS;AAC1D,cAAM,aACL,KAAK,cAAc,OAAO,KAAK,eAAe,WAAY,KAAK,aAAyC;AACzG,cAAM,cAAc,MAAM,QAAQ,KAAK,WAAW,IAAI,KAAK,cAAc;AACzE,cAAM,uBACL,OAAO,KAAK,yBAAyB,WAAW,KAAK,uBAAuB;AAC7E,cAAM,WAAW,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAChD,cAAM,MAAM,MAAM;AAAA,UACjB;AAAA,UACA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACD;AAAA,UACA;AAAA,QACD;AACA,cAAM,8BAA8B,OAAO;AAAA,UAC1C,SAAS;AAAA,UACT,QAAQ,KAAK,UAAU,EAAE,QAAQ,QAAQ,QAAQ,YAAY,CAAC,CAAC,YAAY,aAAa,aAAa,OAAO,CAAC;AAAA,UAC7G;AAAA,UACA;AAAA,QACD,CAAC;AACD,eAAO,YAAY,KAAK,KAAK,GAAG;AAAA,MACjC,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,kCAAkC,GAAG;AACvD,YAAM,YAAY,KAAK;AACvB,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,YAAY,CAAC,GAAI;AAC/E,yBAAiB,OAAO,EAAE,MAAM,iBAAiB,MAAM,KAAK,QAAQ,QAAQ,GAAG,CAAC;AAChF,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,WAAW,eAAe,KAAK,IAAI,EAAE;AAC3C,YAAI,CAAC,SAAU,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AACxE,YAAI,UAAU,eAAe,cAAc,MAAM,WAAW,eAAe,SAAS,GAAG,GAAG;AAC1F,YAAI,CAAC,QAAS,WAAU,wBAAwB,KAAK;AACrD,cAAM,SAAS,kBAAkB,KAAK;AACtC,cAAM,YAAY,2BAA2B,SAAS,MAAM;AAC5D,YAAI,cAAc,sBAAsB;AACvC,iBAAO,QAAQ,KAAK,WAAW,CAAC,OAAO,OAAO,SAAS,CAAC,GAAG,GAAG;AAAA,QAC/D;AACA,YAAI,UAAW,QAAO,QAAQ,KAAK,WAAW,QAAW,GAAG;AAE5D,cAAM,OAAO,MAAM,MAAM,eAAe,QAAQ;AAChD,YAAI,CAAC,KAAM,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAEpE,cAAM,EAAE,UAAU,SAAS,IAAI,aAAa,OAAO;AACnD,cAAM,UAAU,MAAM,MAAM,WAAW,UAAU;AAAA,UAChD;AAAA,UACA;AAAA,UACA,oBAAoB;AAAA,UACpB,mBAAmB,KAAK,IAAI;AAAA,UAC5B,WAAW;AAAA,UACX,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,aAAa;AAAA,QACd,CAAC;AACD,YAAI,CAAC,QAAS,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AACvE,cAAM,WAAW,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAChD,cAAM,kBAAkB,OAAO;AAAA,UAC9B;AAAA,UACA;AAAA,UACA,OAAO,EAAE,eAAe,MAAM,oBAAoB,EAAE;AAAA,UACpD;AAAA,QACD,CAAC;AACD,yBAAiB,OAAO;AAAA,UACvB,MAAM;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,MAAM;AAAA,UACN;AAAA,UACA,QAAQ;AAAA,QACT,CAAC;AACD,eAAO,YAAY,KAAK,EAAE,MAAM,WAAW,OAAO,OAAO,EAAE,GAAG,GAAG;AAAA,MAClE,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,+BAA+B,GAAG;AACpD,YAAM,YAAY,KAAK;AACvB,UAAI,CAAE,MAAM,WAAW,KAAK,GAAG,GAAI;AAClC,yBAAiB,OAAO,EAAE,MAAM,iBAAiB,MAAM,KAAK,QAAQ,QAAQ,GAAG,CAAC;AAChF,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,UAAI;AACH,cAAM,WAAW,eAAe,KAAK,IAAI,EAAE;AAC3C,cAAM,QAAa,CAAC;AACpB,YAAI,KAAK,MAAM,MAAM;AACpB,gBAAM,QAAQ,OAAO,KAAK,EAAE;AAC5B,cAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,cAAc,OAAO,KAAK,GAAG;AAC5D,mBAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,UACrD;AACA,gBAAM,KAAK;AACX,gBAAM,OAAO,oBAAoB,OAAO,KAAK,EAAE;AAAA,QAChD;AACA,YAAI,KAAK,OAAQ,OAAM,SAAS,eAAe,KAAK,QAAQ,EAAE;AAC9D,YAAI,KAAK,WAAW;AACnB,gBAAM,YAAY;AAClB,gBAAM,SAAS;AACf,gBAAM,cAAc;AAAA,QACrB;AACA,YAAI,KAAK,sBAAsB,KAAM,OAAM,qBAAqB,KAAK,qBAAqB,IAAI;AAC9F,cAAM,UAAU,MAAM,MAAM,WAAW,UAAU,KAAK;AACtD,YAAI,CAAC,QAAS,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AACvE,YAAI,OAAO,KAAK,KAAK,EAAE,QAAQ;AAC9B,gBAAM,kBAAkB,OAAO;AAAA,YAC9B,UAAU,OAAO,KAAK,WAAW,CAAC,KAAK,EAAE;AAAA,YACzC;AAAA,YACA;AAAA,YACA;AAAA,UACD,CAAC;AAAA,QACF;AACA,eAAO,YAAY,KAAK,EAAE,MAAM,WAAW,OAAO,OAAO,EAAE,GAAG,GAAG;AAAA,MAClE,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC/C,YAAM,KAAK,KAAK,WAAW,CAAC;AAC5B,UAAI,CAAC,GAAI,QAAO,QAAQ,KAAK,qBAAqB,QAAW,GAAG;AAChE,UAAI;AACH,cAAM,OAAO,MAAM,MAAM,eAAe,OAAO,EAAE,CAAC;AAClD,YAAI,CAAC,KAAM,QAAO,QAAQ,KAAK,uBAAuB,QAAW,GAAG;AAEpE,YAAI,cAAc,MAAM,WAAW,eAAe,SAAS,GAAG;AAC7D,gBAAM,UAAU,eAAe,cAAc,MAAM,WAAW,eAAe,SAAS,GAAG,GAAG;AAC5F,gBAAM,SAAS,kBAAkB,KAAK;AACtC,gBAAM,UAAU,cAAc,MAAM,QAAQ,YAAY,KAAK;AAE7D,cAAI,SAAS;AACZ,gBAAI,CAAC,eAAe,SAAS,KAAK,UAAU,KAAK,QAAQ,GAAG;AAC3D,qBAAO,QAAQ,KAAK,yBAAyB,QAAW,GAAG;AAAA,YAC5D;AAAA,UACD,WAAW,CAAC,KAAK,oBAAoB;AACpC,mBAAO,QAAQ,KAAK,yBAAyB,QAAW,GAAG;AAAA,UAC5D;AAEA,gBAAM,YAAY,uBAAuB,SAAS,OAAO,KAAK,WAAW;AACzE,cAAI,cAAc,sBAAsB;AACvC,mBAAO,QAAQ,KAAK,WAAW,CAAC,OAAO,OAAO,SAAS,CAAC,GAAG,GAAG;AAAA,UAC/D;AACA,cAAI,UAAW,QAAO,QAAQ,KAAK,WAAW,QAAW,GAAG;AAE5D,gBAAM,EAAE,UAAU,SAAS,IAAI,aAAa,OAAO;AACnD,gBAAM,cAAc,gBAAgB,WAAW,SAAS,KAAK,aAAa,OAAO,YAAY;AAC7F,gBAAM,MAAM,WAAW,OAAO,EAAE,GAAG;AAAA,YAClC;AAAA,YACA;AAAA,YACA,oBAAoB;AAAA,YACpB,mBAAmB,KAAK,IAAI;AAAA,YAC5B;AAAA,UACD,CAAC;AAAA,QACF;AAEA,cAAM,QAAQ,MAAM,MAAM,eAAe,OAAO,EAAE,CAAC;AACnD,eAAO,YAAY,KAAK,EAAE,MAAM,QAAQ,WAAW,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG;AAAA,MAC/E,SAAS,KAAU;AAClB,eAAO,SAAS,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MAC9C;AAAA,IACD;AAAA,EACD;AA5Xe;AA8Xf,iBAAe,IAAI,KAAU,KAAU,SAAiB,KAAU;AACjE,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,KAAK,YAAY,GAAG;AAE1B,QAAI,IAAI,WAAW,yBAAyB,GAAG;AAC9C,YAAM,OAAO,OAAO,KAAK,UAAU,iBAAiB,KAAK,KAAK,UAAU,iBAAiB,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AACnH,YAAM,oBAAoB,KAAK;AAC/B,aAAO,YAAY,KAAK,wBAAwB,OAAO,IAAI,GAAG,GAAG;AAAA,IAClE;AAEA,QAAI,IAAI,WAAW,+BAA+B,GAAG;AACpD,UAAI,CAAE,MAAM,WAAW,KAAK,KAAK,uBAAuB,OAAO,WAAW,CAAC,GAAI;AAC9E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,YAAM,oBAAoB,KAAK;AAC/B,aAAO,YAAY,KAAK,uBAAuB,KAAK,GAAG,GAAG;AAAA,IAC3D;AAEA,QAAI,IAAI,WAAW,iCAAiC,GAAG;AACtD,UAAI,CAAE,MAAM,WAAW,KAAK,GAAG,GAAI;AAClC,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,YAAM,cAAc,MAAM,MAAM,YAAY;AAC5C,YAAM,WAAW,sBAAsB,OAAO,SAAS,WAAW;AAClE,aAAO;AAAA,QACN;AAAA,QACA;AAAA,UACC,UAAU,SAAS,IAAI,CAAC,OAAO;AAAA,YAC9B,IAAI,EAAE;AAAA,YACN,IAAI,EAAE;AAAA,YACN,IAAI,EAAE;AAAA,YACN,WAAW,EAAE;AAAA,YACb,WAAW,EAAE;AAAA,YACb,gBAAgB,EAAE;AAAA,YAClB,QAAQ;AAAA,UACT,EAAE;AAAA,QACH;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,6BAA6B,GAAG;AAClD,UAAI,CAAE,MAAM,WAAW,KAAK,GAAG,GAAI;AAClC,yBAAiB,OAAO,EAAE,MAAM,iBAAiB,MAAM,KAAK,QAAQ,OAAO,GAAG,CAAC;AAC/E,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,YAAM,QAAQ,MAAM,MAAM,UAAU;AACpC,aAAO,YAAY,KAAK,EAAE,OAAO,MAAM,IAAI,CAAC,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG;AAAA,IAC/E;AAEA,QAAI,IAAI,WAAW,8BAA8B,GAAG;AACnD,UAAI,CAAE,MAAM,WAAW,KAAK,GAAG,GAAI;AAClC,eAAO,QAAQ,KAAK,kBAAkB,QAAW,GAAG;AAAA,MACrD;AACA,YAAM,qBAAqB,OAAO,SAAS,KAAK;AAChD,YAAM,cAAc,MAAM,oBAAoB,OAAO,SAAS,KAAK;AACnE,YAAM,QAAQA,UAAS,KAAK;AAC5B,aAAO;AAAA,QACN;AAAA,QACA;AAAA,UACC,UAAU;AAAA,UACV,kBAAkB,MAAM,oBAAoB;AAAA,UAC5C,cAAc,CAAC,CAAC,MAAM;AAAA,UACtB,MAAM,MAAM;AAAA,UACZ,IAAI,MAAM;AAAA,QACX;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,IAAI,WAAW,0BAA0B,GAAG;AAC/C,YAAM,KAAK,KAAK,WAAW,CAAC;AAC5B,UAAI,CAAC,GAAI,QAAO,QAAQ,KAAK,qBAAqB,QAAW,GAAG;AAChE,YAAM,OAAO,MAAM,MAAM,eAAe,OAAO,EAAE,CAAC;AAClD,aAAO,YAAY,KAAK,EAAE,MAAM,OAAO,WAAW,OAAO,IAAI,IAAI,KAAK,GAAG,GAAG;AAAA,IAC7E;AAAA,EACD;AA5Ee;AA8Ef,SAAO,EAAE,MAAM,IAAI;AACpB,GAvde;;;ACxFf,IAAO,cAAQ;AAAA,EACb,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,cAAc;AAAA,EACd,qBAAqB;AAAA,EACrB,cAAc;AAChB;;;AChBA,IAAO,aAAQ;AAAA,EACb,OAAO,IAAY,QAAmC,OAAY,MAAM;AACtE,UAAM,KACJ,UAAU,OACN,SACA,MAAM,QAAQ,MAAM,IAClB,OAAO,IAAI,MAAM,IACjB,CAAC,OAAO,MAAM,CAAC;AACvB,WAAO,EAAE,MAAM,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE;AAAA,EACvC;AAAA,EACA,QAAQ,KAAU,MAAW,MAAM;AACjC,QAAI,OAAO,OAAO,QAAQ,YAAY,OAAO,IAAI,OAAO,UAAU;AAChE,aAAO,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,IAChC;AACA,QAAI,eAAe,OAAO;AACxB,YAAM,IAAI,WAAW,OAAO,GAAG;AAAA,IACjC,WAAW,OAAO,OAAO,QAAQ,YAAY,OAAO,IAAI,YAAY,UAAU;AAC5E,YAAM,IAAI;AAAA,IACZ;AACA,WAAO,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,EAChC;AAAA,EACA,SAAS,KAAa,MAAW,MAAM;AACrC,WAAO,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,EAChC;AAAA,EACA,WAAW,KAAU,MAAW,MAAM;AACpC,QAAI,OAAO,KAAK,WAAW,YAAY;AACrC,YAAM,IAAI,OAAO,GAAG;AAAA,IACtB;AACA,WAAO,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,EAChC;AAAA,EACA,QAAQ,MAAc,KAAK;AACzB,WAAO,KAAK,QAAQ,yBAAyB,EAAE;AAAA,EACjD;AAAA,EACA,QAAQ,MAAc,KAAK;AACzB,WAAO,KAAK,QAAQ,qBAAqB,EAAE;AAAA,EAC7C;AAAA,EAEA,UAAU,cAAsB;AAC9B,UAAM,UAAU,aAAa,MAAM,GAAG;AACtC,YAAQ,IAAI;AACZ,UAAM,UAAU,QAAQ,KAAK,GAAG,IAAI;AACpC,WAAO;AAAA,EACT;AAAA,EACA,eAAe,cAAsB;AACnC,mBAAe,QAAQ,IAAI,IAAI;AAC/B,mBAAe,aAAa,QAAQ,OAAO,GAAG;AAC9C,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,UAAUC,MAAS,cAAsB;AACvC,UAAM,aAAa,KAAK,UAAU,YAAY;AAC9C,UAAM,UAAU,KAAK,eAAe,YAAY;AAChD,QAAI,CAACA,KAAG,WAAW,OAAO,GAAG;AAC3B,UAAI,UAAkB;AACtB,iBAAW,MAAM,GAAG,EAAE,QAAQ,CAAC,OAAe;AAC5C,YAAI,IAAI;AACN,cAAI,SAAS;AACX,uBAAW;AAAA,UACb;AACA,qBAAW;AACX,cAAI,CAACA,KAAG,WAAW,OAAO,GAAG;AAC3B,gBAAI,CAACA,KAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC,GAAG;AAC/C,qBAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EACA,QAAQA,MAAS,WAAmB;AAClC,WAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAI;AACF,cAAM,UAAU,KAAK,UAAUD,MAAI,SAAS;AAC5C,QAAAC,SAAQ,OAAO;AAAA,MACjB,SAAS,KAAU;AACjB,eAAO,GAAG;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EACA,YAAY,MAAc,KAAK;AAC7B,QAAI,WAAW;AACf,QAAI,YAAY;AAChB,QAAI,IAAI,WAAW,GAAG,GAAG;AAEvB,iBAAW,KAAK,QAAQ,GAAG;AAAA,IAC7B,WAAW,IAAI,QAAQ,GAAG,IAAI,IAAI;AAEhC,UAAI,IAAI,WAAW,KAAK,GAAG;AACzB,mBAAW,KAAK,QAAQ,MAAM,GAAG;AAAA,MACnC,OAAO;AACL,mBAAW,qBAAqB,KAAK,QAAQ,GAAG;AAAA,MAClD;AAAA,IACF,OAAO;AACL,iBAAW,qBAAqB,KAAK,QAAQ,GAAG;AAAA,IAClD;AACA,gBAAY,KAAK,eAAe,QAAQ;AACxC,WAAO,EAAE,UAAU,UAAU;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAY,IAAS,KAAU;AAC7B,QAAI,KAAK,WAAW;AAElB,SAAG;AACH,UAAI,YAAY;AAAA,IAClB;AAAA,EACF;AAAA,EACA,eAAe,KAAU;AACvB,iBAAa,IAAI,OAAO;AACxB,QAAI,UAAU;AAAA,EAChB;AAAA,EACA,aAAa,IAAS,KAAU;AAC9B,WAAO,WAAW,MAAM;AACtB,SAAG;AACH,WAAK,eAAe,GAAG;AAAA,IACzB,GAAG,IAAI,IAAI;AAAA,EACb;AAAA;AAAA,EAEA,SAAS,IAAS,KAAU;AAC1B,SAAK,YAAY,IAAI,GAAG;AACxB,QAAI,WAAU,oBAAI,KAAK,GAAE,QAAQ;AACjC,QAAI,IAAI,UAAU,IAAI,YAAY,IAAI,MAAM;AAC1C,WAAK,eAAe,GAAG;AAAA,IACzB;AACA,QAAI,CAAC,KAAK,SAAS;AACjB,UAAI,YAAY,IAAI;AACpB,UAAI,UAAU,KAAK,aAAa,IAAI,GAAG;AAAA,IACzC;AAAA,EACF;AAAA;AAAA,EAEA,SAAS,IAAS,KAAU;AAC1B,SAAK,YAAY,IAAI,GAAG;AACxB,QAAI,CAAC,KAAK,SAAS;AACjB,UAAI,UAAU,KAAK,aAAa,IAAI,GAAG;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,aAAqB,IAAI,QAAgB,GAAG,MAAc,IAAY;AACzE,QAAI,MAAc,KAAK,IAAI,EAAE,SAAS,EAAE;AACxC,QAAI,QAAQ,GAAG;AACb,aAAO,MAAM,SAAS,EAAE;AAAA,IAC1B;AACA,UAAM,IAAI,MAAM,EAAE;AAClB,QAAI,YAAY;AACd,YAAM,WAAW,MAAM,EAAE,IAAI;AAAA,IAC/B;AACA,QAAI,SAAiB,IAAI;AACzB,WAAO,SAAS,IAAI;AAClB,cAAS,KAAK,OAAO,IAAI,MAAO,GAAG,SAAS,GAAG,EAAE,MAAM,EAAE;AACzD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EACA,MAAM,KAAU;AACd,UAAM,YAAY,IAAI,QAAQ,iBAAiB;AAC/C,WAAO,YAAY,UAAU,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,WAAW;AAAA,EAC9D;AACF;;;ACzKA,IAAO,iBAAQ;AAAA;AAAA,EAEX,SAAS,KAAa,MAAc;AAChC,UAAM,SAAiB,KAAK,UAAU;AACtC,UAAM,UAAkB,MAAM,UAAU;AACxC,QAAI,SAAiB;AACrB,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC7B,YAAM,OAAe,KAAK,MAAM,KAAK,OAAO,IAAI,GAAI,IAAI;AACxD,YAAM,QAAgB,OAAO,KAAK,SAAS,EAAE,MAAM,EAAE,CAAC,IAAI;AAC1D,YAAM,OAAe,UAAU;AAC/B,UAAI,SAAS,IAAI,YAAY,CAAC;AAC9B,YAAM,KAAa,SAAS;AAC5B,gBAAU,SAAS,MAAM;AACzB,YAAM,KAAa,SAAS;AAC5B,gBAAU,SAAS,MAAM;AACzB,gBACI,KAAM,SAAS,OAAQ,KAAK,IAC5B,KAAK,KAAK,KAAK,IACf,KAAK,KAAK,KAAK,IACf,KAAK,OAAO,IAAI;AAAA,IACxB;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,SAAS,KAAa,MAAc;AAChC,QAAI;AACA,YAAM,SAAiB,IAAI;AAC3B,YAAM,UAAkB,KAAK;AAC7B,UAAI,SAAiB;AACrB,eAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC7B,cAAM,OAAe,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC;AAC5C,cAAM,QAAgB,OAAO,KAAK,SAAS,EAAE,MAAM,EAAE,CAAC,IAAI;AAC1D,cAAM,OAAe,UAAU;AAC/B,kBAAU,QAAQ;AAAA,WACb,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,SAAS,OAAO,QACrC,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,SAAS,QAClC,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI;AAAA,QAClC;AAAA,MACJ;AACA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EACA,YAAY,MAAW,MAAc;AACjC,QAAI;AACA,aAAO,KAAK,MAAM,IAAI;AACtB,aAAO,KAAK;AAAA,QACR,KAAK,SAAS,KAAK,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI,CAAC;AAAA,MAC3D;AAAA,IACJ,SAAS,OAAO;AACZ;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,aAAa,MAAW,MAAc,MAAc;AAChD,WAAO;AAAA,MACH;AAAA,MACA,MAAM,KAAK;AAAA,QACP,KAAK,UAAU,IAAI;AAAA,QACnB,KAAK,SAAS,MAAM,IAAI;AAAA,MAC5B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA,EAEA,SAAS,KAAa;AAClB,UAAM,SAAmB,CAAC;AAC1B,QAAI,MAAM,EAAE,EAAE,QAAQ,CAAC,OAAe;AAClC,aAAO,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,OAAO,MAAM,GAAG,GAAG,EAAE;AAAA,IAClE,CAAC;AACD,WAAO,OAAO,KAAK,EAAE;AAAA,EACzB;AACJ;;;ACxEA,OAAO,YAAY;AAEnB,IAAO,gBAAQ,wBAAC,OAAY,MAAW,SAAS;AAC5C,QAAM,UAAU,OAAO,KAAK,MAAM,WAAW,IAAI,WAAW,QAAQ;AACpE,QAAM,UAAU,OAAO,KAAK,MAAM,WAAW,IAAI,KAAK,MAAM;AAE5D,WAAS,cAAc,OAAY;AAC/B,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI;AACA,aAAO,KAAK,MAAM,KAAK;AAAA,IAC3B,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAPS;AAST,WAAS,aAAa,OAAuB;AACzC,QAAI,OAAO,UAAU,UAAU;AAC3B,YAAM,IAAI,UAAU,yBAAyB;AAAA,IACjD;AACA,WAAO,OAAO,KAAK,OAAO,QAAQ;AAAA,EACtC;AALS;AAOT,WAAS,QAAQ,WAAmB;AAChC,UAAM,KAAK,OAAO,YAAY,MAAM,WAAW,IAAI,QAAQ;AAC3D,UAAM,SAAS,OAAO,eAAe,MAAM,WAAW,IAAI,WAAW,SAAS,EAAE;AAChF,WAAO,OAAO,OAAO;AACrB,UAAM,kBAAkB,OAAO,OAAO,CAAC,OAAO,OAAO,WAAW,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;AACxF,WAAO;AAAA,MACH,MAAM,gBAAgB,SAAS,QAAQ;AAAA,MACvC,IAAI,GAAG,SAAS,QAAQ;AAAA,MACxB,MAAM,OAAO,WAAW,EAAE,SAAS,QAAQ;AAAA,IAC/C;AAAA,EACJ;AAVS;AAYT,WAAS,QAAQ,UAAe;AAC5B,UAAM,KAAK,aAAa,SAAS,EAAE;AACnC,UAAM,UAAU,aAAa,SAAS,IAAI;AAC1C,UAAM,YAAY,aAAa,SAAS,IAAI;AAC5C,UAAM,WAAW,OAAO,iBAAiB,MAAM,WAAW,IAAI,WAAW,SAAS,EAAE;AACpF,aAAS,OAAO,OAAO;AACvB,aAAS,WAAW,OAAO;AAC3B,UAAM,kBAAkB,OAAO,OAAO,CAAC,SAAS,OAAO,SAAS,GAAG,SAAS,MAAM,CAAC,CAAC;AACpF,WAAO,gBAAgB,SAAS,MAAM;AAAA,EAC1C;AATS;AAWT,WAAS,eAAe,SAAc,QAAkB;AACpD,WAAO,OAAO,MAAM,CAAC,QAAQ,OAAO,UAAU,GAAG,MAAM,YAAY,QAAQ,GAAG,EAAE,SAAS,CAAC;AAAA,EAC9F;AAFS;AAIT,WAAS,OAAO,KAAU,KAAU,CAAC,SAAc,MAAM;AACrD,UAAM,UAAU,cAAc,IAAI,IAAI;AACtC,QAAI;AACA,UAAI,eAAe,SAAS,CAAC,QAAQ,MAAM,MAAM,CAAC,GAAG;AACjD,YAAI,UAAe,QAAQ,OAAO;AAClC,YAAI,SAAS,QAAQ,GAAG;AACpB,oBAAU,KAAK,MAAM,OAAO;AAAA,QAChC;AACA,eAAO,GAAG,OAAO;AAAA,MACrB,OAAO;AACH,eAAO,GAAG,OAAO;AAAA,MACrB;AAAA,IACV,SAAS,OAAY;AACpB,UAAI,eAAe,SAAS,CAAC,QAAQ,MAAM,MAAM,CAAC,GAAG;AACpD,cAAM;AAAA,MACP;AACA,aAAO,GAAG,OAAO;AAAA,IAClB;AAAA,EACE;AAlBS;AAmBT,WAAS,OAAO,MAAW;AACvB,QAAI;AACA,UAAI,QAAgB;AACpB,UAAI,QAAQ,OAAO,SAAS,UAAU;AAClC,eAAO,KAAK,UAAU,IAAI;AAC1B,gBAAQ;AAAA,MACZ;AACA,aAAO,OAAO,OAAO,EAAE,KAAK,MAAM,GAAG,QAAQ,IAAI,CAAC;AAAA,IACtD,SAAS,OAAY;AACjB,aAAO;AAAA,IACX;AAAA,EACJ;AAXS;AAaT,SAAO,EAAE,SAAS,SAAS,QAAQ,OAAO;AAC9C,GAhFe;;;ACAf,IAAO,eAAQ,wBAAC,OAAY,QAAa;AACvC,QAAM,aAAkB,qBAAqB,OAAO;AAAA,IAClD,MAAM,KAAK,QAAQ;AAAA,IACnB,KAAK;AAAA,MACH,GAAI,KAAK,OAAO;AAAA,QACd,UAAU;AAAA,QACV,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,IACA,UAAU,KAAK;AAAA,EACjB,CAAC;AAED,WAAS,YAAY,KAAU;AAC7B,QAAI,KAAK,SAAS,YAAY,KAAK,SAAS,SAAS;AACnD,aAAO,IAAI,GAAG;AAAA,IAChB;AACA,WAAO;AAAA,EACT;AALS;AAOT,WAAS,SAAS,WAAgB;AAChC,QAAI,WAAW,IAAI;AACjB,aAAO,UAAU,GAAG,MAAM,GAAG;AAAA,IAC/B;AACA,WAAO,IAAI,MAAM;AAAA,EACnB;AALS;AAOT,WAAS,SAAS,WAAgB;AAChC,UAAM,WAAkB,CAAC;AACzB,SAAK,KAAK,SAAS,YAAY,KAAK,SAAS,YAAY,WAAW,KAAK;AACvE,YAAM,SAAS,UAAU,IAAI,MAAM,GAAG;AACtC,eAAS,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAAA,IACxD;AACA,QAAI,WAAW,IAAI;AACjB,eAAS,KAAK,CAAC,IAAI,MAAM,OAAO,QAAQ,YAAY,GAAG,UAAU,EAAE,GAAG,CAAC,CAAC;AAAA,IAC1E;AACA,QAAI,WAAW,MAAM,WAAW,MAAM;AACpC,eAAS,KAAK,CAAC,UAAU,MAAM,QAAQ,YAAY,IAAI,UAAU,EAAE,GAAG,CAAC,CAAC;AAAA,IAC1E;AACA,QAAI,SAAS,SAAS,GAAG;AACvB,eAAS,QAAQ,KAAK;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AAhBS;AAkBT,WAAS,SAAS,WAAgB;AAChC,UAAM,WAAkB,CAAC;AACzB,QAAI,WAAW,IAAI;AACjB,eAAS,KAAK,CAAC,UAAU,IAAI,WAAW,QAAQ,IAAI,SAAS,KAAK,CAAC;AAAA,IACrE;AACA,WAAO;AAAA,EACT;AANS;AAQT,WAAS,SAAS,WAAgB;AAChC,QAAI,WAAW;AACf,QAAI,UAAkB,WAAW;AACjC,QAAI,WAAW,IAAI;AACjB,gBAAU,WAAW;AACrB,iBAAW,IAAI,UAAU,KAAK,KAAK,OAAO,IAAI,OAAO;AAAA,IACvD,WAAW,SAAS;AAClB,kBAAY;AAAA,IACd;AACA,WAAO;AAAA,EACT;AAVS;AAYT,WAAS,kBAAkB,KAAqB;AAC9C,QAAI;AACF,aAAO,mBAAmB,GAAG;AAAA,IAC/B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AANS;AAQT,WAAS,aAAa,MAAsB;AAC1C,UAAM,OAAO,OAAO,IAAI,EAAE,QAAQ,YAAY,EAAE;AAChD,UAAM,QAAQ,KAAK,YAAY,GAAG;AAClC,WAAO,QAAQ,KAAK,KAAK,UAAU,QAAQ,CAAC,IAAI;AAAA,EAClD;AAJS;AAMT,WAAS,cAAc,KAAmD;AACxE,QAAI,OAAY;AAChB,QAAI,OAAO,SAAS,UAAU;AAC5B,UAAI;AACF,eAAO,KAAK,MAAM,IAAI;AAAA,MACxB,QAAQ;AACN,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,IACF;AACA,QAAI,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AAC5D,aAAO;AAAA,QACL,MAAM,KAAK,QAAQ,OAAO,OAAO,KAAK,IAAI,IAAI;AAAA,QAC9C,SAAS,KAAK,YAAY,SAAY,KAAK,UAAU;AAAA,MACvD;AAAA,IACF;AACA,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAhBS;AAkBT,WAAS,kBAAkB,SAA0B;AACnD,QAAI,WAAW,KAAM,QAAO;AAC5B,QAAI,OAAO,YAAY,SAAU,QAAO;AACxC,WAAO,KAAK,UAAU,OAAO;AAAA,EAC/B;AAJS;AAMT,WAAS,mBAAmB,KAAa,UAA2B;AAClE,WAAO,aAAa,kBAAkB,OAAO,YAAY,EAAE,CAAC;AAAA,EAC9D;AAFS;AAIT,WAAS,kBAAkB,KAAU,KAAU;AAC7C,QAAI;AACJ,UAAM,SAAc,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC;AAC5D,UAAM,SAAS,KAAK,QAAQ,SAAS,KAAK,MAAM,SAAS,OAAO,CAAC,GAAG,WAAW,KAAK,GAAG;AACvF,QAAI,CAAC,MAAO,QAAO;AAEnB,mBAAe;AAAA,MACb,MAAM;AAAA,MACN;AAAA,IACF;AAEA,QAAI,OAAO,CAAC,GAAG;AACb,UAAI,OAAO,CAAC,MAAM,UAAU;AAC1B,qBAAa,OAAO,OAAO,CAAC;AAC5B,YAAI,KAAK,SAAS,QAAQ;AACxB,gBAAM,EAAE,MAAM,UAAU,QAAQ,IAAI,cAAc,IAAI,IAAI;AAC1D,gBAAM,UAAU,mBAAmB,OAAO,CAAC,GAAG,QAAQ;AACtD,uBAAa,QAAQ,IAAI,MAAM;AAC/B,uBAAa,QAAQ,CAAC,CAAC,SAAS,kBAAkB,OAAO,CAAC,CAAC;AAAA,QAC7D,OAAO;AACL,uBAAa,QAAQ,CAAC;AACtB,uBAAa,QAAQ,CAAC;AACtB,gBAAM,WAAkB,CAAC;AACzB,gBAAM,SAAc,OAAO,IAAI,SAAS,WAAW,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI;AAC9E,iBAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,OAAY;AAC1C,gBAAI,IAAI,MAAM,KAAK,SAAS,GAAG,CAAC,CAAC,GAAG;AAClC,2BAAa,MAAM,KAAK,GAAG,CAAC,CAAC;AAC7B,uBAAS,KAAK,GAAG,CAAC,CAAC;AAAA,YACrB;AAAA,UACF,CAAC;AACD,cAAI,CAAC,aAAa,MAAM,SAAS,IAAI,MAAM,GAAG,GAAG;AAC/C,yBAAa,MAAM,KAAK,IAAI,MAAM,GAAG;AACrC,qBAAS,KAAK,OAAO,CAAC,CAAC;AAAA,UACzB;AACA,uBAAa,MAAM,KAAK,QAAQ;AAAA,QAClC;AAAA,MACF,WAAW,OAAO,CAAC,MAAM,UAAU;AACjC,qBAAa,OAAO,OAAO,CAAC;AAC5B,cAAM,SACJ,KAAK,SAAS,SACV,mBAAmB,OAAO,CAAC,CAAC,IAC5B,kBAAkB,OAAO,CAAC,CAAC;AACjC,qBAAa,QAAQ,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,YAAY,MAAM,CAAC,CAAC;AAC/D,YAAI,KAAK,SAAS,QAAQ;AACxB,gBAAM,EAAE,QAAQ,IAAI,cAAc,IAAI,IAAI;AAC1C,gBAAM,eAAe,IAAI,MAAM,OAAO,CAAC,KAAK;AAC5C,uBAAa,MAAM,CAAC,CAAC,cAAc,kBAAkB,OAAO,CAAC,CAAC;AAAA,QAChE,OAAO;AACL,uBAAa,MAAM,CAAC;AACpB,gBAAM,SAAc,OAAO,IAAI,SAAS,WAAW,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI;AAC9E,iBAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,OAAY;AAC1C,gBAAI,IAAI,MAAM,KAAK,SAAS,GAAG,CAAC,CAAC,GAAG;AAClC,kBAAI,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG;AACxB,6BAAa,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;AAAA,cACzC,OAAO;AACL,6BAAa,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAAA,cACtC;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,WAAW,OAAO,CAAC,MAAM,UAAU;AACjC,qBAAa,OAAO,OAAO,CAAC;AAC5B,cAAM,SACJ,KAAK,SAAS,SACV,mBAAmB,OAAO,CAAC,CAAC,IAC5B,kBAAkB,OAAO,CAAC,CAAC;AACjC,qBAAa,QAAQ,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,YAAY,MAAM,CAAC,CAAC;AAAA,MACjE,OAAO;AACL,YAAI,KAAK,KAAK,GAAG;AACf,uBAAa,KAAK,CAAC,IAAI,KAAK;AAAA,QAC9B;AACA,qBAAa,QAAQ,IAAI,MAAM;AAC/B,cAAM,SACJ,KAAK,SAAS,SACV,mBAAmB,OAAO,CAAC,CAAC,IAC5B,kBAAkB,OAAO,CAAC,CAAC;AACjC,qBAAa,QAAQ,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,YAAY,MAAM,CAAC,CAAC;AAAA,MACjE;AAAA,IACF,OAAO;AACL,mBAAa,KAAK,KAAK;AACvB,mBAAa,QAAQ,SAAS,IAAI,IAAI;AACtC,mBAAa,QAAQ,SAAS,IAAI,IAAI;AACtC,mBAAa,QAAQ,SAAS,IAAI,IAAI;AACtC,mBAAa,QAAQ,SAAS,IAAI,IAAI;AAAA,IACxC;AAEA,WAAO;AAAA,EACT;AAvFS;AAyFT,WAAS,QAAQ,KAAU,OAAY;AACrC,QAAI,KAAK,KAAK,SAAS,cAAc,GAAG;AACtC,YAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO;AACnD,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,cAAM,QAAQ,KAAK,IAAI,CAAC,OAAY;AAClC,cAAI,OAAO,OAAO,UAAU;AAC1B,kBAAMC,OAAM,GAAG,YAAY,GAAG;AAC9B,mBAAOA,OAAM,KAAK,GAAG,UAAU,GAAGA,IAAG,IAAI;AAAA,UAC3C;AACA,gBAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ;AACtC,cAAI,UAAkB,OAAO,OAAO,EAAE,UAAU,OAAO,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;AACpF,gBAAM,MAAM,QAAQ,YAAY,GAAG;AACnC,iBAAO,MAAM,KAAK,QAAQ,UAAU,GAAG,GAAG,IAAI;AAAA,QAChD,CAAC;AACD,cAAM,WAAW,MAAM,IAAI,CAAC,UAAkB,EAAE,MAAM,MAAM,KAAK,EAAE;AACnE,YAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,EAAE,SAAS;AAC5C,cAAM,OAAO;AACb,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AArBS;AAuBT,WAAS,sBAAsB,QAAa,OAAY;AACtD,QAAI,OAAO;AACX,QAAI,QAAQ,OAAO,UAAU,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,GAAG;AACrE,aAAO,KAAK,CAAC;AAAA,IACf;AACA,QAAI,KAAK,SAAS,UAAU,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AACpF,YAAM,UAAU,IAAI,OAAO,OAAO,CAAC,KAAK;AACxC,YAAM,aAAa,IAAI,OAAO,OAAO,CAAC,KAAK;AAC3C,UAAI,KAAK,OAAO,KAAK,MAAM;AACzB,aAAK,OAAO,IAAI,aAAa,OAAO,KAAK,OAAO,CAAC,CAAC;AAAA,MACpD;AACA,YAAM,MAAM,KAAK,UAAU;AAC3B,UAAI,OAAO,QAAQ,UAAU;AAC3B,cAAM,OAAO,IAAI,KAAK;AACtB,YAAI,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,GAAG;AAChD,cAAI;AACF,iBAAK,UAAU,IAAI,KAAK,MAAM,IAAI;AAAA,UACpC,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAxBS;AA0BT,WAAS,SAAS,KAAU,OAAY;AACtC,QAAI,KAAK,YAAY,KAAK,SAAS,CAAC,GAAG;AACrC,YAAM,OAAO,MAAM,KAAK,OAAO,SAAS,KAAK,UAAU,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC,CAAC;AAAA,IACrF;AACA,WAAO;AAAA,EACT;AALS;AAOT,WAAS,eAAe,KAAU,KAAU,KAAU;AACpD,UAAM,SAAS,kBAAkB,KAAK,GAAG;AACzC,QAAI,QAAQ;AACV,iBAAW,MAAM,MAAM,EACpB,KAAK,CAAC,UAAe;AACpB,YAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,WAAW,SAAS,KAAK,QAAQ,KAAK,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,MAC3F,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,cAAM,MAAM,OAAO,OAAO,WAAW,SAAS,EAAE;AAChD,YAAI,QAAQ,SAAS,YAAY,IAAI,SAAS,eAAe,GAAG;AAC9D,cAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC;AACzD;AAAA,QACF;AACA,YAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,MACtD,CAAC;AAAA,IACL,OAAO;AACL,UAAI,IAAI,KAAK,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,IACvC;AAAA,EACF;AAlBS;AAoBT,WAAS,cAAc,KAAU,KAAU,KAAU;AACnD,UAAM,SAAS,kBAAkB,KAAK,GAAG;AACzC,QAAI,UAAU,OAAO,WAAW,UAAU,YAAY;AACpD,UAAI;AACF,mBAAW,MAAM,MAAM,EACpB,KAAK,CAAC,UAAe;AACpB,cAAI,UAAe,sBAAsB,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACpE,cAAI,QAAQ,OAAO,KAAK,QAAQ,OAAO,SAAS,GAAG;AACjD,gBAAI,WAAkB,CAAC;AACvB,gBAAI,OAAO,OAAO,MAAM,GAAG,GAAG,SAAS,GAAG;AACxC,yBAAW,CAAC,GAAG,CAAC,OAAO,OAAO,MAAM,GAAG,IAAI,CAAC,CAAC;AAAA,YAC/C,OAAO;AACL,yBAAW,OAAO,MAAM,MAAM,GAAG;AACjC,yBAAW,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAAA,YACvD;AACA,gBAAI,QAAQ,MAAM,QAAQ;AACxB,sBAAQ,OAAO,QAAQ,KAAK,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAAA,YAC9D;AAAA,UACF;AACA,oBAAU,SAAS,KAAK,OAAO;AAC/B,cAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,WAAW,SAAS,GAAG,CAAC,CAAC;AAAA,QAChE,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,gBAAM,MAAM,OAAO,OAAO,WAAW,SAAS,EAAE;AAChD,cAAI,QAAQ,SAAS,YAAY,IAAI,SAAS,eAAe,GAAG;AAC9D,gBAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC;AACzD;AAAA,UACF;AACA,cAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,QACtD,CAAC;AAAA,MACL,QAAQ;AACN,YAAI,IAAI,KAAK,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,MACvC;AAAA,IACF,OAAO;AACL,UAAI,IAAI,KAAK,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,IACvC;AAAA,EACF;AApCS;AAsCT,WAAS,KAAK,KAAU,KAAU,SAAiB,KAAU;AAC3D,QAAI,KAAK,QAAQ,OAAO,IAAI,SAAS,YAAY;AAC/C,cAAQ,QAAQ,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,UAAU,CAAC,EACzD,KAAK,CAAC,YAAY;AACjB,YAAI,CAAC,QAAS,gBAAe,KAAK,KAAK,GAAG;AAAA,MAC5C,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,YAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,MACtD,CAAC;AACH;AAAA,IACF;AACA,mBAAe,KAAK,KAAK,GAAG;AAAA,EAC9B;AAZS;AAcT,WAAS,IAAI,KAAU,KAAU,SAAiB,KAAU;AAC1D,QAAI,KAAK,OAAO,OAAO,IAAI,QAAQ,YAAY;AAC7C,cAAQ,QAAQ,IAAI,IAAI,KAAK,KAAK,SAAS,KAAK,UAAU,CAAC,EACxD,KAAK,CAAC,YAAY;AACjB,YAAI,CAAC,QAAS,eAAc,KAAK,KAAK,GAAG;AAAA,MAC3C,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,YAAI,IAAI,KAAK,UAAU,MAAM,KAAK,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,MACtD,CAAC;AACH;AAAA,IACF;AACA,kBAAc,KAAK,KAAK,GAAG;AAAA,EAC7B;AAZS;AAcT,SAAO,EAAE,YAAY,MAAM,IAAI;AACjC,GAlVe;;;ACFf,IAAO,kBAAQ,wBAAC,UAAe;AAE7B,WAASC,aAAe,KAAW;AACjC,QAAI,OAAO,OAAO,QAAQ,YAAY,aAAc,KAAgB;AAClE,YAAM,IAAK,IAAkC;AAC7C,UAAI,MAAM,OAAW,QAAO;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AANS,SAAAA,cAAA;AAUT,WAAS,eAAe,KAAkB;AACxC,UAAM,UAAU,IAAI,QAAQ,QAAQ,IAAI,MAAM;AAC9C,WAAO,mBAAmB,OAAO;AAAA,EACnC;AAHS;AAQT,WAAS,YAAY,KAAU,MAAW,KAAU;AAClD,UAAM,WAAW,MAAM,KAAK,GAAG,WAAW,MAAM,GAAG;AACnD,QAAI,IAAI,KAAK,UAAU,QAAQ,CAAC;AAAA,EAClC;AAHS;AAQT,WAAS,QAAQ,KAAU,IAAY,QAA4B,KAAW;AAC5E,UAAM,YAAY,MAAM,MAAM;AAC9B,eAAW,iBAAiB,KAAK;AACjC,eAAW,WAAW,OAAO,IAAI,MAAM,QAAQ,MAAM,IAAI,OAAO,IAAI,MAAM,IAAI,UAAU,OAAO,CAAC,OAAO,MAAM,CAAC,IAAI,MAAS;AAC3H,UAAM,WAAW,MAAM,KAAK,GAAG,OAAO,IAAI,QAAQ,GAAG;AACrD,QAAI,IAAI,KAAK,UAAU,QAAQ,CAAC;AAAA,EAClC;AANS;AAWT,WAAS,SAAS,KAAU,KAAU,KAAW;AAC/C,UAAM,YAAY,MAAM,MAAM;AAC9B,eAAW,iBAAiB,KAAK;AACjC,UAAM,aAAa,WAAW,sBAAsB,GAAG;AACvD,QAAI,YAAY,IAAI;AAClB,aAAO,QAAQ,KAAK,WAAW,IAAI,WAAW,IAAI,GAAG;AAAA,IACvD;AACA,UAAM,WAAW,MAAM,KAAK,GAAG,QAAQ,GAAG;AAC1C,QAAI,IAAI,KAAK,UAAU,QAAQ,CAAC;AAAA,EAClC;AATS;AAcT,WAAS,SAAS,KAAU;AAC1B,KAAC,OAAO,QAAQ,QAAQ,KAAK,GAAG,GAAG;AAAA,EACrC;AAFS;AAGT,SAAO,EAAE,aAAAA,cAAa,gBAAgB,aAAa,UAAU,SAAS,MAAM;AAC9E,GAzDe;;;ACAf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAGjB,eAAsB,WAAW,UAAiC;AAChE,QAAM,aAAaC,MAAK,UAAU,QAAQ;AAC1C,QAAMC,IAAG,MAAMD,MAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,QAAM,KAAK,MAAMC,IAAG,KAAK,YAAY,GAAG;AACxC,QAAM,GAAG,MAAM;AACjB;AALsB;AAOtB,eAAsB,WAAW,UAAoC;AACnE,MAAI;AACF,UAAMA,IAAG,OAAOD,MAAK,UAAU,QAAQ,CAAC;AACxC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAPsB;AAStB,eAAsB,SAAsB,UAA8B;AACxE,QAAM,MAAM,MAAMC,IAAG,SAASD,MAAK,UAAU,QAAQ,GAAG,MAAM;AAC9D,SAAO,KAAK,MAAM,GAAG;AACvB;AAHsB;AAMf,SAAS,qBAAqB,SAAiB,SAAyB;AAC7E,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,UAAM,IAAI,MAAM,cAAc;AAAA,EAChC;AACA,MAAI,QAAQ,SAAS,IAAI,GAAG;AAC1B,UAAM,IAAI,MAAM,cAAc;AAAA,EAChC;AACA,QAAM,OAAOA,MAAK,QAAQ,OAAO;AACjC,QAAM,SAASA,MAAK,QAAQ,MAAM,QAAQ,QAAQ,OAAO,GAAG,CAAC;AAC7D,QAAM,MAAMA,MAAK,SAAS,MAAM,MAAM;AACtC,MAAI,IAAI,WAAW,IAAI,KAAKA,MAAK,WAAW,GAAG,GAAG;AAChD,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACpC;AACA,SAAO;AACT;AAdgB;AAiBhB,eAAsB,WAAW,KAAa;AAC5C,QAAM,WAAWA,MAAK,QAAQ,GAAG;AACjC,QAAM,QAAQ,MAAMC,IAAG,KAAK,QAAQ;AACpC,MAAI,CAAC,MAAM,YAAY,GAAG;AACxB,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AACA,QAAM,UAAUD,MAAK,SAAS,QAAQ;AACtC,QAAM,UAAU,MAAMC,IAAG,QAAQ,UAAU,EAAE,eAAe,KAAK,CAAC;AAClE,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,QAAQ,IAAI,OAAO,UAAU;AAC3B,YAAM,WAAWD,MAAK,KAAK,UAAU,MAAM,IAAI;AAC/C,YAAM,KAAK,MAAMC,IAAG,KAAK,QAAQ;AACjC,YAAM,MAAM,MAAM,KAAK,YAAY,GAAG;AACtC,YAAM,OAAO,MAAM,YAAY,IAC3B,QACA,MAAM,KACJ,MAAM,KAAK,UAAU,GAAG,IACxB;AACN,aAAO;AAAA,QACL,MAAM,MAAM;AAAA,QACZ,MAAM,GAAG;AAAA,QACT,MAAM,GAAG,MAAM,YAAY;AAAA,QAC3B,MAAMD,MAAK,UAAU,QAAQ;AAAA,QAC7B;AAAA,QACA,SAAS,GAAG,UAAU,YAAY;AAAA,QAClC,aAAa,GAAG,KAAK,SAAS,CAAC,EAAE,MAAM,EAAE;AAAA,MAC3C;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,MAAM;AAAA,IACZ,MAAM,MAAM,MAAM,YAAY;AAAA,IAC9B,MAAMA,MAAK,UAAU,QAAQ;AAAA,IAC7B,MAAM;AAAA,IACN,SAAS,MAAM,UAAU,YAAY;AAAA,IACrC,aAAa,MAAM,KAAK,SAAS,CAAC,EAAE,MAAM,EAAE;AAAA,IAC5C;AAAA,EACF;AACF;AAvCsB;AA0CtB,eAAsB,WAAW,UAAiC;AAChE,MAAI;AACF,UAAMC,IAAG,OAAOD,MAAK,UAAU,QAAQ,CAAC;AAAA,EAC1C,SAAS,KAAc;AACrB,QAAK,KAA+B,SAAS,SAAU,OAAM;AAAA,EAC/D;AACF;AANsB;AAQf,IAAM,SAAS;AAGtB,eAAsB,MAAM,UAAkB,SAAgC;AAC5E,QAAM,aAAaA,MAAK,UAAU,QAAQ;AAC1C,QAAMC,IAAG,MAAMD,MAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,QAAMC,IAAG,UAAU,YAAY,SAAS,MAAM;AAChD;AAJsB;AAOtB,eAAsB,KAAK,UAAmC;AAC5D,SAAOA,IAAG,SAASD,MAAK,UAAU,QAAQ,GAAG,MAAM;AACrD;AAFsB;AAKtB,eAAsB,UAAU,UAAkB,MAA8B;AAC9E,QAAM,MAAM,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACrD;AAFsB;;;AC/GtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,YAAYE,UAAQ;AACpB,YAAYC,eAAc;AAOnB,SAAS,eAAwB;AACtC,SAAO,OAAQ,QAAuB,QAAQ;AAChD;AAFgB;AAQT,SAAS,oBAAwC;AACtD,MAAI,CAAC,aAAa,EAAG,QAAO;AAC5B,QAAM,QACH,QAAuB,KAAK,cAC5B,QAAuB,KAAK;AAC/B,MAAI,CAAC,MAAO,QAAO;AACnB,SAAgB,kBAAiB,kBAAQ,KAAK,CAAC;AACjD;AAPgB;AAUT,SAAS,cAAsB;AACpC,QAAM,WAAW,kBAAkB;AACnC,MAAI,SAAU,QAAO;AAErB,QAAM,QAAQ,QAAQ,KAAK,CAAC;AAC5B,MAAI,CAAC,OAAO;AACV,WAAgB,kBAAQ,QAAQ,QAAQ;AAAA,EAC1C;AACA,SAAgB,kBAAiB,kBAAQ,KAAK,CAAC;AACjD;AATgB;AAYT,SAAS,aAAqB;AACnC,SAAgB,kBAAQ,QAAQ,QAAQ;AAC1C;AAFgB;AAQT,SAAS,qBAA+B;AAC7C,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAM,wBAAC,MAA0B;AACrC,QAAI,CAAC,EAAG;AACR,UAAM,MAAe,kBAAQ,CAAC;AAC9B,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,WAAK,IAAI,GAAG;AACZ,YAAM,KAAK,GAAG;AAAA,IAChB;AAAA,EACF,GAPY;AASZ,MAAI,QAAQ,IAAI,CAAC;AACjB,MAAI,WAAW,CAAC;AAEhB,MAAI,aAAa,GAAG;AAClB,QAAI,kBAAkB,CAAC;AAAA,EACzB,OAAO;AACL,UAAM,WAAW,YAAY;AAC7B,QAAI,aAAa,WAAW,GAAG;AAC7B,UAAI,QAAQ;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AACT;AAzBgB;AA4BT,SAAS,uBAA+B;AAC7C,aAAW,QAAQ,mBAAmB,GAAG;AACvC,QAAI;AACF,UAAO,cAAkB,eAAK,MAAM,QAAQ,CAAC,EAAE,YAAY,GAAG;AAC5D,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI,aAAa,GAAG;AAClB,WAAO,WAAW;AAAA,EACpB;AACA,SAAO,YAAY;AACrB;AAdgB;;;ACrEhB,IAAO,cAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACxBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAYC,WAAU;AAcf,SAAS,eACd,OACA,KACkB;AAClB,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAM,KAAK,CAAC,KAAK,WAAW;AAC1B,UAAI,KAAK;AACP,eAAO,GAAG;AACV;AAAA,MACF;AACA,UAAI,CAAC,UAAW,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,GAAI;AAC7D,QAAAA,SAAQ,EAAE;AACV;AAAA,MACF;AACA,MAAAA,SAAQ,MAAM;AAAA,IAChB,CAAC;AAAA,EACH,CAAC;AACH;AAjBgB;AAoBT,SAAS,aAAa,OAA+B;AAC1D,MAAI,CAAC,MAAO,QAAO,CAAC;AACpB,SAAO,OAAO,UAAU,WAAW,MAAM,MAAM,GAAG,IAAI;AACxD;AAHgB;AAMT,SAAS,aAAa,OAA0C;AACrE,MAAI,CAAC,SAAS,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AAC7C,QAAM,QAA6B,CAAC;AACpC,aAAW,QAAQ,OAAO;AACxB,QAAI,OAAO,SAAS,SAAU;AAC9B,QAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,UAAU,GAAG;AAC3C,YAAM,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;AAAA,IAC/B;AAAA,EACF;AACA,SAAO;AACT;AAVgB;AAaT,SAAS,YAAY,KAA0C;AACpE,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,MAAI,OAAO,QAAQ,SAAU,QAAO,CAAC;AACrC,QAAM,MAA+B,CAAC;AACtC,aAAW,QAAQ,KAAK;AACtB,QAAI,OAAO,SAAS,SAAU;AAC9B,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAI,KAAK,UAAU,KAAK,OAAO,KAAK,CAAC,MAAM,UAAU;AACnD,YAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC;AAAA,MACvB,WAAW,KAAK,UAAU,GAAG;AAC3B,YAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAfgB;AAkBT,SAAS,aAAa,KAAqC;AAChE,QAAM,SAAS,aAAa,IAAI,KAAK;AACrC,QAAM,SAAS,IAAI;AACnB,MAAI,CAAC,OAAO,UAAU,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACtD,SAAQ,OAAuB,IAAI,CAAC,QAAQ;AAC1C,UAAM,SAAkC,CAAC;AACzC,WAAO,QAAQ,CAAC,OAAO,UAAU;AAC/B,aAAO,KAAK,IAAI,IAAI,KAAK;AAAA,IAC3B,CAAC;AACD,WAAO;AAAA,EACT,CAAC;AACH;AAXgB;AAiBT,SAAS,aAAa,SAAiB,YAA6B;AACzE,QAAM,OAAY,cAAQ,OAAO;AACjC,QAAM,SAAc,cAAQ,UAAU;AACtC,QAAMC,YAAgB,eAAS,MAAM,MAAM;AAC3C,MAAI,CAACA,UAAU,QAAO;AACtB,SAAO,CAACA,UAAS,WAAW,IAAI,KAAK,CAAM,iBAAWA,SAAQ;AAChE;AANgB;AAYT,SAAS,cAAc,UAAkB,UAA4B;AAC1E,QAAM,QAAQ,CAAC,MAAM,QAAQ,OAAO,GAAG,GAAG,GAAG,SAAS,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,QAAQ,OAAO,GAAG,CAAC,CAAC;AAC/F,SAAO,MAAM,OAAO,OAAO,EAAE,KAAK,GAAG;AACvC;AAHgB;AAMT,SAAS,WAAW,OAA8B;AACvD,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,SAAS,IAAI;AACzD,SAAO,MAAM,SAAS,IAAI;AAC5B;AAJgB;AAOT,SAAS,oBAAoB,KAAsE;AACxG,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,MAAM,IAAI,WAAW;AAC3B,MAAI,IAAI,SAAS,sBAAsB,IAAI,SAAS,gBAAgB;AAClE,WAAO,IAAI,SAAS,eAAe,KAAK,IAAI,SAAS,eAAe;AAAA,EACtE;AACA,SAAO,IAAI,SAAS,eAAe,KAAK,IAAI,SAAS,eAAe;AACtE;AAPgB;;;AC3GhB,SAAS,WAAW,OAAuB;AACzC,QAAM,OAAO,OAAO,KAAK,EAAE,QAAQ,MAAM,IAAI;AAC7C,SAAO,IAAI,IAAI;AACjB;AAHS;AAMT,SAAS,iBAAiB,OAA0C;AAClE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,OAAQ,QAAO;AAEnD,QAAM,QAAkB,CAAC;AACzB,MAAI,YAAY;AAEhB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,SAAS,QAAQ,SAAS,OAAO;AACnC,kBAAY;AACZ;AAAA,IACF;AACA,QAAI,CAAC,MAAM,QAAQ,IAAI,EAAG;AAC1B,UAAM,CAAC,OAAO,IAAI,GAAG,IAAI;AACzB,QAAI,CAAC,MAAM,QAAQ;AACjB,YAAM,KAAK,GAAG,KAAK,IAAI,EAAE,IAAI,GAAG,EAAE;AAAA,IACpC,OAAO;AACL,YAAM,KAAK,GAAG,SAAS,IAAI,KAAK,IAAI,EAAE,IAAI,GAAG,EAAE;AAAA,IACjD;AAAA,EACF;AAEA,SAAO,MAAM,SAAS,UAAU,MAAM,KAAK,GAAG,CAAC,KAAK;AACtD;AAtBS;AAyBT,SAAS,iBAAiB,OAA0C;AAClE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,OAAQ,QAAO;AACnD,QAAM,QAAQ,MAAM,IAAI,CAAC,IAAI,MAAM;AACjC,UAAM,SAAS,IAAI,IAAI,MAAM;AAC7B,WAAO,GAAG,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;AAAA,EACpC,CAAC;AACD,SAAO,YAAY,MAAM,KAAK,EAAE,CAAC;AACnC;AAPS;AAUT,SAAS,iBAAiB,OAAwB;AAChD,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,IAAI,OAAO,KAAK;AACtB,MAAI,kBAAkB,KAAK,CAAC,EAAG,QAAO;AACtC,MAAI,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG,EAAG,QAAO;AACjD,SAAO,IAAI,EAAE,QAAQ,MAAM,IAAI,CAAC;AAClC;AANS;AAST,SAAS,iBAAiB,QAA2C;AACnE,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,CAAC,OAAO,OAAQ,QAAO;AACrD,QAAM,OAAQ,OAAuB,IAAI,CAAC,QAAQ,IAAI,IAAI,IAAI,gBAAgB,EAAE,KAAK,GAAG,CAAC,GAAG;AAC5F,SAAO,WAAW,KAAK,KAAK,GAAG,CAAC;AAClC;AAJS;AAOT,SAAS,eAAe,MAAuC;AAC7D,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC,KAAK,OAAQ,QAAO;AAEjD,QAAM,QAAQ,KAAK,IAAI,CAAC,MAAM,MAAM;AAClC,UAAM,SAAS,IAAI,IAAI,MAAM;AAC7B,UAAM,KAAK;AACX,UAAM,CAAC,OAAO,SAAS,GAAG,IAAI;AAE9B,QAAI,OAAO,QAAQ,YAAY,SAAS;AACtC,aAAO,GAAG,MAAM,GAAG,KAAK,IAAI,KAAK,GAAG,OAAO,GAAG,GAAG;AAAA,IACnD;AACA,QAAI,OAAO,QAAQ,YAAY,SAAS;AACtC,UAAI,YAAY,UAAU;AACxB,eAAO,GAAG,MAAM,GAAG,KAAK,IAAI,OAAO,IAAI,KAAK,KAAK,GAAG;AAAA,MACtD;AACA,aAAO,GAAG,MAAM,GAAG,KAAK,IAAI,KAAK,GAAG,OAAO,IAAI,GAAG;AAAA,IACpD;AACA,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,GAAG,MAAM,GAAG,KAAK,IAAI,OAAO;AAAA,IACrC;AACA,WAAO,GAAG,MAAM,GAAG,KAAK,KAAK,OAAO;AAAA,EACtC,CAAC;AAED,SAAO,QAAQ,MAAM,KAAK,EAAE,CAAC;AAC/B;AAxBS;AA2BT,SAAS,iBAAiB,QAA2C;AACnE,QAAM,OAAO,aAAa,MAAM;AAChC,SAAO,KAAK,SAAS,KAAK,KAAK,KAAK,GAAG,CAAC,MAAM;AAChD;AAHS;AAKT,IAAO,cAAQ;AAAA;AAAA;AAAA;AAAA,EAIb,QAAQ,KAAU,MAAwB;AACxC,UAAM,MAAM,IAAI,IAAI;AACpB,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,UAAI,CAAC,IAAI,OAAQ,QAAO;AACxB,cAAQ,MAAM;AAAA,QACZ,KAAK;AACH,iBAAO,iBAAiB,GAAgC;AAAA,QAC1D,KAAK;AACH,iBAAO,iBAAiB,GAAgC;AAAA,QAC1D,KAAK;AACH,iBAAO,iBAAiB,GAAgC;AAAA,QAC1D,KAAK;AACH,iBAAO,eAAe,GAA8B;AAAA,QACtD,KAAK;AACH,iBAAO,iBAAiB,GAAgC;AAAA,MAC5D;AAAA,IACF;AACA,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,MAAM,OAAO,GAAG;AACtB,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,UAAU,GAAG;AAAA,MACtB,KAAK;AACH,eAAO,aAAa,GAAG;AAAA,MACzB,KAAK;AACH,eAAO,YAAY,GAAG;AAAA,MACxB,KAAK;AACH,eAAO,QAAQ,GAAG;AAAA,MACpB,KAAK;AACH,eAAO,KAAK,GAAG;AAAA,MACjB;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,KAAkB;AACxB,UAAM,QAAQ,WAAW,IAAI,KAAK;AAClC,UAAM,KAAK,IAAI;AACf,YAAQ,IAAI;AAAA,MACV,KAAK;AACH,eAAO,eAAe,KAAK,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC;AAAA,MACvF,KAAK;AACH,eAAO,eAAe,KAAK,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC;AAAA,MAC1D,KAAK;AACH,eAAO,UAAU,KAAK,GAAG,KAAK,QAAQ,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC;AAAA,MAChF,KAAK,UAAU;AACb,cAAM,SAAS,IAAI,QAAQ,IAAI,IAAI,KAAK,KAAK;AAC7C,cAAM,QAAQ,IAAI,QAAQ,UAAU,IAAI,KAAK,KAAK;AAClD,eAAO,SAAS,MAAM,SAAS,KAAK,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC,GAAG,KAAK,QAAQ,KAAK,OAAO,CAAC,GAAG,KAAK;AAAA,MACxG;AAAA,MACA;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,KAAU,UAAuC,SAAiB;AAC1E,UAAM,SAAS,YAAY,WAAW,kBAAkB;AACxD,UAAM,SAAS,aAAa,IAAI,KAAK;AACrC,UAAM,UAAoB,CAAC;AAE3B,QAAI,CAAC,WAAW,IAAI,KAAK,GAAG;AAC1B,cAAQ,KAAK,0BAA0B,MAAM,EAAE;AAAA,IACjD;AACA,WAAO,QAAQ,CAAC,SAAS,QAAQ,KAAK,GAAG,IAAI,OAAO,CAAC;AACrD,UAAM,YACJ,YAAY,WAAW,0CAA0C;AACnE,YAAQ,KAAK,SAAS;AAEtB,WAAO,8BAA8B,WAAW,IAAI,KAAK,CAAC,KAAK,QAAQ,KAAK,GAAG,CAAC;AAAA,EAClF;AACF;;;ACjLA,YAAYC,UAAQ;AACpB,YAAYC,WAAU;AAGtB,SAAS,SAAS,MAAW,CAAC,GAAoC;AAEhE,QAAM,EAAE,KAAK,SAAS,IAAI;AAC1B,QAAM,EAAE,cAAAC,eAAc,eAAAC,eAAc,IAAI;AAAA,EASxC,MAAM,OAAO;AAAA,IAhBf,OAgBe;AAAA;AAAA;AAAA,IAOX,YAAY,QAAsB;AAChC,WAAK,SAAS;AACd,WAAK,UAAU,OAAO,QAAQ,OAAO,KAAK,OAAO,OAAO;AACxD,WAAK,WAAW,OAAO,OAAO,OAAO;AACrC,WAAK,YAAY,OAAO,UAAU;AAClC,WAAK,aAAkB,cAAQ,QAAQ,IAAI,GAAG,OAAO,GAAG;AAAA,IAC1D;AAAA,IAEQ,SAAS,MAAa;AAC5B,OAAC,KAAK,QAAQ,OAAO,QAAQ,QAAQ,KAAK,QAAQ,GAAG,IAAI;AAAA,IAC3D;AAAA,IAEA,UAAU,MAAuB;AAC/B,aAAU,gBAAW,KAAK,WAAW,MAAM,KAAK,CAAC;AAAA,IACnD;AAAA;AAAA,IAGQ,YAAY,SAAyB;AAC3C,UAAI,CAAC,SAAS;AACZ,eAAO,KAAK;AAAA,MACd;AACA,YAAM,MAAW,iBAAW,OAAO,IAAS,gBAAU,OAAO,IAAS,cAAQ,KAAK,YAAY,OAAO;AACtG,UAAI,CAACD,cAAa,KAAK,YAAY,GAAG,GAAG;AACvC,eAAO,KAAK;AAAA,MACd;AACA,aAAO;AAAA,IACT;AAAA;AAAA,IAGQ,cAAc,UAAkB,UAA4B;AAClE,aAAOC,eAAc,OAAO,GAAG,QAAQ;AAAA,IACzC;AAAA,IAEQ,iBAAiB,SAAyB;AAChD,UAAI,CAAC,SAAS;AACZ,eAAO;AAAA,MACT;AACA,aAAY,iBAAW,OAAO,IAAS,eAAS,KAAK,YAAY,OAAO,IAAI;AAAA,IAC9E;AAAA,IAEQ,UAAU,SAAyB;AACzC,YAAMC,YAAW,KAAK,iBAAiB,OAAO;AAC9C,YAAM,UAAe,cAAQA,SAAQ;AACrC,YAAM,SAAS,KAAK,YAAY,YAAY,MAAM,KAAK,OAAO;AAC9D,UAAI,KAAK,aAAa,CAAI,gBAAW,MAAM,GAAG;AAC5C,aAAK,MAAM,SAAS,WAAW,MAAM;AACrC,QAAG,eAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,MAC1C;AACA,aAAO;AAAA,IACT;AAAA,IAEQ,WAAW,MAAc,gBAAyB,MAAc;AACtE,UAAI,MAAM;AACV,UAAI,KAAK,WAAW,CAAC,IAAI,SAAS,KAAK,OAAO,GAAG;AAC/C,eAAO,KAAK;AAAA,MACd;AACA,UAAI,eAAe;AACjB,aAAK,UAAU,GAAG;AAAA,MACpB;AACA,aAAO,KAAK,YAAY,GAAG;AAAA,IAC7B;AAAA,IAEA,OAAO,cAA4B;AACjC,YAAM,UAAU,KAAK,YAAY,YAAY;AAC7C,UAAI,CAAI,gBAAW,OAAO,GAAG;AAC3B;AAAA,MACF;AAEA,WAAK,MAAM,UAAU,WAAW,OAAO;AACvC,YAAM,UAAa,iBAAY,SAAS,EAAE,eAAe,KAAK,CAAC;AAC/D,iBAAW,SAAS,SAAS;AAC3B,cAAM,UAAe,WAAK,SAAS,MAAM,IAAI;AAC7C,YAAI,MAAM,YAAY,GAAG;AACvB,eAAK,OAAY,WAAK,cAAc,MAAM,IAAI,CAAC;AAAA,QACjD,OAAO;AACL,eAAK,MAAM,UAAU,YAAY,OAAO;AACxC,UAAG,gBAAW,OAAO;AAAA,QACvB;AAAA,MACF;AACA,MAAG,eAAU,OAAO;AAAA,IACtB;AAAA,IAEQ,YAAY,MAAc,KAAyC;AACzE,YAAM,aAAqC,CAAC;AAE5C,UAAI,KAAK,UAAU;AACjB,mBAAW,KAAK,EAAE,KAAU,WAAK,MAAM,IAAI,QAAQ,EAAE,CAAC;AACtD,mBAAW,KAAK,EAAE,KAAU,WAAK,OAAO,YAAY,KAAK,SAAS,IAAI,QAAQ,EAAE,CAAC;AAAA,MACnF,OAAO;AACL,mBAAW,KAAK,EAAE,KAAK,KAAK,CAAC;AAC7B,mBAAW,KAAK,EAAE,KAAK,OAAO,KAAK,UAAU,UAAU,CAAC;AAAA,MAC1D;AAEA,iBAAW,aAAa,YAAY;AAClC,cAAM,MAAM,KAAK,WAAW,UAAU,KAAK,KAAK;AAChD,YAAO,gBAAW,GAAG,GAAG;AACtB,iBAAO,EAAE,MAAM,KAAK,KAAK,UAAU,IAAI;AAAA,QACzC;AAAA,MACF;AAEA,aAAO,EAAE,MAAM,IAAI,KAAK,GAAG;AAAA,IAC7B;AAAA,IAEQ,WAAW,MAAc,KAAyC;AACxE,YAAMC,QAAO,KAAK,YAAY,MAAM,GAAG;AACvC,UAAI,CAACA,MAAK,MAAM;AACd,eAAO,EAAE,MAAM,IAAI,KAAKA,MAAK,IAAI;AAAA,MACnC;AACA,UAAI,KAAK,UAAU;AACjB,eAAO,EAAE,MAAW,cAAQA,MAAK,IAAI,GAAG,KAAU,cAAQA,MAAK,GAAG,EAAE;AAAA,MACtE;AACA,aAAO,EAAE,MAAMA,MAAK,MAAM,KAAKA,MAAK,IAAI;AAAA,IAC1C;AAAA,IAEQ,WAAW,MAAc,KAAkB;AACjD,UAAI,KAAK,UAAU;AACjB,eAAO,KAAK,WAAgB,WAAK,MAAM,IAAI,QAAQ,GAAG,IAAI;AAAA,MAC5D;AACA,aAAO,KAAK,WAAW,MAAM,IAAI;AAAA,IACnC;AAAA,IAEA,MAAM,MAAc,MAAW,KAA0B;AACvD,UAAI;AACF,cAAM,WAAW,KAAK,SAAS,WAAW,KAAK,WAAW,MAAM,GAAG,IAAI,KAAK,YAAY,MAAM,GAAG,EAAE,QAAQ,KAAK,WAAW,MAAM,GAAG;AACpI,aAAK,MAAM,SAAS,WAAW,QAAQ;AACvC,QAAG,mBAAc,UAAU,MAAM,MAAM;AACvC,eAAO;AAAA,MACT,SAAS,GAAG;AACV,aAAK,MAAM,gBAAgB,iBAAiB,CAAC;AAC7C,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,KAAK,MAAc,KAAU,WAA2B,QAAa;AACnE,UAAI;AACF,cAAMA,QAAO,KAAK,YAAY,MAAM,GAAG;AACvC,YAAI,CAACA,MAAK,MAAM;AACd,iBAAO,EAAE,OAAO,QAAQ;AAAA,QAC1B;AACA,aAAK,MAAM,QAAQ,UAAUA,MAAK,IAAI;AACtC,cAAM,OAAU,kBAAaA,MAAK,MAAM,EAAE,SAAS,CAAC,KAAK;AACzD,cAAM,WAAW,KAAK,WAAWA,MAAK,IAAI,SAAS,KAAK,OAAO,IAAIA,MAAK,MAAMA,MAAK,MAAM,KAAK;AAC9F,eAAO,CAAC,EAAE,MAAM,MAAM,SAAS,CAAC;AAAA,MAClC,SAAS,GAAG;AACV,aAAK,MAAM,eAAe,gBAAgB,CAAC;AAC3C,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,IAAI,MAAc,KAA0B;AAC1C,UAAI;AACF,cAAM,MAAM,KAAK,WAAW,MAAM,GAAG;AACrC,YAAI,CAAC,IAAI,MAAM;AACb,iBAAO;AAAA,QACT;AAEA,YAAI,KAAK,WAAW,KAAK,SAAS;AAChC,gBAAM,SAAS,IAAI,OAAO,YAAY,KAAK;AAC3C,eAAK,MAAM,eAAe,iBAAiB,GAAG,IAAI,IAAI,OAAO,MAAM,EAAE;AACrE,UAAG,gBAAW,IAAI,MAAM,MAAM;AAAA,QAChC,WAAW,KAAK,UAAU;AACxB,eAAK,OAAO,IAAI,GAAG;AAAA,QACrB,OAAO;AACL,eAAK,MAAM,UAAU,YAAY,IAAI,IAAI;AACzC,UAAG,gBAAW,IAAI,IAAI;AAAA,QACxB;AACA,eAAO;AAAA,MACT,SAAS,GAAG;AACV,aAAK,MAAM,iBAAiB,kBAAkB,CAAC;AAC/C,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,GAAG,MAAc,KAA0B;AACzC,UAAI;AACF,cAAM,MAAM,KAAK,WAAW,MAAM,GAAG;AACrC,YAAI,CAAC,IAAI,MAAM;AACb,iBAAO;AAAA,QACT;AACA,YAAI,KAAK,SAAS;AAChB,gBAAM,aAAa,KAAK,UAAU,KAAK,QAAQ,QAAQ,OAAO,KAAK,IAAI;AACvE,gBAAM,WAAW,IAAI,KAAK,QAAQ,IAAI,OAAO,UAAW,UAAU,GAAG,GAAG,EAAE;AAC1E,cAAI,aAAa,IAAI,MAAM;AACzB,iBAAK,MAAM,WAAW,aAAa,GAAG,IAAI,IAAI,OAAO,QAAQ,EAAE;AAC/D,YAAG,gBAAW,IAAI,MAAM,QAAQ;AAAA,UAClC;AAAA,QACF,OAAO;AACL,eAAK,MAAM,gBAAgB,kBAAkB,IAAI,IAAI;AACrD,UAAG,gBAAW,IAAI,IAAI;AAAA,QACxB;AACA,eAAO;AAAA,MACT,SAAS,GAAG;AACV,aAAK,MAAM,kBAAkB,mBAAmB,CAAC;AACjD,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,KAAK,KAAa,KAAe;AAC/B,UAAI;AACF,cAAM,SAAS,KAAK,YAAY,GAAG;AACnC,aAAK,MAAM,QAAQ,UAAU,MAAM;AACnC,YAAI;AACJ,YAAI;AACF,oBAAa,iBAAY,QAAQ,EAAE,eAAe,KAAK,CAAC;AAAA,QAC1D,QAAQ;AACN,iBAAO,KAAK,OAAO,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,IAAI,CAAC;AAAA,QACjD;AAEA,cAAM,SAAc,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE;AAC3C,cAAM,eAAe,YAAY,KAAK;AACtC,mBAAW,SAAS,SAAS;AAC3B,cAAI,CAAC,MAAM,OAAO,EAAG;AACrB,gBAAM,WAAW,MAAM;AACvB,gBAAM,WAAW,SAAS,SAAS,YAAY;AAC/C,gBAAM,WAAW,WAAW,SAAS,MAAM,GAAG,CAAC,aAAa,MAAM,IAAI;AACtE,cAAI,KAAK,WAAW,CAAC,SAAS,SAAS,KAAK,OAAO,EAAG;AACtD,gBAAM,WAAgB,WAAK,QAAQ,QAAQ;AAC3C,cAAI;AACF,kBAAM,OAAU,kBAAa,UAAU,MAAM;AAC7C,kBAAM,YAAY,EAAE,MAAM,MAAM,SAAS;AACzC,gBAAI,UAAU;AACZ,kBAAI,KAAK,KAAM,QAAO,OAAO,KAAK,SAAS;AAAA,YAC7C,OAAO;AACL,qBAAO,KAAK,KAAK,SAAS;AAAA,YAC5B;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AACA,eAAO,KAAK,OAAO,SAAS,OAAO;AAAA,MACrC,SAAS,GAAG;AACV,aAAK,MAAM,eAAe,gBAAgB,CAAC;AAC3C,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA,IAGQ,qBAAqB,OAA6B;AACxD,UAAI,CAAC,SAAS,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAC5C,YAAM,QAAQ,MAAM,KAAK,CAAC,SAAS,MAAM,QAAQ,IAAI,CAAC;AACtD,YAAM,MAAM,QAAQ,CAAC;AACrB,UAAI,OAAO,QAAQ,UAAU;AAC3B,eAAO,IAAI,QAAQ,YAAY,EAAE;AAAA,MACnC;AACA,aAAO,OAAO,OAAO,EAAE;AAAA,IACzB;AAAA,IAEA,MAAM,KAAwB;AAC5B,aAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,YAAI;AACF,cAAI;AACJ,gBAAM,WAAW,KAAK,cAAc,IAAI,KAAK;AAE7C,cAAI,IAAI,SAAS,UAAU;AACzB,kBAAM,CAAC,MAAM,IAAI,IAAK,IAAI,MAAqB,CAAC;AAChD,qBAAS,KAAK,MAAM,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,MAAM,GAAG;AAAA,UACpE,WAAW,IAAI,SAAS,UAAU;AAChC,kBAAM,OAAO,KAAK,qBAAqB,IAAI,KAAK;AAChD,qBAAS,KAAK,IAAI,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,GAAG;AAAA,UAC5D,WAAW,IAAI,SAAS,MAAM;AAC5B,kBAAM,OAAO,KAAK,qBAAqB,IAAI,KAAK;AAChD,qBAAS,KAAK,GAAG,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,GAAG;AAAA,UAC3D,WAAW,IAAI,SAAS,UAAU;AAChC,kBAAM,OAAO,KAAK,qBAAqB,IAAI,KAAK;AAChD,kBAAM,OAAQ,IAAI,IAAmB,CAAC,EAAE,CAAC;AACzC,qBAAS,KAAK,MAAM,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,MAAM,GAAG;AAAA,UACpE,WAAW,IAAI,SAAS,UAAU;AAChC,gBAAI,KAAK,OAAO,UAAU,KAAK,OAAO,GAAG;AACvC,oBAAM,OAAO,KAAK,qBAAqB,IAAI,KAAK;AAChD,oBAAM,UAAU,KAAK,KAAK,KAAK,cAAc,IAAI,OAAO,IAAI,GAAG,GAAG;AAClE,oBAAM,SAAc,CAAC;AACrB,kBAAI,UAAU,CAAC,GAAG,QAAQ,CAAC,QAAQ,OAAO;AACxC,oBAAI,IAAI,OAAO,GAAG;AAChB,sBAAI;AACF,0BAAM,SAAS,KAAK,MAAM,QAAQ,CAAC,EAAE,IAAI;AACzC,wBAAI,IAAI,OAAO,QAAQ;AACrB,sBAAC,IAAI,MAAmB,QAAQ,CAAC,MAAM;AACrC,+BAAO,CAAC,IAAI,OAAO,CAAC,KAAK;AAAA,sBAC3B,CAAC;AAAA,oBACH,OAAO;AACL,6BAAO,OAAO,QAAQ,MAAM;AAAA,oBAC9B;AAAA,kBACF,QAAQ;AAAA,kBAER;AAAA,gBACF,OAAO;AACL,wBAAM,SAAS,IAAI;AACnB,yBAAO,OAAO,CAAC,CAAC,IAAI,QAAQ,CAAC,EAAE;AAC/B,sBAAI,OAAO,CAAC,GAAG;AACb,2BAAO,OAAO,CAAC,CAAC,IAAI,QAAQ,CAAC,EAAE;AAAA,kBACjC;AAAA,gBACF;AAAA,cACF;AACA,uBAAS,CAAC,MAAM;AAAA,YAClB,OAAO;AACL,oBAAM,UAAU,KAAK,KAAK,UAAU,GAAG;AACvC,kBAAI,WAAW,CAAC,QAAQ,OAAO;AAC7B,oBAAI,KAAK,MAAM;AACb,wBAAM,WAAW,wBAAC,OAAY;AAC5B,0BAAM,SAAS,IAAI;AACnB,0BAAM,OAAY,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG,KAAK;AACzC,wBAAI,OAAO,CAAC,EAAG,MAAK,OAAO,CAAC,CAAC,IAAI,GAAG;AACpC,2BAAO;AAAA,kBACT,GALiB;AAMjB,sBAAI,QAAQ,KAAM,SAAQ,OAAO,QAAQ,KAAK,IAAI,QAAQ;AAC1D,sBAAI,QAAQ,OAAQ,SAAQ,SAAS,QAAQ,OAAO,IAAI,QAAQ;AAChE,2BAAS;AAAA,gBACX,OAAO;AACL,sBAAI,KAAK,OAAO,GAAG;AACjB,wBAAI,QAAQ;AACZ,wBAAI,IAAI,OAAO,QAAQ;AACrB,4BAAM,QAAQ,IAAI;AAClB,4BAAM,YAAY,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAC5D,8BAAQ,MAAM,OAAO,CAAC,OAAY;AAChC,4BAAI,QAAQ,cAAc;AAC1B,iCAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,8BAAI,OAAO,MAAM,CAAC,MAAM,SAAU;AAClC,gCAAM,OAAO,MAAM,CAAC;AACpB,8BAAI,CAAC,KAAM;AACX,gCAAM,QAAQ,KAAK,CAAC;AACpB,gCAAM,YAAY,OAAO,KAAK,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE;AAClD,8BAAI,WAAW;AACf,8BAAI;AACF,uCAAW,KAAK,MAAM,GAAG,IAAI,EAAE,KAAK,KAAK;AAAA,0BAC3C,QAAQ;AAAA,0BAER;AACA,gCAAM,YAAY,OAAO,QAAQ,EAAE,SAAS,SAAS;AACrD,8BAAI,cAAc,OAAO;AACvB,oCAAQ,SAAS;AACjB,gCAAI,CAAC,MAAO;AAAA,0BACd,OAAO;AACL,oCAAQ,SAAS;AACjB,gCAAI,MAAO;AAAA,0BACb;AAAA,wBACF;AACA,+BAAO;AAAA,sBACT,CAAC;AAAA,oBACH;AACA,4BAAQ,MAAM,IAAI,CAAC,OAAY;AAC7B,4BAAM,MAAW,CAAC;AAClB,0BAAI;AACF,8BAAM,SAAS,KAAK,MAAM,GAAG,IAAI;AACjC,4BAAI,IAAI,OAAO,QAAQ;AACrB,0BAAC,IAAI,MAAmB,QAAQ,CAAC,MAAM;AACrC,gCAAI,CAAC,IAAI,OAAO,CAAC,KAAK;AAAA,0BACxB,CAAC;AAAA,wBACH,OAAO;AACL,iCAAO,OAAO,KAAK,MAAM;AAAA,wBAC3B;AAAA,sBACF,QAAQ;AAAA,sBAER;AACA,6BAAO;AAAA,oBACT,CAAC;AACD,wBAAI,IAAI,OAAO,QAAQ;AACrB,4BAAM,aAAa,IAAI,MAAM,CAAC;AAC9B,4BAAM,iBAAiB,OAAO,eAAe,WAAW,aAAa,WAAW,CAAC;AACjF,4BAAM,YAAY,OAAO,eAAe,WAAW,QAAQ,OAAO,WAAW,CAAC,CAAC,EAAE,YAAY;AAC7F,4BAAM,KAAK,CAAC,GAAQ,MAAW;AAC7B,8BAAM,OAAO,OAAO,EAAE,cAAc,KAAK,EAAE;AAC3C,8BAAM,OAAO,OAAO,EAAE,cAAc,KAAK,EAAE;AAC3C,8BAAM,MAAM,KAAK,cAAc,IAAI;AACnC,+BAAO,cAAc,SAAS,CAAC,MAAM;AAAA,sBACvC,CAAC;AAAA,oBACH;AACA,6BAAS;AAAA,kBACX,OAAO;AACL,0BAAM,SAAS,IAAI;AACnB,6BAAS,QAAQ,IAAI,CAAC,QAAa;AAAA,sBACjC,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG;AAAA,sBAChB,GAAI,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG,KAAK,IAAI,CAAC;AAAA,oBAC9C,EAAE;AAAA,kBACJ;AAAA,gBACF;AAAA,cACF,OAAO;AACL,yBAAS,KAAK,OAAO,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,IAAI,CAAC;AAAA,cACnD;AAAA,YACF;AAAA,UACF;AAEA,cAAI,WAAW,QAAW;AACxB,YAAAA,SAAQ,MAAM;AAAA,UAChB,OAAO;AACL,mBAAO,EAAE;AAAA,UACX;AAAA,QACF,SAAS,GAAG;AACV,iBAAO,CAAC;AAAA,QACV;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AA5ZS;AA6ZT,IAAOC,iBAAQ;;;ACtYf,IAAM,eAAe;AAErB,SAAS,kBAAgC;AACvC,SAAOC,eAAO,EAAE,SAAS,CAAC,GAAU,kBAAK,yBAAS,CAAC;AACrD;AAFS;AAIT,SAAS,cAAc,MAAc,WAA8C;AACjF,MAAI,SAAS,cAAc;AACzB,WAAO,gBAAgB;AAAA,EACzB;AACA,QAAM,UAAU,UAAU,IAAI;AAC9B,MAAI,OAAO,YAAY,YAAY;AACjC,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,EAAE,SAAS,CAAC,GAAU,kBAAK,yBAAS,CAAC;AACtD;AATS;AAcT,IAAM,SAAmB,wBAAC,OAAO,cAAc,SAAS,CAAC,GAAG,YAAY,CAAC,MAAM;AAC7E,MAAI,SAAS,cAAc,MAAM,SAAS;AAC1C,MAAI,CAAC,QAAQ;AACX,QAAI,SAAS,cAAc;AACzB,cAAQ;AAAA,QACN,4CAAmB,IAAI,gDAAiC,IAAI;AAAA,MAC9D;AAAA,IACF;AACA,aAAS,gBAAgB;AAAA,EAC3B;AACA,SAAO,IAAI,OAAO,MAAM;AAC1B,GAXyB;AAazB,IAAO,aAAQ;;;AC9CA,SAAR,UAA2B,OAAY,MAA4B,CAAC,GAAS;AAClF,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO,CAAC;AAC/B,QAAM,OAAO,EAAE,GAAG,aAAc,GAAG,MAAM,MAAM,GAAI,OAAO,CAAC,EAAG;AAC9D,QAAM,aAAa;AACnB,QAAM,KAAK,WAAW,iBAAiB,KAAK;AAC5C,MAAI,CAAC,MAAM,KAAK,IAAK,OAAM,KAAK,MAAM,CAAC;AACvC,QAAM,KAAK,MAAM,EAAE,GAAG,aAAc,GAAG,MAAM,KAAK,IAAI;AACtD,MAAI,CAAC,MAAM,KAAK,GAAI,OAAM,KAAK,KAAK,CAAC;AACrC,QAAM,KAAK,KAAK,EAAE,GAAG,YAAa,GAAG,MAAM,KAAK,GAAG;AACrD;AATwB;;;ACRjB,SAAS,oBAAoB,KAA+C;AAClF,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO,CAAC;AAC7C,0BAAwB,GAAG;AAC3B,2BAAyB,GAAG;AAC5B,MAAI,IAAI,UAAU,OAAO,IAAI,WAAW,UAAU;AACjD,+BAA2B,IAAI,MAAM;AAAA,EACtC;AACA,4BAA0B,GAAG;AAC7B,uBAAqB,GAAG;AACxB,SAAO;AACR;AAVgB;AAYhB,SAAS,qBAAqB,KAAgC;AAC7D,MAAI,CAAC,IAAI,SAAS,OAAO,IAAI,UAAU,SAAU;AACjD,MAAI,IAAI,MAAM,WAAW,OAAO,IAAI,MAAM,YAAY,UAAU;AAC/D,8BAA0B,IAAI,MAAM,OAAO;AAAA,EAC5C;AACA,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,IAAI,KAAK,GAAG;AACrD,QAAI,SAAS,aAAa,CAAC,QAAQ,OAAO,SAAS,SAAU;AAC7D,8BAA0B,IAA+B;AAAA,EAC1D;AACD;AATS;AAYF,SAAS,wBAAwB,KAAgC;AACvE,MAAI,CAAC,IAAI,YAAY,OAAO,IAAI,aAAa,UAAU;AACtD,QAAI,WAAW,EAAE,aAAa,GAAG,KAAK,GAAG,UAAU,EAAE;AACrD;AAAA,EACD;AACA,QAAM,MAAM,IAAI;AAChB,MAAI,IAAI,eAAe,KAAM,KAAI,cAAc;AAC/C,MAAI,IAAI,OAAO,KAAM,KAAI,MAAM;AAC/B,MAAI,IAAI,YAAY,KAAM,KAAI,WAAW;AACzC,MAAI,CAAC,MAAM,QAAQ,IAAI,aAAa,GAAG;AACtC,QAAI,gBAAgB;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACA,MAAI,CAAC,IAAI,SAAS,OAAO,IAAI,UAAU,UAAU;AAChD,QAAI,QAAQ,EAAE,SAAS,EAAE;AAAA,EAC1B;AACA,MAAI,IAAI,iBAAiB,KAAM,KAAI,gBAAgB;AACnD,MAAI,IAAI,mBAAmB,KAAM,KAAI,kBAAkB;AACvD,MAAI,IAAI,kBAAkB,KAAM,KAAI,iBAAiB;AACrD,MAAI,IAAI,mBAAmB,KAAM,KAAI,kBAAkB;AACvD,MAAI,IAAI,qBAAqB,KAAM,KAAI,oBAAoB;AAC3D,MAAI,CAAC,IAAI,kBAAkB,OAAO,IAAI,mBAAmB,UAAU;AAClE,QAAI,iBAAiB;AAAA,MACpB,WAAW,IAAI;AAAA,MACf,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,cAAc;AAAA,IACf;AAAA,EACD;AACA,MAAI,CAAC,IAAI,UAAU,OAAO,IAAI,WAAW,UAAU;AAClD,QAAI,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG;AAAA,EACrC;AACA,MAAI,IAAI,sBAAsB,KAAM,KAAI,qBAAqB;AAC7D,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,QAAQ;AACnD,QAAI,QAAQ;AAAA,MACX,EAAE,MAAM,UAAU,OAAO,GAAG,aAAa,CAAC,MAAM,EAAE;AAAA,MAClD,EAAE,MAAM,YAAY,OAAO,GAAG,aAAa,CAAC,QAAQ,SAAS,EAAE;AAAA,MAC/D,EAAE,MAAM,YAAY,OAAO,GAAG,aAAa,CAAC,QAAQ,WAAW,OAAO,EAAE;AAAA,MACxE,EAAE,MAAM,SAAS,OAAO,GAAG,aAAa,CAAC,QAAQ,WAAW,SAAS,OAAO,EAAE;AAAA,MAC9E,EAAE,MAAM,aAAa,OAAO,GAAG,aAAa,CAAC,QAAQ,WAAW,SAAS,SAAS,SAAS,EAAE;AAAA,MAC7F,EAAE,MAAM,cAAc,OAAO,IAAI,aAAa,CAAC,QAAQ,WAAW,SAAS,SAAS,WAAW,OAAO,EAAE;AAAA,IACzG;AAAA,EACD;AACA,MAAI,IAAI,YAAY,KAAM,KAAI,WAAW;AACzC,MAAI,CAAC,MAAM,QAAQ,IAAI,UAAU,KAAK,CAAC,IAAI,WAAW,QAAQ;AAC7D,QAAI,aAAa;AAAA,MAChB,EAAE,IAAI,GAAG,KAAK,SAAS,MAAM,4BAAQ,QAAQ,QAAQ;AAAA,MACrD,EAAE,IAAI,GAAG,KAAK,YAAY,MAAM,sBAAO,QAAQ,WAAW;AAAA,MAC1D,EAAE,IAAI,GAAG,KAAK,YAAY,MAAM,sBAAO,QAAQ,WAAW;AAAA,MAC1D,EAAE,IAAI,GAAG,KAAK,SAAS,MAAM,sBAAO,QAAQ,gBAAgB;AAAA,MAC5D,EAAE,IAAI,GAAG,KAAK,aAAa,MAAM,sBAAO,QAAQ,YAAY;AAAA,MAC5D,EAAE,IAAI,IAAI,KAAK,cAAc,MAAM,kCAAS,QAAQ,sBAAsB;AAAA,IAC3E;AAAA,EACD;AACA,MAAI,CAAC,IAAI,wBAAwB,OAAO,IAAI,yBAAyB,UAAU;AAC9E,QAAI,uBAAuB,EAAE,SAAS,GAAG,WAAW,GAAG,YAAY,EAAE;AAAA,EACtE;AACD;AArEgB;AAwET,SAAS,yBAAyB,KAAgC;AACxE,MAAI,CAAC,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AACxD,QAAI,YAAY;AAAA,MACf,MAAM;AAAA,MACN,KAAK,EAAE,KAAK,wBAAwB,KAAK,SAAS,QAAQ,EAAE;AAAA,IAC7D;AACA;AAAA,EACD;AACA,QAAM,QAAQ,IAAI;AAClB,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO;AAC9B,MAAI,CAAC,MAAM,OAAO,OAAO,MAAM,QAAQ,SAAU,OAAM,MAAM,CAAC;AAC9D,MAAI,MAAM,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAM,IAAI,IAAK,OAAM,IAAI,MAAM;AACpC,QAAI,CAAC,MAAM,IAAI,IAAK,OAAM,IAAI,MAAM;AACpC,QAAI,MAAM,IAAI,UAAU,KAAM,OAAM,IAAI,SAAS;AAAA,EAClD,WAAW,MAAM,SAAS,UAAU;AACnC,QAAI,CAAC,MAAM,IAAI,SAAU,OAAM,IAAI,WAAW;AAC9C,QAAI,MAAM,IAAI,UAAU,KAAM,OAAM,IAAI,SAAS;AAAA,EAClD,WAAW,MAAM,SAAS,SAAS;AAClC,QAAI,CAAC,MAAM,IAAI,KAAM,OAAM,IAAI,OAAO;AACtC,QAAI,CAAC,MAAM,IAAI,KAAM,OAAM,IAAI,OAAO;AACtC,QAAI,MAAM,IAAI,YAAY,KAAM,OAAM,IAAI,WAAW;AACrD,QAAI,CAAC,MAAM,IAAI,SAAU,OAAM,IAAI,WAAW;AAC9C,QAAI,MAAM,IAAI,UAAU,KAAM,OAAM,IAAI,SAAS;AAAA,EAClD;AACD;AAzBgB;AA4BT,SAAS,2BAA2B,QAAmC;AAC7E,MAAI,CAAC,OAAO,SAAS,OAAO,OAAO,UAAU,UAAU;AACtD,WAAO,QAAQ,EAAE,MAAM,QAAQ,KAAK,4BAA4B,KAAK,SAAS,QAAQ,EAAE;AACxF;AAAA,EACD;AACA,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAM,KAAM,OAAM,OAAO;AAC9B,MAAI,MAAM,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAM,IAAK,OAAM,MAAM;AAC5B,QAAI,CAAC,MAAM,IAAK,OAAM,MAAM;AAAA,EAC7B,WAAW,MAAM,SAAS,UAAU;AACnC,QAAI,CAAC,MAAM,SAAU,OAAM,WAAW;AAAA,EACvC,WAAW,MAAM,SAAS,SAAS;AAClC,QAAI,CAAC,MAAM,KAAM,OAAM,OAAO;AAC9B,QAAI,CAAC,MAAM,KAAM,OAAM,OAAO;AAC9B,QAAI,MAAM,YAAY,KAAM,OAAM,WAAW;AAC7C,QAAI,CAAC,MAAM,SAAU,OAAM,WAAW;AAAA,EACvC;AACA,MAAI,MAAM,UAAU,KAAM,OAAM,SAAS;AACzC,MAAI,CAAC,OAAO,aAAc,QAAO,eAAe,CAAC;AACjD,MAAI,CAAC,OAAO,aAAa,aAAa;AACrC,WAAO,aAAa,cAAc;AAAA,EACnC;AACA,MAAI,CAAC,OAAO,QAAQ,OAAO,OAAO,SAAS,UAAU;AACpD,WAAO,OAAO,EAAE,SAAS,EAAE;AAAA,EAC5B;AACA,MAAI,OAAO,KAAK,WAAW,KAAM,QAAO,KAAK,UAAU;AACvD,MAAI,OAAO,eAAe,KAAM,QAAO,cAAc;AACrD,MAAI,OAAO,2BAA2B,KAAM,QAAO,0BAA0B;AAC9E;AA7BgB;AAkCT,SAAS,0BAA0B,KAAgC;AACzE,MAAI,CAAC,IAAI,cAAc,OAAO,IAAI,eAAe,UAAU;AAC1D,QAAI,aAAa,CAAC;AAAA,EACnB;AACA,QAAM,SAAS,IAAI;AAEnB,MAAI,CAAC,OAAO,QAAQ,IAAI,WAAW;AAClC,WAAO,OAAO,EAAE,MAAM,IAAI,UAAU,QAAQ,QAAQ,KAAK,EAAE,GAAI,IAAI,UAAU,OAAO,CAAC,EAAG,EAAE;AAAA,EAC3F;AACA,MAAI,CAAC,OAAO,MAAM;AACjB,WAAO,OAAO;AAAA,MACb,MAAM;AAAA,MACN,KAAK,EAAE,KAAK,wBAAwB,KAAK,SAAS,QAAQ,EAAE;AAAA,IAC7D;AAAA,EACD;AACA,MAAI,OAAO,QAAQ,OAAO,OAAO,SAAS,UAAU;AACnD,UAAM,YAAY,OAAO;AACzB,UAAM,WAAY,UAAU,QAAQ;AACpC,QAAI,CAAC,UAAU,KAAM,WAAU,OAAO;AACtC,QAAI,CAAC,UAAU,OAAO,OAAO,UAAU,QAAQ,SAAU,WAAU,MAAM,CAAC;AAC1E,QAAI,aAAa,QAAQ;AACxB,UAAI,CAAC,UAAU,IAAI,IAAK,WAAU,IAAI,MAAM;AAC5C,UAAI,CAAC,UAAU,IAAI,IAAK,WAAU,IAAI,MAAM;AAAA,IAC7C,WAAW,aAAa,UAAU;AACjC,UAAI,CAAC,UAAU,IAAI,SAAU,WAAU,IAAI,WAAW;AAAA,IACvD,WAAW,aAAa,SAAS;AAChC,UAAI,CAAC,UAAU,IAAI,KAAM,WAAU,IAAI,OAAO;AAC9C,UAAI,CAAC,UAAU,IAAI,KAAM,WAAU,IAAI,OAAO;AAC9C,UAAI,UAAU,IAAI,YAAY,KAAM,WAAU,IAAI,WAAW;AAC7D,UAAI,CAAC,UAAU,IAAI,SAAU,WAAU,IAAI,WAAW;AAAA,IACvD;AACA,QAAI,UAAU,IAAI,UAAU,KAAM,WAAU,IAAI,SAAS;AAAA,EAC1D;AACA,MAAI,CAAC,OAAO,OAAO,IAAI,QAAQ,OAAO;AACrC,UAAM,IAAI,IAAI,OAAO;AACrB,WAAO,MAAM;AAAA,MACZ,MAAM,EAAE,QAAQ;AAAA,MAChB,KAAK;AAAA,QACJ,UAAU,EAAE;AAAA,QACZ,KAAK,EAAE;AAAA,QACP,KAAK,EAAE;AAAA,QACP,MAAM,EAAE;AAAA,QACR,MAAM,EAAE;AAAA,QACR,UAAU,EAAE;AAAA,QACZ,QAAQ,EAAE;AAAA,MACX;AAAA,IACD;AAAA,EACD;AACA,MAAI,OAAO,OAAO,OAAO,OAAO,QAAQ,UAAU;AACjD,UAAM,WAAW,OAAO;AACxB,UAAM,UAAW,SAAS,QAAQ;AAClC,QAAI,CAAC,SAAS,OAAO,OAAO,SAAS,QAAQ,SAAU,UAAS,MAAM,CAAC;AACvE,QAAI,YAAY,QAAQ;AACvB,UAAI,CAAC,SAAS,IAAI,IAAK,UAAS,IAAI,MAAM;AAC1C,UAAI,CAAC,SAAS,IAAI,IAAK,UAAS,IAAI,MAAM;AAAA,IAC3C,WAAW,YAAY,UAAU;AAChC,UAAI,CAAC,SAAS,IAAI,SAAU,UAAS,IAAI,WAAW;AAAA,IACrD;AACA,QAAI,SAAS,IAAI,UAAU,KAAM,UAAS,IAAI,SAAS;AAAA,EACxD;AACA,MAAI,CAAC,OAAO,SAAS;AACpB,WAAO,UAAU;AAAA,MAChB,MAAM;AAAA,MACN,KAAK,EAAE,UAAU,wCAAwC,QAAQ,EAAE;AAAA,IACpE;AAAA,EACD;AAGA,MAAI,OAAO,MAAM;AAChB,QAAI,YAAY,EAAE,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,OAAO,KAAK,OAAO,CAAC,EAAE;AAC/E,6BAAyB,GAAG;AAAA,EAC7B;AACA,MAAI,OAAO,OAAO,IAAI,QAAQ;AAC7B,UAAM,KAAK,OAAO,IAAI,OAAO,CAAC;AAC9B,QAAI,OAAO,QAAQ;AAAA,MAClB,MAAM,OAAO,IAAI,QAAQ;AAAA,MACzB,UAAU,GAAG;AAAA,MACb,KAAK,GAAG;AAAA,MACR,KAAK,GAAG;AAAA,MACR,MAAM,GAAG;AAAA,MACT,MAAM,GAAG;AAAA,MACT,UAAU,GAAG;AAAA,MACb,QAAQ,GAAG;AAAA,IACZ;AACA,+BAA2B,IAAI,MAAM;AAAA,EACtC;AACD;AAtFgB;AAwFT,SAAS,mBAAmB,KAAoC;AACtE,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACpC,WAAO,CAAC,uDAAoB;AAAA,EAC7B;AAGA,MAAI,IAAI,YAAY,MAAM;AACzB,WAAO,KAAK,+HAAkF;AAAA,EAC/F;AACA,MAAI,IAAI,UAAU,MAAM;AACvB,WAAO,KAAK,mFAA2C;AAAA,EACxD;AACA,MAAI,IAAI,KAAK,aAAa,MAAM;AAC/B,WAAO,KAAK,iGAAyD;AAAA,EACtE;AACA,MAAI,IAAI,WAAW,OAAO,QAAQ,IAAI,WAAW,QAAQ,MAAM;AAC9D,WAAO,KAAK,yIAAmE;AAAA,EAChF;AACA,MAAI,IAAI,UAAU,iBAAiB,MAAM;AACxC,WAAO,KAAK,2GAAmE;AAAA,EAChF;AACA,MAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,OAAO,IAAI,MAAM,CAAC,MAAM,YAAY,IAAI,MAAM,CAAC,EAAE,SAAS,GAAG;AAC5F,WAAO,KAAK,0FAAkD;AAAA,EAC/D;AAEA,0BAAwB,GAAG;AAC3B,2BAAyB,GAAG;AAE5B,MAAI,IAAI,UAAU,OAAO,IAAI,WAAW,UAAU;AACjD,+BAA2B,IAAI,MAAM;AAAA,EACtC;AACA,4BAA0B,GAAG;AAE7B,MAAI,IAAI,cAAc,OAAO,IAAI,eAAe,UAAU;AACzD,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,UAAU,GAAG;AAC3D,YAAM,IAAI;AACV,UAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,UAAU,OAAO,EAAE,SAAS,EAAE,IAAI,GAAG;AAC7D,eAAO,KAAK,cAAc,IAAI,4CAA6B;AAAA,MAC5D;AAAA,IACD;AAAA,EACD;AAEA,MAAI,IAAI,YAAY,OAAO,IAAI,aAAa,UAAU;AACrD,UAAM,MAAM,IAAI;AAChB,QAAI,IAAI,eAAe,QAAQ,IAAI,gBAAgB,KAAK,IAAI,gBAAgB,GAAG;AAC9E,aAAO,KAAK,oDAAgC;AAAA,IAC7C;AACA,QAAI,IAAI,OAAO,QAAQ,IAAI,QAAQ,KAAK,IAAI,QAAQ,GAAG;AACtD,aAAO,KAAK,4CAAwB;AAAA,IACrC;AACA,QAAI,IAAI,gBAAgB,SAAS,OAAO,IAAI,iBAAiB,YAAY,IAAI,eAAe,IAAI;AAC/F,aAAO,KAAK,kEAA+B;AAAA,IAC5C;AAAA,EACD;AAEA,MAAI,CAAC,IAAI,SAAS,OAAO,IAAI,UAAU,UAAU;AAChD,WAAO,KAAK,sCAAa;AAAA,EAC1B,OAAO;AACN,QAAI,CAAC,IAAI,MAAM,SAAS;AACvB,aAAO,KAAK,4BAAkB;AAAA,IAC/B,OAAO;AACN,gCAA0B,IAAI,MAAM,OAAkC;AAAA,IACvE;AACA,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,IAAI,KAAK,GAAG;AACrD,YAAM,IAAI;AACV,UAAI,SAAS,WAAW;AACvB,+BAAuB,MAAM,GAAG,MAAM;AACtC;AAAA,MACD;AACA,UAAI,EAAE,QAAQ,SAAS,OAAO,EAAE,SAAS,YAAY,EAAE,QAAQ,KAAK,EAAE,OAAO,QAAQ;AACpF,eAAO,KAAK,SAAS,IAAI,uBAAa,EAAE,IAAI,EAAE;AAAA,MAC/C;AACA,UAAI,EAAE,YAAY,QAAQ,CAAC,MAAM,QAAQ,EAAE,QAAQ,GAAG;AACrD,eAAO,KAAK,SAAS,IAAI,0CAAiB;AAAA,MAC3C;AACA,6BAAuB,MAAM,GAAG,MAAM;AAAA,IACvC;AAAA,EACD;AAEA,MAAI,IAAI,QAAQ,UAAU,OAAO,IAAI,OAAO,WAAW,UAAU;AAChE,WAAO,KAAK,qFAA6C;AAAA,EAC1D;AACA,MAAI,IAAI,QAAQ,QAAQ,QAAQ,CAAC,MAAM,QAAQ,IAAI,OAAO,IAAI,GAAG;AAChE,WAAO,KAAK,sGAA+C;AAAA,EAC5D;AAEA,MAAI,IAAI,cAAc,OAAO,IAAI,eAAe,UAAU;AACzD,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,UAAU,GAAG;AAC3D,YAAM,IAAI;AACV,UAAI,EAAE,OAAO,EAAE,aAAa,QAAQ,OAAO,EAAE,cAAc,UAAU;AACpE,eAAO,KAAK,cAAc,IAAI,yBAAe;AAAA,MAC9C;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAjGgB;AAmGhB,SAAS,uBAAuB,MAAc,GAAwB,QAAwB;AAC7F,QAAM,QAAQ,CAAC,SAAS,MAAM,UAAU,QAAQ,QAAQ;AACxD,aAAW,OAAO,OAAO;AACxB,QAAI,EAAE,GAAG,KAAK,QAAQ,EAAE,GAAG,MAAM,KAAK,EAAE,GAAG,MAAM,GAAG;AACnD,aAAO,KAAK,SAAS,IAAI,IAAI,GAAG,gCAAY;AAAA,IAC7C;AAAA,EACD;AACA,aAAW,OAAO,CAAC,WAAW,SAAS,WAAW,GAAY;AAC7D,QAAI,EAAE,GAAG,KAAK,SAAS,OAAO,EAAE,GAAG,MAAM,YAAY,EAAE,GAAG,KAAK,IAAI;AAClE,aAAO,KAAK,SAAS,IAAI,IAAI,GAAG,uCAAS;AAAA,IAC1C;AAAA,EACD;AACA,MAAI,EAAE,QAAQ,QAAQ,CAAC,MAAM,QAAQ,EAAE,IAAI,GAAG;AAC7C,WAAO,KAAK,SAAS,IAAI,wDAAgB;AAAA,EAC1C;AACD;AAfS;AAkBF,SAAS,2BAA2B,KAAoC;AAC9E,QAAM,SAAmB,CAAC;AAC1B,MAAI,QAAQ,IAAI,aAAa,aAAc,QAAO;AAElD,QAAM,MAAM,KAAK;AACjB,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACpC,WAAO,KAAK,wEAAsB;AAClC,WAAO;AAAA,EACR;AACA,MAAI,IAAI,gBAAgB,GAAG;AAC1B,WAAO,KAAK,+GAA8C;AAAA,EAC3D;AACA,MAAI,IAAI,kBAAkB,GAAG;AAC5B,WAAO,KAAK,uHAAiD;AAAA,EAC9D;AACA,MAAI,CAAC,IAAI,OAAO,SAAS;AACxB,WAAO,KAAK,2GAA+C;AAAA,EAC5D;AACA,MAAI,IAAI,QAAQ,GAAG;AAClB,WAAO,KAAK,6GAAuC;AAAA,EACpD;AACA,MAAI,OAAO,IAAI,iBAAiB,YAAY,IAAI,eAAe,GAAG;AACjE,WAAO,KAAK,+EAAkC;AAAA,EAC/C;AACA,MAAI,IAAI,aAAa,KAAK,CAAC,KAAK,WAAW,WAAW,CAAC,KAAK,WAAW,KAAK;AAC3E,WAAO,KAAK,0FAAwC;AAAA,EACrD;AAEA,SAAO;AACR;AA7BgB;;;ACxVhB,IAAM,kBAAiD;AAAA,EACtD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AACR;AAEA,IAAM,oBAA6D;AAAA,EAClE,KAAK,EAAE,SAAS,MAAM,YAAY,IAAI,cAAc,KAAM,UAAU,KAAO,QAAQ,EAAE;AAAA,EACrF,MAAM,EAAE,SAAS,MAAM,YAAY,IAAI,cAAc,KAAM,UAAU,KAAO,QAAQ,EAAE;AAAA,EACtF,OAAO,EAAE,SAAS,MAAM,YAAY,IAAI,cAAc,KAAM,UAAU,KAAO,QAAQ,EAAE;AACxF;AAuBO,SAAS,kBAAkB,KAAU,MAAiD;AAC5F,QAAM,QAAQ,MAAM,IAAI;AACxB,SAAO,SAAS,OAAO,UAAU,WAAW,QAAQ;AACrD;AAHgB;AAKT,SAAS,oBAAoB,KAAU,MAAiD;AAC9F,QAAM,MAAM,kBAAkB,KAAK,IAAI,GAAG;AAC1C,SAAO,OAAO,OAAO,QAAQ,WAAW,MAAM;AAC/C;AAHgB;AAKT,SAAS,oBAAoB,KAAU,MAA8B;AAC3E,SAAO,CAAC,CAAC,oBAAoB,KAAK,IAAI;AACvC;AAFgB;AAKT,SAAS,iBAAiB,KAAU,MAA6B;AACvE,QAAM,MAAM,oBAAoB,KAAK,IAAI;AACzC,QAAM,KAAK,KAAK;AAChB,SAAO,OAAO,OAAO,YAAY,GAAG,SAAS,IAAI,KAAK,gBAAgB,IAAI;AAC3E;AAJgB;AAOT,SAAS,kBAAkB,KAAsD;AACvF,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,IAAI,gBAAgB;AAC5B;AAHgB;AAMT,SAAS,wBACf,KACA,MACA,KACmB;AACnB,QAAM,OAAO,kBAAkB,IAAI;AACnC,QAAM,KAAK,KAAK;AAChB,QAAM,WAAW,KAAK,IAAI;AAE1B,SAAO;AAAA,IACN,SAAS,IAAI,YAAY,SAAS,KAAK,YAAY;AAAA,IACnD,YAAY,IAAI,cAAc,YAAY,KAAK,cAAc;AAAA,IAC7D,cAAc,IAAI,gBAAgB,KAAK,gBAAgB;AAAA,IACvD,UAAU,IAAI,YAAY,KAAK,YAAY;AAAA,IAC3C,QAAQ,IAAI,UAAU,KAAK,UAAU;AAAA,EACtC;AACD;AAhBgB;;;AC3EhB,IAAM,kBAAiD;AAAA,EACtD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AACR;AAgBO,SAAS,oBAAoB,MAAmC;AACtE,QAAM,EAAE,OAAO,QAAQ,IAAI;AAC3B,QAAM,KAAK,UAAU,IAAI;AACzB,MAAI,CAAC,MAAM,KAAK,UAAU,GAAG;AAC5B,UAAM,KAAK,UAAU,IAAI,CAAC;AAAA,EAC3B;AAEA,QAAM,aAAa,oBAAoB,MAAM,YAAY,KAAK,SAAS;AACvE,QAAM,SAAS,iBAAiB,MAAM,YAAY,KAAK,SAAS;AAEhE,MAAI,YAAY;AACf,UAAM,QAAQ,KAAK,mBAAmB,UAAU;AAChD,UAAM,gBAAgB,KAAK,SAAS,CAAC,IAAI,EAAE,QAAQ,QAAQ,MAAM;AACjE,QAAI,kBAAkB,UAAU,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,MAAM,GAAG;AACrE,YAAM,KAAK,UAAU,EAAE,MAAM,IAAI,QAAQ,QAAQ,KAAK;AAAA,IACvD;AAAA,EACD;AAEA,cAAY,OAAO,KAAK,UAAU,KAAK,UAAU;AACjD,aAAW,OAAO,KAAK,SAAS,KAAK,SAAS;AAC9C,SAAO;AACR;AArBgB;AAwBT,SAAS,wBAAwB,OAAY,WAAyC;AAC5F,QAAM,UAAU,MAAM,gBAAgB,SAAS,CAAC;AAChD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,aACL,cAAc,QAAQ,gBAAgB,cAAc,SAAS,iBAAiB;AAC/E,QAAM,aACL,cAAc,QACX,sBACA,cAAc,SACb,uBACA;AAEL,QAAM,UAAU,MAAM,UAAU;AAChC,MAAI,CAAC,WAAW,CAAC,QAAQ,OAAQ,QAAO;AAExC,MAAI,CAAC,MAAM,UAAU,EAAG,OAAM,UAAU,IAAI,CAAC;AAC7C,MAAI,CAAC,MAAM,UAAU,EAAE,QAAQ,MAAM,GAAG;AACvC,UAAM,UAAU,EAAE,QAAQ,MAAM,IAAI,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EACnE;AACA,SAAO,QAAQ;AAChB;AArBgB;AAwBT,SAAS,2BAA2B,OAAY,SAAc;AACpE,SAAO,CAAC,UAAe;AACtB,QAAI,OAAO,MAAM,SAAS,UAAU;AACnC,UAAI;AACH,cAAM,OAAO,KAAK,MAAM,MAAM,IAAI;AAAA,MACnC,QAAQ;AAAA,MAER;AAAA,IACD;AACA,QAAI,MAAM,MAAM,IAAI;AACnB,cAAQ,MAAM,MAAM,IAAI,MAAM,IAAI;AAClC;AAAA,IACD;AACA,QAAI;AACH,YAAM,QAAQ,OAAO,SAAS,eAAe,QAAQ;AACrD,YAAM,YAAY,KAAK,GAAG,UAAU,MAAM,IAAI;AAAA,IAC/C,QAAQ;AAAA,IAER;AAAA,EACD;AACD;AApBgB;AAuBT,SAAS,4BACf,SACA,QACA,WACO;AACP,UAAQ,GAAG,OAAO,WAAW,CAAC,UAAe;AAC5C,YAAQ,IAAI,GAAG,SAAS,6BAAS,MAAM,IAAI,MAAM,SAAS,EAAE;AAAA,EAC7D,CAAC;AACD,UAAQ,GAAG,OAAO,cAAc,CAAC,UAAe;AAC/C,YAAQ,IAAI,GAAG,SAAS,6BAAS,MAAM,IAAI,MAAM,SAAS,EAAE;AAAA,EAC7D,CAAC;AAED,MAAI,OAAO,OAAO;AACjB,YAAQ,GAAG,OAAO,OAAO,MAAM;AAAA,IAAC,CAAC;AAAA,EAClC;AACD;AAfgB;;;AC0ET,IAAM,cAAc;;;ACtH3B,SAAS,YAAe,KAAW;AAClC,MAAI,OAAO,OAAO,QAAQ,YAAY,aAAc,KAAgB;AACnE,UAAM,IAAK,IAAmC;AAC9C,QAAI,MAAM,OAAW,QAAO;AAAA,EAC7B;AACA,SAAO;AACR;AANS;AAQT,IAAM,WAAW,YAAY,WAAW;AAExC,IAAMC,sBAA2C;AAAA,EAChD,MAAM;AAAA,EACN,IAAI,wBAAC,OAAoB,QACxB,SAAS,OAAO,GAAG,GADhB;AAAA,EAEJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAmEO,IAAM,iBACZ,OACG,UACA;AAEJ,IAAO,gBAAQC;","names":["ensureFile","resolve","ensureFile","fs","fs","logSecurityConfigIntervention","getComplianceReport","ws","WebSocket","WebSocket","ws","fs","path","fs","nodePath","fs","path","fs","process","process","ws","createUserStore","path","resolve","$asai","postdata","ws","$asai","resolve","ws","ws","fs","path","ensureFile","pathExists","readLogDir","removeFile","resolvePathUnderBase","fs","path","data","fs","nodePath","os","os","getQuota","fs","resolve","dot","hostDefault","fs","path","path","fs","fs","nodePath","path","resolve","relative","fs","path","isPathInside","joinTablePath","relative","read","resolve","Index_default","Index_default","initAsaiHostNodejs","initAsaiHostNodejs"]}
|