@gachlab/devup 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/control-plane/socket-server.d.ts +6 -0
- package/dist/control-plane/socket-server.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/orchestrator/daemon.d.ts.map +1 -1
- package/dist/tui/hooks/useControlPlane.d.ts +1 -1
- package/dist/tui/hooks/useControlPlane.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config/loader.ts","../src/config/validator.ts","../src/lazy/classifier.ts","../src/config/cli.ts","../src/orchestrator/subcommands.ts","../src/process/health.ts","../src/utils/env.ts","../src/utils/format.ts","../src/utils/search.ts","../src/utils/redact.ts","../src/utils/install-stamp.ts","../src/utils/process-args.ts","../src/utils/stats.ts","../src/utils/phases.ts","../src/utils/colors.ts","../src/control-plane/client.ts","../src/control-plane/socket-server.ts","../src/orchestrator/daemon.ts","../src/process/manager.ts","../src/process/installer.ts","../src/process/spawner.ts","../src/process/internals.ts","../src/process/restarter.ts","../src/process/health-poller.ts","../src/process/lifecycle.ts","../src/process/log-sink.ts","../src/utils/broadcaster.ts","../src/process/external.ts","../src/lazy/proxy.ts","../src/orchestrator/config-watcher.ts","../src/config/diff.ts","../src/process/port-conflicts.ts","../src/platform/detect.ts","../src/proxy-config/traefik.ts","../src/proxy-config/nginx.ts","../src/proxy-config/caddy.ts","../src/proxy-config/detect.ts","../src/tui/App.tsx","../src/tui/hooks/useProcessManager.ts","../src/tui/hooks/useKeyBindings.ts","../src/tui/hooks/useProxySync.ts","../src/tui/hooks/useTerminalSize.ts","../src/tui/hooks/useLogsPause.ts","../src/tui/hooks/useControlPlane.ts","../src/tui/hooks/useHotReload.ts","../src/tui/hooks/useContextualTips.ts","../src/tui/tips.ts","../src/tui/StatsPanel.tsx","../src/tui/hooks/useBootSequence.ts","../src/tui/LogsPanel.tsx","../src/tui/StatusBar.tsx","../src/tui/ServiceList.tsx","../src/tui/SearchInput.tsx","../src/orchestrator/dry-run.ts","../src/orchestrator/once.ts","../src/config/types.ts"],"sourcesContent":["import React from 'react';\nimport { render } from 'ink';\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { homedir } from 'node:os';\n\nimport { findConfigFile, loadConfig } from './config/loader.js';\nimport { validateConfig, formatValidationErrors, collectWarnings, formatValidationWarnings } from './config/validator.js';\nimport { parseCliArgs, filterServices, USAGE } from './config/cli.js';\nimport { detectSubcommand, runLogs, runInstall, runStatus, runHelp, runCtl, runDown } from './orchestrator/subcommands.js';\nimport { runDetached, daemonBody, isDaemonRunning } from './orchestrator/daemon.js';\nimport { scanPortConflicts, resolvePortConflicts } from './process/port-conflicts.js';\nimport { detectPlatform } from './platform/detect.js';\nimport { detectProxyProvider } from './proxy-config/detect.js';\nimport { parseEnvFile } from './utils.js';\nimport { App } from './tui/App.js';\nimport { LogSink } from './process/log-sink.js';\nimport { runDryRun } from './orchestrator/dry-run.js';\nimport { runOnce } from './orchestrator/once.js';\nimport type { ProxyConfigProvider, ProxyOpts } from './proxy-config/types.js';\n\n// Re-export for config files\nexport { defineConfig } from './config/types.js';\nexport type { DevStackConfig, ServiceConfig, LazyConfig, ProxyConfig } from './config/types.js';\nexport type { Platform, ProcessStats } from './platform/types.js';\nexport type { ProxyConfigProvider, ProxyOpts } from './proxy-config/types.js';\n\nfunction readVersion(): string {\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(here, '..', 'package.json');\n return JSON.parse(readFileSync(pkgPath, 'utf8')).version ?? 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\nasync function main() {\n const raw = process.argv.slice(2);\n // --version / --help short-circuit before any config loading\n if (raw.includes('-v') || raw.includes('--version')) {\n console.log(readVersion());\n return;\n }\n if (raw.includes('-h') || raw.includes('--help')) {\n console.log(USAGE);\n return;\n }\n\n // Subcommand dispatch (devup logs / install / status / help). All require the config\n // file to be present so we can know which services exist and where logs live.\n const subcmd = detectSubcommand(raw);\n if (subcmd === 'help') {\n process.exit(runHelp(raw.slice(1)));\n }\n\n const cwd = process.cwd();\n const cliArgs = parseCliArgs(raw);\n\n if (subcmd) {\n const subArgs = raw.slice(1);\n // Load config (no validation needed for read-only ops, but resolve path errors clearly)\n let cfgPath: string;\n try { cfgPath = findConfigFile(cwd, cliArgs.configPath); }\n catch (e: any) { console.error(`❌ ${e.message}`); process.exit(1); }\n const cfg = await loadConfig(cfgPath);\n const subOpts = { config: cfg, baseCwd: cwd, env: process.env as Record<string, string>, logDir: cliArgs.logDir };\n if (subcmd === 'logs') process.exit(await runLogs(subArgs, subOpts));\n if (subcmd === 'install') process.exit(await runInstall(subOpts));\n if (subcmd === 'status') process.exit(await runStatus(subOpts));\n if (subcmd === 'ctl') process.exit(await runCtl(subArgs, subOpts));\n if (subcmd === 'down') process.exit(await runDown(subOpts));\n // `up` falls through to the full setup pipeline so it can boot the stack like the TUI does.\n }\n\n // Load config\n let configPath: string;\n try {\n configPath = findConfigFile(cwd, cliArgs.configPath);\n } catch (e: any) {\n console.error(`❌ ${e.message}`);\n process.exit(1);\n }\n\n const config = await loadConfig(configPath);\n\n // Validate\n const errors = validateConfig(config, cwd);\n if (errors.length) {\n console.error(`❌ Config validation failed:\\n${formatValidationErrors(errors)}`);\n process.exit(1);\n }\n const warnings = collectWarnings(config);\n if (warnings.length) {\n console.warn(`⚠ Config warnings:\\n${formatValidationWarnings(warnings)}`);\n }\n\n // Filter services\n let services: ReturnType<typeof filterServices>;\n try {\n services = filterServices(config.services, cliArgs, config);\n } catch (e: any) {\n console.error(`❌ ${e.message}`);\n process.exit(1);\n }\n if (!services.length) {\n console.error('❌ No services to run after filtering');\n process.exit(1);\n }\n\n // Platform\n const platform = await detectPlatform();\n\n // Env\n const envFile = config.envFile ? join(cwd, config.envFile) : join(cwd, '.env');\n const env = parseEnvFile(envFile, process.env as Record<string, string>);\n if (config.env) {\n for (const [k, v] of Object.entries(config.env)) {\n if (!env[k]) env[k] = v;\n }\n }\n\n // Proxy provider\n let proxyProvider: ProxyConfigProvider | null = null;\n let proxyOpts: ProxyOpts | null = null;\n if (cliArgs.proxy && config.proxy) {\n proxyProvider = detectProxyProvider(config.proxy.provider);\n proxyOpts = {\n host: cliArgs.proxyHost ?? config.proxy.host ?? platform.defaultTraefikHost,\n domain: env['GUESTHUB_DOMAIN'] ?? env['DOMAIN'] ?? 'localhost',\n routes: config.proxy.routes,\n tls: cliArgs.proxyTls ?? config.proxy.tls ?? true,\n entrypoint: cliArgs.proxyEntrypoint ?? config.proxy.entrypoint ?? 'websecure',\n confPath: cliArgs.proxyConf ?? config.proxy.confPath ?? join(homedir(), '.traefik', 'traefik_conf.yaml'),\n };\n }\n\n // --dry-run: imprime plan y sale\n if (cliArgs.dryRun) {\n runDryRun({ config, services, cliArgs, env, baseCwd: cwd, proxyProvider, proxyOpts });\n return;\n }\n\n // Log sink (a disco). Desactivable con --no-log-file.\n let logSink: LogSink | null = null;\n if (cliArgs.logFile) {\n logSink = new LogSink({ projectName: config.name, rootDir: cliArgs.logDir });\n }\n\n // Daemon-already-running guard. Applies to all \"boot the stack\" flows\n // (TUI, --once, devup up -d). If a healthy daemon is up for this project,\n // the ports we'd scan belong to its services — killing them only triggers\n // the daemon's auto-restarter and produces churn. Skip only for the daemon\n // child itself (which IS the running daemon).\n if (process.env.DEVUP_DAEMON_CHILD !== '1') {\n const daemonStatus = isDaemonRunning(config.name);\n if (daemonStatus.pid && !daemonStatus.stale) {\n console.error(`❌ A devup daemon is already running for \"${config.name}\" (pid=${daemonStatus.pid}).`);\n console.error('');\n console.error('Stop it first with `devup down`, or interact via the control plane:');\n console.error(' devup ctl status');\n console.error(' devup ctl logs <svc> --follow');\n console.error(' devup ctl restart <svc>');\n await logSink?.close();\n process.exit(1);\n }\n }\n\n // Pre-boot port conflict resolution. Skip in the daemon child (the parent\n // already cleared conflicts before spawning us). All other flows benefit:\n // TUI, `devup up -d`, `--once`.\n if (process.env.DEVUP_DAEMON_CHILD !== '1') {\n const conflicts = await scanPortConflicts(services);\n if (conflicts.length) {\n const resolved = await resolvePortConflicts(conflicts, {\n autoKill: cliArgs.killPortConflicts,\n out: msg => process.stderr.write(msg + '\\n'),\n prompt: () => askYesNo('Kill these processes and continue? [y/N]: '),\n });\n if (!resolved) {\n await logSink?.close();\n process.exit(1);\n }\n }\n }\n\n // --once: arranca, espera ready, sale 0/1 (sin TUI)\n if (cliArgs.once) {\n const code = await runOnce({\n config, services, cliArgs, platform, env, baseCwd: cwd, logSink,\n });\n await logSink?.close();\n process.exit(code);\n }\n\n // Daemon child: spawned by `devup up -d`. Skip Ink/TUI; run the daemon body\n // which stays alive until SIGTERM. The parent process polls for the PID file.\n if (process.env.DEVUP_DAEMON_CHILD === '1') {\n await daemonBody({ config, services, cliArgs, platform, env, baseCwd: cwd, proxyProvider, proxyOpts });\n return; // daemonBody installs its own signal handlers and only exits via process.exit\n }\n\n // `devup up -d`: spawn the daemon child detached, wait for it to signal ready, exit.\n if (subcmd === 'up') {\n if (!raw.includes('-d') && !raw.includes('--detach')) {\n console.error('usage: devup up -d (use plain `devup` for the TUI)');\n process.exit(1);\n }\n process.exit(await runDetached({\n config, services, cliArgs, platform, env, baseCwd: cwd, proxyProvider, proxyOpts,\n }));\n }\n\n // Render TUI\n const isInteractive = process.stdin.isTTY ?? false;\n const { waitUntilExit } = render(\n React.createElement(App, {\n config, services, cliArgs, platform, env, baseCwd: cwd,\n proxyProvider, proxyOpts, logSink,\n }),\n { exitOnCtrlC: false, patchConsole: isInteractive, interactive: isInteractive },\n );\n\n await waitUntilExit();\n}\n\n/** Single-line y/N prompt. Reads stdin directly rather than going through\n * readline — `readline.createInterface` can no-op silently when the input\n * stream has been touched elsewhere (e.g. terminal multiplexers, IDE\n * integrated terminals, complex shells), which left users with the\n * question printed but the process moving on without waiting.\n *\n * TTY is detected via any of stdin / stderr / stdout being a TTY; some\n * environments misreport one but not the others. Resolves false on EOF\n * or non-TTY so a caller can fall back to \"non-interactive\" handling. */\nfunction askYesNo(question: string): Promise<boolean> {\n return new Promise(resolve => {\n const isTTY = Boolean(process.stdin.isTTY || process.stderr.isTTY || process.stdout.isTTY);\n if (!isTTY) { resolve(false); return; }\n\n process.stderr.write(question);\n process.stdin.resume();\n process.stdin.setEncoding('utf8');\n\n const cleanup = () => {\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n process.stdin.pause();\n };\n const onData = (data: string | Buffer) => {\n cleanup();\n resolve(/^y(es)?$/i.test(String(data).trim()));\n };\n const onEnd = () => { cleanup(); resolve(false); };\n\n process.stdin.once('data', onData);\n process.stdin.once('end', onEnd);\n });\n}\n\n/** Only run main() when this script is invoked directly (i.e. as the `devup`\n * binary). When the bundle is *imported* — which happens whenever a user's\n * `devup.config.ts` does `import { defineConfig } from '@gachlab/devup'` —\n * we just want our exports (`defineConfig`, types) to be available, NOT to\n * start a second concurrent main() that races for the same ports and\n * duplicates every line of output.\n *\n * Compare `import.meta.url` (this module's file URL) against the realpath\n * of `process.argv[1]` (the entry script). When invoked as `devup`, npm\n * installs `bin/devup` as a symlink to `dist/index.js`, so the realpath\n * resolves to our module and the comparison matches. When imported from a\n * config file, `process.argv[1]` points at the outer entry — which lives\n * at a different node_modules path even when the same version — and the\n * comparison fails, so `main()` does not fire. */\nfunction isInvokedDirectly(): boolean {\n const argvPath = process.argv[1];\n if (!argvPath) return false;\n const moduleFile = fileURLToPath(import.meta.url);\n try {\n return realpathSync(argvPath) === moduleFile;\n } catch {\n return argvPath === moduleFile;\n }\n}\n\nif (isInvokedDirectly()) {\n main().catch(e => {\n console.error(e);\n process.exit(1);\n });\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { resolve, join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { DevStackConfig } from './types.js';\n\nconst CONFIG_NAMES = [\n 'devup.config.ts',\n 'devup.config.js',\n 'devup.config.json',\n];\n\nexport function findConfigFile(cwd: string, explicit?: string): string {\n if (explicit) {\n const full = resolve(cwd, explicit);\n if (!existsSync(full)) throw new Error(`Config not found: ${full}`);\n return full;\n }\n for (const name of CONFIG_NAMES) {\n const full = join(cwd, name);\n if (existsSync(full)) return full;\n }\n throw new Error(\n `No config found. Create one of: ${CONFIG_NAMES.join(', ')}\\n` +\n `Or use --config <path>`,\n );\n}\n\nexport async function loadConfig(configPath: string): Promise<DevStackConfig> {\n if (configPath.endsWith('.json')) {\n const raw = await readFile(configPath, 'utf8');\n return JSON.parse(raw) as DevStackConfig;\n }\n\n // .ts and .js — dynamic import (tsx loader handles .ts at runtime)\n const url = pathToFileURL(configPath).href;\n const mod = await import(url);\n const config = mod.default ?? mod;\n\n if (!config || typeof config !== 'object' || !Array.isArray(config.services)) {\n throw new Error(`Invalid config: must export a DevStackConfig (use defineConfig() from @gachlab/devup)`);\n }\n\n return config as DevStackConfig;\n}\n","import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { DevStackConfig } from './types.js';\nimport { LAZY_PORT_OFFSET } from '../lazy/classifier.js';\n\nexport interface ValidationError {\n field: string;\n message: string;\n}\n\nexport interface ValidationWarning {\n field: string;\n message: string;\n}\n\n/** Collects non-blocking warnings: things that look suspicious but don't justify\n * refusing to start the stack. Run alongside `validateConfig` from the CLI entry\n * point; print them and continue. */\nexport function collectWarnings(config: DevStackConfig): ValidationWarning[] {\n const warnings: ValidationWarning[] = [];\n if (!config.services?.length) return warnings;\n\n for (const svc of config.services) {\n // extraEnv.PORT vs svc.port: catches the common \"I set PORT in extraEnv to\n // something other than port and now nothing connects\" footgun.\n const ep = svc.extraEnv?.['PORT'];\n if (ep !== undefined) {\n const expected = String(svc.port);\n if (ep !== expected) {\n warnings.push({\n field: `services[${svc.name}].extraEnv.PORT`,\n message: `extraEnv.PORT=\"${ep}\" does not match port=${svc.port}. devup will health-check :${svc.port} but the service will probably bind to :${ep}.`,\n });\n }\n }\n }\n return warnings;\n}\n\nexport function formatValidationWarnings(warnings: ValidationWarning[]): string {\n return warnings.map(w => ` ⚠ ${w.field}: ${w.message}`).join('\\n');\n}\n\nexport function validateConfig(config: DevStackConfig, cwd: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (!config.name?.trim()) {\n errors.push({ field: 'name', message: 'Project name is required' });\n }\n\n if (!config.services?.length) {\n errors.push({ field: 'services', message: 'At least one service is required' });\n return errors;\n }\n\n // Unique names\n const names = new Set<string>();\n for (const svc of config.services) {\n if (names.has(svc.name)) {\n errors.push({ field: `services[${svc.name}].name`, message: `Duplicate service name: ${svc.name}` });\n }\n names.add(svc.name);\n }\n\n // Unique ports\n const ports = new Map<number, string>();\n for (const svc of config.services) {\n const existing = ports.get(svc.port);\n if (existing) {\n errors.push({ field: `services[${svc.name}].port`, message: `Port ${svc.port} already used by ${existing}` });\n }\n ports.set(svc.port, svc.name);\n }\n\n // Valid fields per service\n for (const svc of config.services) {\n if (!svc.name?.trim()) errors.push({ field: 'services[].name', message: 'Service name is required' });\n if (!svc.cwd?.trim()) errors.push({ field: `services[${svc.name}].cwd`, message: 'cwd is required' });\n if (!svc.cmd?.trim()) errors.push({ field: `services[${svc.name}].cmd`, message: 'cmd is required' });\n if (!svc.type || !['api', 'web'].includes(svc.type)) {\n errors.push({ field: `services[${svc.name}].type`, message: `Invalid type: ${svc.type} (must be \"api\" or \"web\")` });\n }\n if (typeof svc.port !== 'number' || svc.port <= 0) {\n errors.push({ field: `services[${svc.name}].port`, message: `Invalid port: ${svc.port}` });\n }\n if (typeof svc.phase !== 'number' || svc.phase < 0) {\n errors.push({ field: `services[${svc.name}].phase`, message: `Invalid phase: ${svc.phase}` });\n }\n\n // cwd exists\n if (svc.cwd && !existsSync(resolve(cwd, svc.cwd))) {\n errors.push({ field: `services[${svc.name}].cwd`, message: `Directory not found: ${svc.cwd}` });\n }\n\n // errorPattern (same regex grammar as readyPattern)\n if (svc.errorPattern !== undefined) {\n if (typeof svc.errorPattern !== 'string' || !svc.errorPattern.length) {\n errors.push({ field: `services[${svc.name}].errorPattern`, message: `errorPattern must be a non-empty string` });\n } else {\n const slashed = /^\\/(.+)\\/([gimsuy]*)$/.exec(svc.errorPattern);\n try {\n if (slashed) new RegExp(slashed[1]!, slashed[2] || 'i');\n else new RegExp(svc.errorPattern, 'i');\n } catch (e: any) {\n errors.push({ field: `services[${svc.name}].errorPattern`, message: `Invalid regex: ${e.message}` });\n }\n }\n }\n\n // readyPattern\n if (svc.readyPattern !== undefined) {\n if (typeof svc.readyPattern !== 'string' || !svc.readyPattern.length) {\n errors.push({ field: `services[${svc.name}].readyPattern`, message: `readyPattern must be a non-empty string` });\n } else {\n const slashed = /^\\/(.+)\\/([gimsuy]*)$/.exec(svc.readyPattern);\n try {\n if (slashed) new RegExp(slashed[1]!, slashed[2] || 'i');\n else new RegExp(svc.readyPattern, 'i');\n } catch (e: any) {\n errors.push({ field: `services[${svc.name}].readyPattern`, message: `Invalid regex: ${e.message}` });\n }\n }\n }\n\n // preBuild / watchBuild\n if (svc.preBuild !== undefined && (typeof svc.preBuild !== 'string' || !svc.preBuild.trim())) {\n errors.push({ field: `services[${svc.name}].preBuild`, message: `preBuild must be a non-empty string` });\n }\n if (svc.watchBuild !== undefined && (typeof svc.watchBuild !== 'string' || !svc.watchBuild.trim())) {\n errors.push({ field: `services[${svc.name}].watchBuild`, message: `watchBuild must be a non-empty string` });\n }\n\n // healthCheck\n if (svc.healthCheck) {\n const hc = svc.healthCheck;\n if (hc.type !== 'tcp' && hc.type !== 'http') {\n errors.push({ field: `services[${svc.name}].healthCheck.type`, message: `Invalid healthCheck.type: ${hc.type} (must be \"tcp\" or \"http\")` });\n }\n if (hc.startPeriod !== undefined && (typeof hc.startPeriod !== 'number' || hc.startPeriod < 0)) {\n errors.push({ field: `services[${svc.name}].healthCheck.startPeriod`, message: `startPeriod must be a non-negative number (seconds), got ${hc.startPeriod}` });\n }\n if (hc.type === 'http' && hc.path && !hc.path.startsWith('/')) {\n errors.push({ field: `services[${svc.name}].healthCheck.path`, message: `healthCheck.path must start with \"/\": got \"${hc.path}\"` });\n }\n }\n }\n\n // Lazy refs\n if (config.lazy?.alwaysOn) {\n for (const ref of config.lazy.alwaysOn) {\n if (!names.has(ref)) {\n errors.push({ field: `lazy.alwaysOn`, message: `Unknown service: ${ref}` });\n }\n }\n }\n\n // Lazy port collisions: in lazy mode each non-always-on service also listens on port + LAZY_PORT_OFFSET\n if (config.lazy) {\n const alwaysOn = new Set(config.lazy.alwaysOn ?? []);\n const portToSvc = new Map<number, string>();\n for (const svc of config.services) portToSvc.set(svc.port, svc.name);\n for (const svc of config.services) {\n if (alwaysOn.has(svc.name)) continue;\n const realPort = svc.port + LAZY_PORT_OFFSET;\n const conflict = portToSvc.get(realPort);\n if (conflict && conflict !== svc.name) {\n errors.push({\n field: `services[${svc.name}].port`,\n message: `Lazy real port ${realPort} (= ${svc.port}+${LAZY_PORT_OFFSET}) collides with service ${conflict}`,\n });\n }\n }\n }\n\n // External services\n if (config.external) {\n const extNames = new Set<string>();\n for (const ext of config.external) {\n if (!ext.name?.trim()) {\n errors.push({ field: 'external[].name', message: 'External service name is required' });\n continue;\n }\n if (extNames.has(ext.name)) {\n errors.push({ field: `external[${ext.name}].name`, message: `Duplicate external name: ${ext.name}` });\n }\n extNames.add(ext.name);\n if (!ext.cmd?.trim()) {\n errors.push({ field: `external[${ext.name}].cmd`, message: 'cmd is required' });\n }\n if (ext.healthCheck) {\n const hc = ext.healthCheck;\n if (hc.type !== 'tcp' && hc.type !== 'http') {\n errors.push({ field: `external[${ext.name}].healthCheck.type`, message: `Invalid healthCheck.type: ${hc.type}` });\n }\n if ((hc.type === 'tcp' || hc.type === 'http') && (typeof ext.port !== 'number' || ext.port <= 0)) {\n errors.push({ field: `external[${ext.name}].port`, message: `port is required when healthCheck is set (got ${ext.port})` });\n }\n if (hc.type === 'http' && hc.path && !hc.path.startsWith('/')) {\n errors.push({ field: `external[${ext.name}].healthCheck.path`, message: `must start with \"/\"` });\n }\n }\n }\n }\n\n // Proxy route refs\n if (config.proxy?.routes) {\n for (const ref of Object.keys(config.proxy.routes)) {\n if (!names.has(ref)) {\n errors.push({ field: `proxy.routes`, message: `Unknown service: ${ref}` });\n }\n }\n }\n\n // Profiles\n if (config.profiles) {\n for (const [profile, svcNames] of Object.entries(config.profiles)) {\n if (!Array.isArray(svcNames) || !svcNames.length) {\n errors.push({ field: `profiles.${profile}`, message: `Profile \"${profile}\" must be a non-empty array of service names` });\n continue;\n }\n for (const ref of svcNames) {\n if (!names.has(ref)) {\n errors.push({ field: `profiles.${profile}`, message: `Unknown service: ${ref}` });\n }\n }\n }\n }\n\n return errors;\n}\n\nexport function formatValidationErrors(errors: ValidationError[]): string {\n return errors.map(e => ` ✗ ${e.field}: ${e.message}`).join('\\n');\n}\n","import type { ServiceConfig, LazyConfig } from '../config/types.js';\n\nexport const LAZY_PORT_OFFSET = 10000;\nexport const DEFAULT_LAZY_TIMEOUT = 10;\n\nexport interface ClassifiedServices {\n alwaysOn: ServiceConfig[];\n lazy: ServiceConfig[];\n}\n\nexport function classifyServices(services: ServiceConfig[], config?: LazyConfig): ClassifiedServices {\n const alwaysOnSet = new Set(config?.alwaysOn ?? []);\n const alwaysOn: ServiceConfig[] = [];\n const lazy: ServiceConfig[] = [];\n\n for (const svc of services) {\n if (alwaysOnSet.has(svc.name)) alwaysOn.push(svc);\n else lazy.push(svc);\n }\n return { alwaysOn, lazy };\n}\n\nexport function getLazyRealPort(originalPort: number): number {\n return originalPort + LAZY_PORT_OFFSET;\n}\n\nexport function rewriteServicePort(svc: ServiceConfig): ServiceConfig & { realPort: number; originalPort: number } {\n const realPort = getLazyRealPort(svc.port);\n const args = svc.args.map(a => a === String(svc.port) ? String(realPort) : a);\n const extraEnv = { ...svc.extraEnv, PORT_OVERRIDE: String(realPort) };\n return { ...svc, port: realPort, args, extraEnv, realPort, originalPort: svc.port };\n}\n","import type { DevStackConfig, ServiceConfig } from './types.js';\n\nexport interface CliArgs {\n configPath?: string;\n only?: string;\n skip: string[];\n services?: string[];\n profile?: string;\n lazy: boolean;\n lazyTimeout: number;\n proxy: boolean;\n proxyHost?: string;\n proxyConf?: string;\n proxyTls: boolean;\n proxyEntrypoint: string;\n dryRun: boolean;\n once: boolean;\n onceTimeout: number;\n logFile: boolean;\n logDir?: string;\n watchConfig: boolean;\n killPortConflicts: boolean;\n}\n\nconst DEFAULT_LAZY_TIMEOUT = 10;\nconst DEFAULT_ONCE_TIMEOUT = 90;\n\nexport const USAGE = `devup — terminal UI dev stack runner\n\nUsage: devup [options]\n\nService selection:\n --only apis | webs Start only APIs or only webs\n --services a,b,c Start only the named services\n --profile <name> Start the services in a named profile (see ROADMAP)\n --skip a,b,c Start everything except these\n --config <path> Use a custom config file\n\nLazy mode:\n --lazy Enable lazy mode (default)\n --no-lazy Start every service immediately\n --timeout <minutes> Idle timeout for lazy services. Default: 10\n\nReverse proxy:\n --proxy Enable proxy config generation\n --proxy-host <host> Override the target host (Docker/local)\n --proxy-conf <path> Override the generated config file path\n --proxy-tls Enable TLS in the generated config (default)\n --no-proxy-tls Disable TLS\n --proxy-entrypoint <n> Override entrypoint name (Traefik only)\n\nCI / scripting:\n --dry-run Print the resolved boot plan and exit\n --once Boot, wait for readiness, exit 0/1 (no TUI)\n --once-timeout <s> Max seconds to wait in --once mode. Default: 90\n\nLog files:\n --no-log-file Disable persistent log files\n --log-dir <path> Override log root (default: ~/.devup/logs)\n\nHot reload:\n --watch-config Watch devup.config.* and apply add/remove/restart\n service changes without exiting the TUI\n\nPort conflicts:\n --kill-port-conflicts Kill any processes already holding a configured\n port before boot. Interactive prompt without it;\n required for non-TTY (daemon, --once, CI)\n\nOther:\n -h, --help Show this help and exit\n -v, --version Show version and exit\n\nSee https://github.com/gachlab/devup for the full documentation.`;\n\nexport function parseCliArgs(argv: string[]): CliArgs {\n const args: CliArgs = {\n skip: [],\n lazy: true,\n lazyTimeout: DEFAULT_LAZY_TIMEOUT,\n proxy: false,\n proxyTls: true,\n proxyEntrypoint: 'websecure',\n dryRun: false,\n once: false,\n onceTimeout: DEFAULT_ONCE_TIMEOUT,\n logFile: true,\n watchConfig: false,\n killPortConflicts: false,\n };\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n const next = argv[i + 1];\n\n switch (arg) {\n case '--config': args.configPath = next; i++; break;\n case '--only': args.only = next; i++; break;\n case '--skip': args.skip = next?.split(',') ?? []; i++; break;\n case '--services': args.services = next?.split(','); i++; break;\n case '--profile': args.profile = next; i++; break;\n case '--lazy': args.lazy = true; break;\n case '--no-lazy': args.lazy = false; break;\n case '--timeout': args.lazyTimeout = parseInt(next ?? '', 10) || DEFAULT_LAZY_TIMEOUT; i++; break;\n case '--proxy': args.proxy = true; break;\n case '--proxy-host': args.proxyHost = next; i++; break;\n case '--proxy-conf': args.proxyConf = next; i++; break;\n case '--proxy-tls': args.proxyTls = true; break;\n case '--no-proxy-tls': args.proxyTls = false; break;\n case '--proxy-entrypoint': args.proxyEntrypoint = next ?? 'websecure'; i++; break;\n case '--dry-run': args.dryRun = true; break;\n case '--once': args.once = true; break;\n case '--once-timeout': args.onceTimeout = parseInt(next ?? '', 10) || DEFAULT_ONCE_TIMEOUT; i++; break;\n case '--no-log-file': args.logFile = false; break;\n case '--log-dir': args.logDir = next; i++; break;\n case '--watch-config': args.watchConfig = true; break;\n case '--kill-port-conflicts': args.killPortConflicts = true; break;\n }\n }\n\n return args;\n}\n\nexport function filterServices(\n services: ServiceConfig[],\n args: CliArgs,\n config?: Pick<DevStackConfig, 'profiles'>,\n): ServiceConfig[] {\n let result = services;\n\n if (args.profile) {\n const profileNames = config?.profiles?.[args.profile];\n if (!profileNames) {\n const available = Object.keys(config?.profiles ?? {});\n const hint = available.length ? `Available: ${available.join(', ')}` : 'No profiles defined in config.';\n throw new Error(`Unknown profile: \"${args.profile}\". ${hint}`);\n }\n const set = new Set(profileNames);\n result = result.filter(s => set.has(s.name));\n } else if (args.services) {\n const explicit = new Set(args.services);\n result = result.filter(s => explicit.has(s.name));\n } else if (args.only) {\n switch (args.only) {\n case 'apis': result = result.filter(s => s.type === 'api'); break;\n case 'webs': result = result.filter(s => s.type === 'web'); break;\n default: result = result.filter(s => s.name.startsWith(args.only!)); break;\n }\n }\n\n if (args.skip.length) {\n const skipSet = new Set(args.skip);\n result = result.filter(s => !skipSet.has(s.name));\n }\n\n return result;\n}\n","import { spawn } from 'node:child_process';\nimport { createReadStream, watchFile, unwatchFile, existsSync, statSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { homedir } from 'node:os';\nimport { createInterface } from 'node:readline';\nimport { checkHealth } from '../process/health.js';\nimport { needsInstall, writeInstallStamp } from '../utils.js';\nimport { sendRpc, openStream, resolveSocket, assertSocketExists } from '../control-plane/client.js';\nimport { stopDaemon } from './daemon.js';\nimport type { DevStackConfig } from '../config/types.js';\n\nconst KNOWN = new Set(['logs', 'install', 'status', 'help', 'ctl', 'up', 'down']);\n\n/** Returns the subcommand name if the first arg is one we recognise, else null. */\nexport function detectSubcommand(argv: string[]): string | null {\n const first = argv[0];\n return first && KNOWN.has(first) ? first : null;\n}\n\ninterface SubOpts {\n config: DevStackConfig;\n baseCwd: string;\n env: Record<string, string>;\n logDir?: string;\n out?: (line: string) => void;\n}\n\nfunction logRoot(config: DevStackConfig, override?: string): string {\n const root = override ?? join(homedir(), '.devup', 'logs');\n return join(root, sanitize(config.name));\n}\n\nfunction sanitize(name: string): string {\n return name.replace(/[^a-zA-Z0-9._-]+/g, '_').replace(/^_+|_+$/g, '') || 'devup';\n}\n\n// ── devup logs <svc> [--follow] ──\n\nexport async function runLogs(argv: string[], opts: SubOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => console.log(l));\n const follow = argv.includes('--follow') || argv.includes('-f');\n const svcArg = argv.find(a => !a.startsWith('-'));\n if (!svcArg) {\n out('usage: devup logs <service> [--follow]');\n return 1;\n }\n const knownSvcs = opts.config.services.map(s => s.name);\n if (!knownSvcs.includes(svcArg)) {\n out(`Unknown service \"${svcArg}\". Known: ${knownSvcs.join(', ')}`);\n return 1;\n }\n const file = join(logRoot(opts.config, opts.logDir), `${sanitize(svcArg)}.log`);\n if (!existsSync(file)) {\n out(`No log file yet for \"${svcArg}\" (${file})`);\n return follow ? await followFile(file, out) : 1;\n }\n await streamFile(file, out);\n if (!follow) return 0;\n return await followFile(file, out, statSync(file).size);\n}\n\nasync function streamFile(file: string, out: (l: string) => void): Promise<void> {\n return new Promise((resolve, reject) => {\n const rl = createInterface({ input: createReadStream(file, { encoding: 'utf8' }) });\n rl.on('line', l => out(l));\n rl.on('close', () => resolve());\n rl.on('error', reject);\n });\n}\n\nasync function followFile(file: string, out: (l: string) => void, startAt = 0): Promise<number> {\n let pos = startAt;\n // Wait for the file to appear if it doesn't yet\n while (!existsSync(file)) await new Promise(r => setTimeout(r, 500));\n return new Promise(resolve => {\n const tick = async () => {\n const size = statSync(file).size;\n if (size > pos) {\n await new Promise<void>(res => {\n const rl = createInterface({ input: createReadStream(file, { encoding: 'utf8', start: pos, end: size - 1 }) });\n rl.on('line', l => out(l));\n rl.on('close', () => { pos = size; res(); });\n });\n } else if (size < pos) {\n // File was truncated / rotated — restart from beginning\n pos = 0;\n }\n };\n watchFile(file, { interval: 500 }, () => { void tick(); });\n process.once('SIGINT', () => { unwatchFile(file); resolve(0); });\n });\n}\n\n// ── devup install ──\n\nexport async function runInstall(opts: SubOpts & { concurrency?: number }): Promise<number> {\n const out = opts.out ?? ((l: string) => console.log(l));\n const concurrency = opts.concurrency ?? 4;\n const items = opts.config.services.map(s => ({ name: s.name, cwd: join(opts.baseCwd, s.cwd) }));\n const queue = [...items];\n const failed: string[] = [];\n let inFlight = 0;\n\n await new Promise<void>(resolve => {\n const pump = () => {\n while (inFlight < concurrency && queue.length) {\n const item = queue.shift()!;\n inFlight++;\n installOne(item.cwd, opts.env).then(ok => {\n inFlight--;\n if (ok) out(`✓ ${item.name}`);\n else { failed.push(item.name); out(`✗ ${item.name}`); }\n if (queue.length === 0 && inFlight === 0) resolve();\n else pump();\n });\n }\n };\n pump();\n });\n\n if (failed.length) {\n out(`\\nfailed: ${failed.join(', ')}`);\n return 1;\n }\n out(`\\n${items.length} services up to date`);\n return 0;\n}\n\nfunction installOne(cwd: string, env: Record<string, string>): Promise<boolean> {\n if (!existsSync(cwd)) return Promise.resolve(false);\n if (!needsInstall(cwd)) return Promise.resolve(true);\n return new Promise(resolve => {\n const command = process.platform === 'win32' ? 'npm.cmd' : 'npm';\n const proc = spawn(command, ['install'], { cwd, env, stdio: ['ignore', 'ignore', 'pipe'] });\n proc.on('close', code => {\n if (code === 0) { writeInstallStamp(cwd); resolve(true); } else resolve(false);\n });\n proc.on('error', () => resolve(false));\n });\n}\n\n// ── devup status ──\n\nexport async function runStatus(opts: SubOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => console.log(l));\n out(`${opts.config.icon ?? '📦'} ${opts.config.name} — ${opts.config.services.length} services`);\n out('');\n\n const maxLen = Math.max(...opts.config.services.map(s => s.name.length), 12);\n out(`${'Service'.padEnd(maxLen)} ${'Port'.padStart(5)} ${'Type'.padEnd(4)} Health`);\n out('-'.repeat(maxLen + 24));\n\n for (const svc of opts.config.services) {\n const up = await checkHealth(svc.port, svc.healthCheck);\n const health = up ? '✓ up' : '✗ down';\n out(`${svc.name.padEnd(maxLen)} ${String(svc.port).padStart(5)} ${svc.type.padEnd(4)} ${health}`);\n }\n return 0;\n}\n\n// ── devup ctl <method> [args] ──\n\ninterface CtlOpts {\n config: DevStackConfig;\n out?: (line: string) => void;\n socketPath?: string;\n}\n\ntype ServiceRow = {\n name: string; status: string; health: string;\n port: number; type: string; pid: number | null;\n errors: number; restarts: number;\n};\n\nfunction fmtStatus(rows: ServiceRow[], out: (l: string) => void): void {\n const maxLen = Math.max(...rows.map(r => r.name.length), 8);\n for (const r of rows) {\n const pid = r.pid != null ? `pid=${r.pid}` : ' ';\n const name = r.name.padEnd(maxLen);\n const port = `:${r.port}`.padStart(6);\n const status = r.status.padEnd(8);\n const health = r.health.padEnd(4);\n out(`${name} ${port} ${status} ${health} ${pid} errors=${r.errors} restarts=${r.restarts}`);\n }\n}\n\nexport async function runCtl(argv: string[], opts: CtlOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => process.stdout.write(l + '\\n'));\n const method = argv[0];\n const follow = argv.includes('--follow') || argv.includes('-f');\n const socketPath = resolveSocket(opts.config.name, opts.socketPath);\n\n if (!method || method === 'help') {\n out('Usage: devup ctl <method> [args] [--follow]');\n out(' ping Check if devup is running');\n out(' status [--follow] Service snapshot, or live updates');\n out(' logs <svc> [--follow] Tail logs (last 100), or follow live stream');\n out(' restart <svc> Restart a service');\n out(' stop <svc> Stop a service');\n return 0;\n }\n\n try {\n assertSocketExists(socketPath, opts.config.name);\n } catch (e: any) {\n out(e.message);\n return 1;\n }\n\n try {\n if (method === 'ping') {\n const res = await sendRpc(socketPath, 'ping') as { ok: boolean; ts: number };\n out(`pong ts=${res.ts}`);\n return 0;\n }\n\n if (method === 'status' && !follow) {\n const res = await sendRpc(socketPath, 'status') as { services: ServiceRow[] };\n if (!res.services.length) { out('(no services)'); return 0; }\n fmtStatus(res.services, out);\n return 0;\n }\n\n if (method === 'status' && follow) {\n return await new Promise<number>(resolve => {\n const abort = openStream(socketPath, 'status.follow', {}, frame => {\n const rows = frame.data as ServiceRow[];\n const ts = new Date().toISOString().slice(11, 23);\n for (const r of rows) {\n out(`[${ts}] ${r.name.padEnd(24)} ${r.status}/${r.health}`);\n }\n }, err => { out(`error: ${err.message}`); resolve(1); });\n process.once('SIGINT', () => { abort(); resolve(0); });\n });\n }\n\n if (method === 'logs') {\n const svc = argv.find((a, i) => i > 0 && !a.startsWith('-'));\n if (!svc) { out('usage: devup ctl logs <service> [--follow]'); return 1; }\n\n if (!follow) {\n const res = await sendRpc(socketPath, 'logs.tail', { svc, lines: 100 }) as { lines: string[] };\n for (const l of res.lines) out(l);\n return 0;\n }\n\n return await new Promise<number>(resolve => {\n const abort = openStream(socketPath, 'logs.follow', { svc, tail: 100 }, frame => {\n out(frame.data as string);\n }, err => { out(`error: ${err.message}`); resolve(1); });\n process.once('SIGINT', () => { abort(); resolve(0); });\n });\n }\n\n if (method === 'restart') {\n const svc = argv[1];\n if (!svc) { out('usage: devup ctl restart <service>'); return 1; }\n await sendRpc(socketPath, 'restart', { svc });\n out(`✓ restart sent to ${svc}`);\n return 0;\n }\n\n if (method === 'stop') {\n const svc = argv[1];\n if (!svc) { out('usage: devup ctl stop <service>'); return 1; }\n await sendRpc(socketPath, 'stop', { svc });\n out(`✓ stop sent to ${svc}`);\n return 0;\n }\n\n out(`unknown ctl method: ${method}. Run \\`devup ctl help\\` for usage.`);\n return 1;\n } catch (e: any) {\n out(`error: ${e.message}`);\n return 1;\n }\n}\n\n// ── devup down ──\n\nexport async function runDown(opts: SubOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => process.stdout.write(l + '\\n'));\n return stopDaemon(opts.config.name, { out });\n}\n\n// ── devup help <subcommand> ──\n\nexport function runHelp(argv: string[], opts: { out?: (l: string) => void } = {}): number {\n const out = opts.out ?? ((l: string) => console.log(l));\n const sub = argv[0];\n if (sub === 'logs') {\n out('Usage: devup logs <service> [--follow|-f]');\n out(' Print the persisted log file for a service (works without devup running).');\n out(' --follow tails new lines as they are appended.');\n return 0;\n }\n if (sub === 'install') {\n out('Usage: devup install');\n out(' Run `npm install` across every service.cwd in parallel (max 4 at a time).');\n out(' Skips services whose .install-stamp matches package.json hash.');\n return 0;\n }\n if (sub === 'status') {\n out('Usage: devup status');\n out(' For each service, probes its health-check endpoint and prints up/down.');\n return 0;\n }\n if (sub === 'ctl') {\n out('Usage: devup ctl <method> [args] [--follow]');\n out(' Send commands to a running devup process via the control plane socket.');\n out('');\n out(' ping Check if devup is running');\n out(' status [--follow] Service snapshot, or live state-change stream');\n out(' logs <svc> [--follow] Tail last 100 lines, or follow the live stream');\n out(' restart <svc> Restart the named service');\n out(' stop <svc> Stop the named service');\n out('');\n out(' devup must be running in the same project directory.');\n return 0;\n }\n if (sub === 'up') {\n out('Usage: devup up -d');\n out(' Boot the stack in detached/daemon mode (like `docker compose up -d`).');\n out(' Returns immediately once the stack is healthy; services keep running.');\n out(' Use `devup ctl status`, `devup ctl logs`, or `devup down` to interact.');\n out(' Not supported on Windows yet — use `devup` (TUI) instead.');\n return 0;\n }\n if (sub === 'down') {\n out('Usage: devup down');\n out(' Stop the daemon for the current project. SIGTERM with 10s grace,');\n out(' then SIGKILL. Removes the PID file and the control-plane socket.');\n return 0;\n }\n out('Subcommands:');\n out(' devup logs <service> [--follow] Read the persisted log file');\n out(' devup install Concurrent npm install across services');\n out(' devup status Health check every service in config');\n out(' devup up -d Boot the stack in detached/daemon mode');\n out(' devup down Stop the running daemon');\n out(' devup ctl <method> [args] Control a running devup (restart/stop/logs/...)');\n out(' devup help [<subcommand>] Show detailed help for a subcommand');\n out('');\n out('No subcommand → launch the interactive TUI.');\n return 0;\n}\n\nvoid readFile;\nvoid dirname;\nvoid fileURLToPath;\n","import net from 'node:net';\nimport http from 'node:http';\nimport type { HealthStatus } from './types.js';\nimport type { HealthCheckConfig } from '../config/types.js';\n\n/** \"Is something accepting connections at port?\" — connect-based test.\n * Use this for health checks and waitForPort, where \"occupied\" means\n * \"the service is up\". Do NOT use this to decide whether to spawn — use\n * `isPortBindable` instead (a bound but pre-accept server would slip\n * through this check). */\nexport function checkPort(port: number, host = '127.0.0.1', timeoutMs = 2000): Promise<boolean> {\n return new Promise(resolve => {\n const socket = new net.Socket();\n socket.setTimeout(timeoutMs);\n socket.once('connect', () => { socket.destroy(); resolve(true); });\n socket.once('error', () => { socket.destroy(); resolve(false); });\n socket.once('timeout', () => { socket.destroy(); resolve(false); });\n socket.connect(port, host);\n });\n}\n\n/** \"Can I bind to this port right now?\" — bind-based test. Returns true\n * if a server could listen on the port on every wildcard address. Used as\n * the pre-flight before spawning a service: catches every case that would\n * cause the spawned process to die with EADDRINUSE, including bound-but-\n * not-yet-accepting states that `checkPort` misses.\n *\n * Implementation detail: tests both IPv4 (`0.0.0.0`) and IPv6 (`::`)\n * wildcards. On Linux these usually share an address space (IPV6_V6ONLY=0),\n * so a single test suffices; on Windows the defaults isolate the stacks,\n * so a one-stack test can miss a conflicting bind on the other. We require\n * both stacks to be free to call the port bindable. */\nexport async function isPortBindable(port: number): Promise<boolean> {\n // Sequential, not parallel — on Linux the IPv4/IPv6 wildcards share an\n // address space, so two simultaneous test-binds race each other and the\n // second loses with EADDRINUSE even when the port is genuinely free.\n for (const host of ['0.0.0.0', '::']) {\n if (!(await tryBind(port, host))) return false;\n }\n return true;\n}\n\nfunction tryBind(port: number, host: string): Promise<boolean> {\n return new Promise(resolve => {\n const server = net.createServer();\n server.once('error', (err: NodeJS.ErrnoException) => {\n // EADDRINUSE / EACCES → conflict. Other errors (e.g. EAFNOSUPPORT on an\n // IPv6-disabled box) we treat as \"stack unavailable, not a conflict\".\n if (err.code === 'EADDRINUSE' || err.code === 'EACCES') resolve(false);\n else resolve(true);\n });\n server.once('listening', () => server.close(() => resolve(true)));\n server.listen(port, host);\n });\n}\n\nexport function checkHttp(\n port: number,\n opts: { path?: string; expect?: number | number[]; host?: string; timeoutMs?: number } = {},\n): Promise<boolean> {\n const path = opts.path ?? '/';\n const host = opts.host ?? '127.0.0.1';\n const timeoutMs = opts.timeoutMs ?? 2000;\n const accept = (code: number) => {\n if (opts.expect === undefined) return code >= 200 && code < 300;\n if (Array.isArray(opts.expect)) return opts.expect.includes(code);\n return code === opts.expect;\n };\n return new Promise(resolve => {\n const req = http.get({ host, port, path, timeout: timeoutMs }, res => {\n const ok = typeof res.statusCode === 'number' && accept(res.statusCode);\n res.resume();\n resolve(ok);\n });\n req.on('error', () => resolve(false));\n req.on('timeout', () => { req.destroy(); resolve(false); });\n });\n}\n\n/** Run the right check for a service, given its optional healthCheck config. */\nexport function checkHealth(port: number, hc?: HealthCheckConfig): Promise<boolean> {\n if (hc?.type === 'http') {\n return checkHttp(port, {\n path: hc.path, expect: hc.expect, host: hc.host, timeoutMs: hc.timeoutMs,\n });\n }\n return checkPort(port, '127.0.0.1', hc?.timeoutMs);\n}\n\nexport function waitForPort(port: number, opts: { timeout?: number; interval?: number } = {}): Promise<boolean> {\n const { timeout = 45000, interval = 1000 } = opts;\n return new Promise(resolve => {\n const start = Date.now();\n const check = () => {\n checkPort(port).then(ok => {\n if (ok) return resolve(true);\n if (Date.now() - start > timeout) return resolve(false);\n setTimeout(check, interval);\n });\n };\n check();\n });\n}\n\nexport function deriveHealth(isUp: boolean, currentStatus: string): HealthStatus {\n if (currentStatus === 'idle') return 'idle';\n if (isUp) return 'up';\n return currentStatus === 'starting' ? 'wait' : 'down';\n}\n","import { existsSync, readFileSync } from 'node:fs';\n\n/** Reads a `.env`-style file and overlays it on top of `baseEnv`.\n * Lines starting with `#` are comments. Quoted values get the quotes stripped.\n * Existing keys in `baseEnv` win — file values only fill the gaps. */\nexport function parseEnvFile(filePath: string, baseEnv: Record<string, string> = {}): Record<string, string> {\n const env = { ...baseEnv };\n if (!existsSync(filePath)) return env;\n\n for (const line of readFileSync(filePath, 'utf8').split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIdx = trimmed.indexOf('=');\n if (eqIdx === -1) continue;\n const key = trimmed.slice(0, eqIdx).trim();\n let val = trimmed.slice(eqIdx + 1).trim();\n if ((val.startsWith('\"') && val.endsWith('\"')) || (val.startsWith(\"'\") && val.endsWith(\"'\"))) {\n val = val.slice(1, -1);\n }\n if (!env[key]) env[key] = val;\n }\n return env;\n}\n","/** Formats a duration (in ms) as a short human string: 45s, 2m5s, 1h2m, 2d3h. */\nexport function fmtUptime(ms: number): string {\n if (!ms || ms < 0) return '-';\n const s = Math.floor(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m${s % 60}s`;\n const h = Math.floor(m / 60);\n if (h < 24) return `${h}h${m % 60}m`;\n const d = Math.floor(h / 24);\n return `${d}d${h % 24}h`;\n}\n","export interface SearchMatcher {\n test: (line: string) => boolean;\n /** Set when the input was a vim-style /pattern/flags — used to drive highlighting. */\n regex?: RegExp;\n /** True when input started with `/` but produced an invalid regex; UI may show a hint. */\n invalid?: boolean;\n}\n\n/** Compiles a search term to a matcher.\n * - `/foo/` → regex (case-insensitive by default; honors flags after the closing slash)\n * - anything else → case-insensitive substring (existing behavior)\n * - invalid regex → falls back to substring, sets `invalid: true` */\nexport function compileSearchPattern(term: string | null): SearchMatcher | null {\n if (!term) return null;\n const slashed = /^\\/(.+)\\/([gimsuy]*)$/.exec(term);\n if (slashed) {\n const flags = slashed[2]!.includes('i') ? slashed[2]! : slashed[2]! + 'i';\n try {\n const re = new RegExp(slashed[1]!, flags);\n return { test: (l: string) => re.test(l), regex: re };\n } catch {\n const lower = term.toLowerCase();\n return { test: (l: string) => l.toLowerCase().includes(lower), invalid: true };\n }\n }\n const lower = term.toLowerCase();\n return { test: (l: string) => l.toLowerCase().includes(lower) };\n}\n\nexport type LogLevel = 'error' | 'warn' | 'info';\n\n/** Detects the level of a log line by case-insensitive keyword priority:\n * error (and synonyms) > warn > info. Used by the L-level filter. */\nexport function detectLogLevel(line: string): LogLevel {\n const l = line.toLowerCase();\n // Conjugations covered for fail/crash; `error` and `exception` matched as exact word.\n if (/\\b(?:error|err|fail(?:ed|ure|ures|s)?|fatal|exception|crash(?:ed|es)?)\\b/.test(l) || /❌|✗|⛔/.test(line)) return 'error';\n if (/\\b(?:warn(?:ed|ing|s|ings)?|deprec)\\b/.test(l) || /⚠/.test(line)) return 'warn';\n return 'info';\n}\n","/** Returns the env record with values redacted to *** for keys that look\n * secret-ish (token / password / secret / key / auth). Case-insensitive. */\nexport function redactSecrets(env: Record<string, string> | undefined): Record<string, string> {\n if (!env) return {};\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) {\n out[k] = /secret|token|password|api[_-]?key|auth/i.test(k) ? '***' : v;\n }\n return out;\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { join } from 'node:path';\n\n/** Returns true if the service's node_modules is missing or its install stamp\n * doesn't match the current package.json hash. */\nexport function needsInstall(fullCwd: string): boolean {\n const nm = join(fullCwd, 'node_modules');\n if (!existsSync(nm)) return true;\n try {\n const pkgHash = createHash('md5').update(readFileSync(join(fullCwd, 'package.json'))).digest('hex');\n const stampFile = join(nm, '.install-stamp');\n if (existsSync(stampFile) && readFileSync(stampFile, 'utf8') === pkgHash) return false;\n } catch { /* stamp missing or unreadable */ }\n return true;\n}\n\n/** Writes the install stamp file for a service after a successful `npm install`. */\nexport function writeInstallStamp(fullCwd: string): void {\n try {\n const pkgHash = createHash('md5').update(readFileSync(join(fullCwd, 'package.json'))).digest('hex');\n writeFileSync(join(fullCwd, 'node_modules', '.install-stamp'), pkgHash);\n } catch { /* best effort */ }\n}\n","import type { ServiceConfig } from '../config/types.js';\n\n/** Builds the final args list for spawning a service: prepends `--max-old-space-size`\n * for `node` commands when maxMem is set, plus any nodeArgs overrides. */\nexport function buildProcessArgs(svc: ServiceConfig): string[] {\n const extra = svc.nodeArgs ?? [];\n if (!svc.maxMem) return [...extra, ...svc.args];\n if (svc.cmd === 'node') return [`--max-old-space-size=${svc.maxMem}`, ...extra, ...svc.args];\n return [...extra, ...svc.args];\n}\n\n/** Builds the env for spawning a service: merges extraEnv and injects\n * NODE_OPTIONS=--max-old-space-size when maxMem is set and cmd != 'node'. */\nexport function buildProcessEnv(svc: ServiceConfig, baseEnv: Record<string, string>): Record<string, string> {\n const env = { ...baseEnv, ...(svc.extraEnv ?? {}) };\n if (svc.maxMem && svc.cmd !== 'node') {\n const existing = env['NODE_OPTIONS'] ?? '';\n const flag = `--max-old-space-size=${svc.maxMem}`;\n if (!existing.includes('max-old-space-size')) {\n env['NODE_OPTIONS'] = existing ? `${existing} ${flag}` : flag;\n }\n }\n return env;\n}\n","/** Returns a copy of `names` sorted by the requested mode.\n * - `'name'` → alphabetical\n * - `'mem'` → highest mem first (string-parsed)\n * - any other (treated as `'errors'`) → highest error count first */\nexport function sortServiceNames(\n names: string[], sortMode: string,\n statsMap: Record<string, { cpu?: string; mem?: string }>,\n procState: Record<string, { errors?: number }>,\n): string[] {\n if (sortMode === 'name') return names.slice().sort();\n return names.slice().sort((a, b) => {\n if (sortMode === 'mem') {\n return (parseFloat(statsMap[b]?.mem ?? '0') || 0) - (parseFloat(statsMap[a]?.mem ?? '0') || 0);\n }\n return (procState[b]?.errors ?? 0) - (procState[a]?.errors ?? 0);\n });\n}\n\n/** Converts cumulative CPU seconds into a percentage of wall-clock time\n * elapsed since the previous sample. */\nexport function calcCpuPercent(totalCpuSec: number, prevCpu: number, prevTime: number): number {\n const elapsed = (Date.now() - prevTime) / 1000;\n const cpuDelta = totalCpuSec - prevCpu;\n return elapsed > 0 ? (cpuDelta / elapsed) * 100 : 0;\n}\n\n/** Hysteresis state machine for the \"RAM pressure\" banner.\n * - turns on when usagePct ≥ highWatermark\n * - turns off when usagePct < lowWatermark\n * - stays as-is in the dead band between watermarks */\nexport function nextRamBannerVisibility(\n usagePct: number,\n previousVisible: boolean,\n highWatermark = 80,\n lowWatermark = 75,\n): boolean {\n if (usagePct >= highWatermark) return true;\n if (usagePct < lowWatermark) return false;\n return previousVisible;\n}\n","import type { ServiceConfig } from '../config/types.js';\n\n/** Groups a flat list of services by their `phase` field. */\nexport function groupByPhase(services: ServiceConfig[]): Record<number, ServiceConfig[]> {\n const phases: Record<number, ServiceConfig[]> = {};\n for (const s of services) {\n (phases[s.phase] ??= []).push(s);\n }\n return phases;\n}\n","/** Color palette used for the service-tag prefix in the logs panel.\n * Wrapped modulo length when there are more services than entries. */\nexport const tagColors = [\n 'cyan', 'yellow', 'green', 'magenta', 'blue',\n 'red', '#5faf5f', '#d7af5f', '#5f87d7', '#af5faf',\n '#5fd7d7', '#d75f5f', 'white',\n];\n","import { createConnection } from 'node:net';\nimport { createInterface } from 'node:readline';\nimport { existsSync } from 'node:fs';\nimport { defaultSocketPath } from './socket-server.js';\n\nexport { defaultSocketPath };\n\n/** Resolve the socket path, preferring an explicit override. */\nexport function resolveSocket(projectName: string, overridePath?: string): string {\n return overridePath ?? defaultSocketPath(projectName);\n}\n\n/** Throw a friendly error if the socket doesn't exist (devup not running). */\nexport function assertSocketExists(socketPath: string, projectName: string): void {\n if (!existsSync(socketPath)) {\n throw new Error(\n `devup is not running for project \"${projectName}\".\\nStart it with \\`devup\\` first.`,\n );\n }\n}\n\n/** Send a single RPC request and return the result, or throw on error. */\nexport function sendRpc(\n socketPath: string,\n method: string,\n params: Record<string, unknown> = {},\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let settled = false;\n const fail = (err: Error) => { if (!settled) { settled = true; reject(err); } };\n const ok = (v: unknown) => { if (!settled) { settled = true; resolve(v); } };\n\n const c = createConnection(socketPath);\n const rl = createInterface({ input: c });\n // Both the socket AND the readline interface can emit 'error' (readline\n // re-forwards errors from its input stream). Attach to BOTH so an\n // ECONNREFUSED on the socket can't escape as an unhandled error event.\n c.on('error', fail);\n rl.on('error', fail);\n rl.once('line', l => {\n c.end();\n try {\n const msg = JSON.parse(l);\n if (msg.error) fail(new Error(msg.error.message ?? String(msg.error)));\n else ok(msg.result);\n } catch (e: any) {\n fail(e);\n }\n });\n c.write(JSON.stringify({ id: 1, method, params }) + '\\n');\n });\n}\n\nexport interface StreamFrame {\n event: string;\n data: unknown;\n svc?: string;\n}\n\n/** Open a streaming RPC (logs.follow / status.follow).\n * Returns an abort function. The stream runs until abort() is called or the socket closes. */\nexport function openStream(\n socketPath: string,\n method: string,\n params: Record<string, unknown>,\n onFrame: (frame: StreamFrame) => void,\n onError?: (err: Error) => void,\n): () => void {\n const c = createConnection(socketPath);\n const rl = createInterface({ input: c });\n let ackDone = false;\n\n // Both the socket and the readline interface can emit 'error'. Listen on\n // both — without an rl handler an ECONNREFUSED can escape as an unhandled\n // 'error' event and crash the host process.\n const onErr = (err: Error) => onError?.(err);\n c.on('error', onErr);\n rl.on('error', onErr);\n c.write(JSON.stringify({ id: 1, method, params }) + '\\n');\n\n rl.on('line', l => {\n try {\n const msg = JSON.parse(l);\n if (!ackDone) {\n ackDone = true;\n if (msg.error) { onError?.(new Error(msg.error.message ?? String(msg.error))); c.destroy(); }\n return;\n }\n if (msg.event) onFrame(msg as StreamFrame);\n } catch { /* ignore malformed frames */ }\n });\n\n return () => c.destroy();\n}\n","import { createServer, type Server, type Socket } from 'node:net';\nimport { createInterface } from 'node:readline';\nimport { existsSync, unlinkSync, chmodSync, mkdirSync, statSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { ProcessState } from '../process/types.js';\n\n/** Minimal JSON-RPC-like protocol over a local Unix socket.\n * Request ─► { id?, method, params? } newline-terminated JSON\n * Response ─► { id?, result | error } newline-terminated JSON\n * Stream ─► { id, event, data } pushed until socket closes\n *\n * Auth model: unix socket created with `chmod 0600`. Anyone with read access\n * to the socket file already has the same uid as the devup process — no\n * additional auth needed. Strictly local; TCP exposure is intentionally\n * out of scope. */\n\nexport interface ServiceStatEntry {\n cpu: number; // percent (e.g. 2.3)\n memMB: number; // RSS in MB (e.g. 184.2)\n}\n\nexport interface StatsResult {\n services: Record<string, ServiceStatEntry>;\n system: {\n totalMemMB: number;\n freeMemMB: number;\n cpuCores: number;\n };\n}\n\nexport interface ProxyInfo {\n active: boolean;\n provider: string;\n domain: string;\n tls: boolean;\n routes: Record<string, string>;\n}\n\nexport interface RpcContext {\n /** State of every service (read-only snapshot). */\n states(): Map<string, ProcessState>;\n /** Restart a service by name. */\n restart(name: string): Promise<void>;\n /** Stop a service by name. */\n stop(name: string): void;\n /** Tail N most recent log lines for the given service (from the persistent log file). */\n tailLogs(svcName: string, lines: number): Promise<string[]>;\n /** Subscribe to live log lines. Pass null to receive logs from all services.\n * Returns an unsubscribe function. */\n watchLogs(svcName: string | null, onLine: (svc: string, line: string) => void): () => void;\n /** Subscribe to service-state changes. Returns an unsubscribe function. */\n watchStatus(onUpdate: (name: string, state: ProcessState) => void): () => void;\n /** Per-service CPU/mem stats + system totals. */\n getStats(): Promise<StatsResult>;\n /** Active proxy configuration, or null when no proxy is running. */\n getProxyInfo(): ProxyInfo | null;\n}\n\nexport interface SocketServerHandle {\n server: Server;\n path: string;\n close(): Promise<void>;\n}\n\nexport function defaultSocketPath(projectName: string): string {\n const safe = projectName.replace(/[^a-zA-Z0-9._-]+/g, '_') || 'devup';\n return join(homedir(), '.devup', `sock-${safe}.sock`);\n}\n\nexport async function startSocketServer(\n projectName: string,\n ctx: RpcContext,\n opts: { path?: string; onLog?: (msg: string) => void } = {},\n): Promise<SocketServerHandle> {\n const path = opts.path ?? defaultSocketPath(projectName);\n mkdirSync(dirname(path), { recursive: true });\n\n // Stale socket from a crashed previous run.\n if (existsSync(path)) {\n try {\n const st = statSync(path);\n if (st.isSocket()) unlinkSync(path);\n } catch { /* ignore — listen() will surface the real error */ }\n }\n\n // Track every active client socket so `close()` can destroy them. Without\n // this, `server.close()` waits for all clients to disconnect on their own\n // — and long-lived streaming clients (logs.follow / status.follow, e.g.\n // the VS Code extension) keep the connection open indefinitely, which\n // means `devup down` would hang past its 10 s grace and SIGKILL the daemon\n // before cleanup could run, leaking child processes.\n const activeClients = new Set<Socket>();\n const server = createServer(socket => {\n activeClients.add(socket);\n socket.once('close', () => activeClients.delete(socket));\n handleClient(socket, ctx);\n });\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(path, () => {\n server.off('error', reject);\n try { chmodSync(path, 0o600); } catch { /* best effort on platforms without chmod */ }\n opts.onLog?.(`🔌 control plane at ${path}`);\n resolve();\n });\n });\n\n return {\n server,\n path,\n async close() {\n // Destroy active clients first so server.close() can complete promptly.\n for (const sock of activeClients) sock.destroy();\n activeClients.clear();\n await new Promise<void>(resolve => server.close(() => resolve()));\n if (existsSync(path)) {\n try { unlinkSync(path); } catch { /* ignore */ }\n }\n },\n };\n}\n\nfunction handleClient(socket: Socket, ctx: RpcContext): void {\n const rl = createInterface({ input: socket });\n const unsubs = new Set<() => void>();\n\n socket.on('close', () => {\n for (const unsub of unsubs) unsub();\n unsubs.clear();\n });\n\n rl.on('line', async (line: string) => {\n if (!line.trim()) return;\n let req: { id?: unknown; method?: unknown; params?: unknown };\n try {\n req = JSON.parse(line);\n } catch (e: any) {\n respond(socket, { error: { code: -32700, message: `parse error: ${e.message}` } });\n return;\n }\n if (typeof req.method !== 'string') {\n respond(socket, { id: req.id, error: { code: -32600, message: 'method required' } });\n return;\n }\n const params = (req.params ?? {}) as Record<string, unknown>;\n if (req.method === 'logs.follow' || req.method === 'status.follow') {\n try {\n await handleFollow(socket, req as { id?: unknown; method: string }, params, ctx, unsubs);\n } catch (e: any) {\n respond(socket, { id: req.id, error: { code: -32603, message: e.message ?? String(e) } });\n }\n return;\n }\n try {\n const result = await dispatch(req.method, params, ctx);\n respond(socket, { id: req.id, result });\n } catch (e: any) {\n respond(socket, { id: req.id, error: { code: -32603, message: e.message ?? String(e) } });\n }\n });\n socket.on('error', () => {/* swallow ECONNRESET etc. */});\n}\n\nasync function handleFollow(\n socket: Socket,\n req: { id?: unknown; method: string },\n params: Record<string, unknown>,\n ctx: RpcContext,\n unsubs: Set<() => void>,\n): Promise<void> {\n if (req.method === 'logs.follow') {\n const rawSvc = params['svc'] ?? params['service'];\n const svcName = rawSvc != null ? stringOrThrow(rawSvc, 'svc') : null;\n const tail = Math.max(0, Math.min(1000, Number(params['tail'] ?? 50)));\n\n respond(socket, { id: req.id, result: { ok: true } });\n\n // Replay recent history before going live.\n if (svcName) {\n const lines = await ctx.tailLogs(svcName, tail);\n for (const l of lines) {\n respond(socket, { id: req.id, event: 'log', data: l });\n }\n }\n\n const unsub = ctx.watchLogs(svcName, (svc, line) => {\n respond(socket, { id: req.id, event: 'log', data: line, svc });\n });\n unsubs.add(unsub);\n\n } else {\n // status.follow\n respond(socket, { id: req.id, result: { ok: true } });\n\n // Send current snapshot immediately so the client has something to render.\n const snapshot: Array<Record<string, unknown>> = [];\n for (const [name, st] of ctx.states()) {\n snapshot.push(serializeState(name, st));\n }\n if (snapshot.length) {\n respond(socket, { id: req.id, event: 'status', data: snapshot });\n }\n\n const unsub = ctx.watchStatus((name, state) => {\n respond(socket, { id: req.id, event: 'status', data: [serializeState(name, state)] });\n });\n unsubs.add(unsub);\n }\n}\n\nfunction serializeState(name: string, st: ProcessState): Record<string, unknown> {\n return {\n name,\n status: st.status,\n health: st.health,\n port: st.svc.port,\n type: st.svc.type,\n errors: st.errors,\n restarts: st.restarts,\n pid: st.pid,\n startedAt: st.startedAt,\n };\n}\n\nfunction respond(socket: Socket, payload: object): void {\n if (socket.writable) socket.write(JSON.stringify(payload) + '\\n');\n}\n\nasync function dispatch(\n method: string,\n params: Record<string, unknown>,\n ctx: RpcContext,\n): Promise<unknown> {\n switch (method) {\n case 'status': {\n const out: Array<Record<string, unknown>> = [];\n for (const [name, st] of ctx.states()) {\n out.push(serializeState(name, st));\n }\n return { services: out, proxy: ctx.getProxyInfo() };\n }\n case 'stats':\n return await ctx.getStats();\n case 'restart': {\n const svc = stringOrThrow(params['svc'] ?? params['service'], 'svc');\n await ctx.restart(svc);\n return { ok: true };\n }\n case 'stop': {\n const svc = stringOrThrow(params['svc'] ?? params['service'], 'svc');\n ctx.stop(svc);\n return { ok: true };\n }\n case 'logs.tail': {\n const svc = stringOrThrow(params['svc'] ?? params['service'], 'svc');\n const lines = Math.max(1, Math.min(10_000, Number(params['lines'] ?? 100)));\n return { lines: await ctx.tailLogs(svc, lines) };\n }\n case 'ping':\n return { ok: true, ts: Date.now() };\n default:\n throw new Error(`unknown method: ${method}`);\n }\n}\n\nfunction stringOrThrow(v: unknown, paramName: string): string {\n if (typeof v !== 'string' || !v.trim()) {\n throw new Error(`param \"${paramName}\" must be a non-empty string`);\n }\n return v;\n}\n","import { spawn } from 'node:child_process';\nimport { writeFileSync, readFileSync, existsSync, unlinkSync, mkdirSync, createReadStream } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir, totalmem, freemem, cpus } from 'node:os';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { createInterface } from 'node:readline';\n\nimport { ProcessManager } from '../process/manager.js';\nimport { LogSink } from '../process/log-sink.js';\nimport { groupByPhase, calcCpuPercent } from '../utils.js';\nimport { waitForPort } from '../process/health.js';\nimport { Broadcaster } from '../utils/broadcaster.js';\nimport { startSocketServer, type SocketServerHandle } from '../control-plane/socket-server.js';\nimport { startExternals, stopExternals, type ExternalProc } from '../process/external.js';\nimport { classifyServices, rewriteServicePort } from '../lazy/classifier.js';\nimport { createLazyProxy, type LazyProxy } from '../lazy/proxy.js';\nimport { watchConfig } from './config-watcher.js';\nimport { findConfigFile } from '../config/loader.js';\n\nimport type { DevStackConfig, ServiceConfig } from '../config/types.js';\nimport type { CliArgs } from '../config/cli.js';\nimport type { Platform } from '../platform/types.js';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from '../proxy-config/types.js';\nimport type { ProcessState } from '../process/types.js';\n\nconst SAFE = /[^a-zA-Z0-9._-]+/g;\nconst sanitize = (n: string) => n.replace(SAFE, '_').replace(/^_+|_+$/g, '') || 'devup';\nconst devupDir = () => join(homedir(), '.devup');\n\nexport function pidPathFor(projectName: string): string {\n return join(devupDir(), `${sanitize(projectName)}.pid`);\n}\nexport function bootErrorPathFor(projectName: string): string {\n return join(devupDir(), `${sanitize(projectName)}.boot-error`);\n}\n\nfunction pidAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\n/** Inspect the PID file. `pid=null` means no daemon recorded.\n * `stale=true` means a pid file exists but the recorded pid is not alive. */\nexport function isDaemonRunning(projectName: string): { pid: number | null; stale: boolean } {\n const path = pidPathFor(projectName);\n if (!existsSync(path)) return { pid: null, stale: false };\n let pid: number;\n try {\n pid = Number(readFileSync(path, 'utf8').trim());\n if (!pid || !Number.isFinite(pid)) return { pid: null, stale: true };\n } catch {\n return { pid: null, stale: true };\n }\n return pidAlive(pid) ? { pid, stale: false } : { pid, stale: true };\n}\n\n// ── Daemon child body ──────────────────────────────────────────────────────\n\nexport interface DaemonOpts {\n config: DevStackConfig;\n services: ServiceConfig[];\n cliArgs: CliArgs;\n platform: Platform;\n env: Record<string, string>;\n baseCwd: string;\n proxyProvider: ProxyConfigProvider | null;\n proxyOpts: ProxyOpts | null;\n}\n\n/** Runs in the detached child process. Boots the stack, opens the control\n * plane, writes the PID file when ready (the parent's success signal), then\n * stays alive until SIGTERM/SIGINT. */\nexport async function daemonBody(opts: DaemonOpts): Promise<void> {\n const { config, services, cliArgs, platform, env, baseCwd, proxyProvider, proxyOpts } = opts;\n const projectName = config.name;\n const errPath = bootErrorPathFor(projectName);\n const pidPath = pidPathFor(projectName);\n\n mkdirSync(devupDir(), { recursive: true });\n if (existsSync(errPath)) { try { unlinkSync(errPath); } catch { /* ignore */ } }\n\n // Always write logs to disk in daemon mode (no terminal to scroll back through).\n const logSink = new LogSink({ projectName, rootDir: cliArgs.logDir });\n\n const logBus = new Broadcaster<{ svc: string; text: string }>();\n const stateBus = new Broadcaster<{ name: string; state: ProcessState }>();\n const lazyProxies = new Map<string, LazyProxy>();\n const prevCpuMap = new Map<string, { time: number; cpu: number }>();\n let externals: ExternalProc[] = [];\n let socket: SocketServerHandle | null = null;\n let healthTimer: NodeJS.Timeout | null = null;\n let proxyTimer: NodeJS.Timeout | null = null;\n let stopConfigWatcher: (() => void) | null = null;\n\n const writeDevupLog = (text: string) => {\n logSink.write('devup', text);\n logBus.emit({ svc: 'devup', text });\n };\n\n const mgr = new ProcessManager({\n baseCwd, env, platform,\n events: {\n onLog: (svcName, text) => {\n logSink.write(svcName, text);\n logBus.emit({ svc: svcName, text });\n },\n onStateChange: (name, state) => stateBus.emit({ name, state }),\n },\n });\n\n const cleanup = async (): Promise<void> => {\n if (healthTimer) clearInterval(healthTimer);\n if (proxyTimer) clearInterval(proxyTimer);\n if (stopConfigWatcher) { try { stopConfigWatcher(); } catch { /* ignore */ } }\n for (const p of lazyProxies.values()) p.destroy();\n if (socket) await socket.close().catch(() => {});\n await mgr.cleanup().catch(() => {});\n if (externals.length) {\n await stopExternals(externals, platform, {\n baseCwd, env,\n onLog: (svc, msg) => logSink.write(`ext:${svc}`, msg),\n }).catch(() => {});\n }\n if (proxyProvider && proxyOpts && cliArgs.proxy) {\n try { proxyProvider.clear(proxyOpts); } catch { /* ignore */ }\n }\n await logSink.close().catch(() => {});\n if (existsSync(pidPath)) { try { unlinkSync(pidPath); } catch { /* ignore */ } }\n };\n\n let shuttingDown = false;\n const onSignal = () => {\n if (shuttingDown) return;\n shuttingDown = true;\n cleanup().then(() => process.exit(0), () => process.exit(1));\n };\n process.on('SIGTERM', onSignal);\n process.on('SIGINT', onSignal);\n\n try {\n // ── Externals (DBs, queues) — must be healthy before phase 0 ──\n if (config.external?.length) {\n writeDevupLog(`▶ externals (${config.external.length})`);\n const result = await startExternals(config.external, {\n baseCwd, env, platform,\n onLog: (svc, msg) => { logSink.write(`ext:${svc}`, msg); logBus.emit({ svc: `ext:${svc}`, text: msg }); },\n });\n externals = result.procs;\n if (!result.allHealthy) {\n throw new Error(`externals failed: ${result.failed.join(', ')}`);\n }\n }\n\n // ── Boot phases ──\n if (cliArgs.lazy && config.lazy) {\n await bootLazy(mgr, services, config.lazy, cliArgs.lazyTimeout, lazyProxies);\n } else {\n await bootNormal(mgr, services);\n }\n\n // ── Control plane ──\n socket = await startSocketServer(projectName, {\n states: () => mgr.state,\n restart: (n) => mgr.restart(n),\n stop: (n) => mgr.stop(n),\n tailLogs: async (svcName, lines) => {\n const file = logSink.pathFor(svcName);\n if (!existsSync(file)) return [];\n return new Promise<string[]>((resolve, reject) => {\n const buf: string[] = [];\n const rl = createInterface({ input: createReadStream(file, { encoding: 'utf8' }) });\n rl.on('line', l => { buf.push(l); if (buf.length > lines) buf.shift(); });\n rl.on('close', () => resolve(buf));\n rl.on('error', reject);\n });\n },\n watchLogs: (svcName, onLine) => logBus.subscribe(({ svc, text }) => {\n if (svcName === null || svc === svcName) onLine(svc, text);\n }),\n watchStatus: (onUpdate) => stateBus.subscribe(({ name, state }) => onUpdate(name, state)),\n async getStats() {\n const pids: number[] = [];\n const pidToName = new Map<number, string>();\n for (const [name, st] of mgr.state) {\n if (st.pid) { pids.push(st.pid); pidToName.set(st.pid, name); }\n }\n const raw = pids.length ? await platform.getProcessStats(pids) : new Map();\n const services: Record<string, { cpu: number; memMB: number }> = {};\n for (const [name] of mgr.state) {\n services[name] = { cpu: 0, memMB: 0 };\n }\n for (const [pid, data] of raw) {\n const name = pidToName.get(pid);\n if (!name) continue;\n const prev = prevCpuMap.get(name) ?? { time: Date.now(), cpu: 0 };\n const cpu = calcCpuPercent(data.cpuSeconds, prev.cpu, prev.time);\n prevCpuMap.set(name, { time: Date.now(), cpu: data.cpuSeconds });\n services[name] = { cpu: Math.round(cpu * 10) / 10, memMB: Math.round((data.rss / 1024) * 10) / 10 };\n }\n return {\n services,\n system: {\n totalMemMB: Math.round(totalmem() / 1024 / 1024),\n freeMemMB: Math.round(freemem() / 1024 / 1024),\n cpuCores: cpus().length,\n },\n };\n },\n getProxyInfo() {\n if (!proxyProvider || !proxyOpts || !cliArgs.proxy) return null;\n return {\n active: true,\n provider: proxyProvider.name,\n domain: proxyOpts.domain,\n tls: proxyOpts.tls,\n routes: proxyOpts.routes,\n };\n },\n }, { onLog: msg => writeDevupLog(msg) });\n\n // ── Health poller (keeps state.health fresh for control-plane consumers) ──\n healthTimer = setInterval(() => { void mgr.checkAllHealth(); }, 3000);\n\n // ── Proxy sync (write traefik/nginx/caddy config when state changes) ──\n if (proxyProvider && proxyOpts && cliArgs.proxy) {\n let lastContent: string | null = null;\n const sync = () => {\n const svcStates = new Map<string, ServiceState>();\n for (const [n, st] of mgr.state) {\n svcStates.set(n, { port: st.svc.port, health: st.health, realPort: (st.svc as { realPort?: number }).realPort });\n }\n const content = proxyProvider.generate(svcStates, proxyOpts);\n if (content === lastContent) return;\n lastContent = content;\n try { proxyProvider.write(content, proxyOpts); } catch { /* ignore — best-effort */ }\n };\n sync();\n proxyTimer = setInterval(sync, 3000);\n }\n\n // ── Hot-reload watcher (opt-in via --watch-config) ──\n if (cliArgs.watchConfig) {\n try {\n const configPath = findConfigFile(baseCwd, cliArgs.configPath);\n writeDevupLog(`👀 watching ${configPath}`);\n stopConfigWatcher = watchConfig({\n configPath, baseCwd, manager: mgr,\n log: msg => writeDevupLog(msg),\n });\n } catch (e: any) {\n writeDevupLog(`⚠ watch-config disabled: ${e.message ?? String(e)}`);\n }\n }\n\n // ── Write PID file (signals \"ready\" to the parent process) ──\n writeFileSync(pidPath, String(process.pid));\n writeDevupLog(`✓ daemon ready (pid=${process.pid})`);\n\n // Stay alive. The open socket server + child procs keep the event loop running.\n // SIGTERM/SIGINT handler does the actual exit.\n } catch (e: any) {\n try { writeFileSync(errPath, e.message ?? String(e)); } catch { /* ignore */ }\n try { writeDevupLog(`❌ boot failed: ${e.message ?? String(e)}`); } catch { /* ignore */ }\n await cleanup().catch(() => {});\n process.exit(1);\n }\n}\n\nasync function bootNormal(mgr: ProcessManager, services: ServiceConfig[]): Promise<void> {\n const phases = groupByPhase(services);\n let colorIdx = 0;\n for (const num of Object.keys(phases).map(Number).sort((a, b) => a - b)) {\n for (const svc of phases[num]!) {\n const ci = colorIdx++;\n await mgr.install(svc, ci);\n await mgr.start(svc, ci);\n }\n const apis = phases[num]!.filter(s => s.type === 'api');\n if (apis.length) await Promise.all(apis.map(s => waitForPort(s.port, { timeout: 45000 })));\n phases[num]!.filter(s => s.type === 'web').forEach(s => {\n const st = mgr.state.get(s.name);\n if (st) st.status = 'running';\n });\n }\n}\n\nasync function bootLazy(\n mgr: ProcessManager,\n services: ServiceConfig[],\n lazyCfg: NonNullable<DevStackConfig['lazy']>,\n lazyTimeout: number,\n lazyProxies: Map<string, LazyProxy>,\n): Promise<void> {\n const { alwaysOn, lazy } = classifyServices(services, lazyCfg);\n const phases = groupByPhase(alwaysOn);\n let colorIdx = 0;\n for (const num of Object.keys(phases).map(Number).sort((a, b) => a - b)) {\n for (const svc of phases[num]!) {\n const ci = colorIdx++;\n await mgr.install(svc, ci);\n await mgr.start(svc, ci);\n }\n const apis = phases[num]!.filter(s => s.type === 'api');\n if (apis.length) await Promise.all(apis.map(s => waitForPort(s.port, { timeout: 45000 })));\n phases[num]!.filter(s => s.type === 'web').forEach(s => {\n const st = mgr.state.get(s.name);\n if (st) st.status = 'running';\n });\n }\n for (const svc of lazy) {\n const ci = colorIdx++;\n const rewritten = rewriteServicePort(svc);\n mgr.state.set(svc.name, {\n svc: rewritten, proc: null, pid: null,\n status: 'idle', health: 'idle',\n errors: 0, restarts: 0, startedAt: null,\n intentionalStop: false, colorIdx: ci,\n });\n const proxy = createLazyProxy({\n listenPort: svc.port, targetPort: rewritten.realPort, timeoutMin: lazyTimeout,\n onDemandStart: async () => {\n await mgr.install(rewritten, ci);\n await mgr.start(rewritten, ci);\n const ok = await waitForPort(rewritten.realPort, { timeout: 45000 });\n const st = mgr.state.get(svc.name);\n if (st) { st.status = ok ? 'running' : 'timeout'; if (ok) st.health = 'up'; }\n },\n onIdleStop: () => {\n mgr.stop(svc.name);\n const st = mgr.state.get(svc.name);\n if (st) { st.status = 'idle'; st.health = 'idle'; st.pid = null; st.proc = null; st.startedAt = null; }\n },\n isAlive: () => {\n const st = mgr.state.get(svc.name);\n return !!st && !!st.proc && !st.proc.killed && st.health === 'up';\n },\n });\n lazyProxies.set(svc.name, proxy);\n }\n}\n\n// ── Parent process: spawn detached child and wait for ready signal ──────────\n\nexport interface DetachedOpts extends DaemonOpts {\n out?: (line: string) => void;\n}\n\n/** Runs in the parent process. Validates state, spawns the daemon child\n * detached, polls for the PID file (ready) or boot-error file (failure),\n * prints the welcome line, and returns the exit code. */\nexport async function runDetached(opts: DetachedOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => process.stdout.write(l + '\\n'));\n const projectName = opts.config.name;\n\n if (process.platform === 'win32') {\n out('❌ daemon mode (devup up -d) is not yet supported on Windows. Run `devup` to use the TUI instead.');\n return 1;\n }\n\n const existing = isDaemonRunning(projectName);\n if (existing.pid && !existing.stale) {\n out(`❌ daemon already running for \"${projectName}\" (pid=${existing.pid}). Run \\`devup down\\` to stop it.`);\n return 1;\n }\n if (existing.stale) {\n out(`ℹ removing stale pid file for \"${projectName}\"`);\n try { unlinkSync(pidPathFor(projectName)); } catch { /* ignore */ }\n }\n\n mkdirSync(devupDir(), { recursive: true });\n const errPath = bootErrorPathFor(projectName);\n const pidPath = pidPathFor(projectName);\n if (existsSync(errPath)) { try { unlinkSync(errPath); } catch { /* ignore */ } }\n\n // Strip the subcommand and detach flags from argv; the child reuses everything else.\n const filteredArgs = process.argv.slice(2).filter((arg, i) => {\n if (i === 0 && arg === 'up') return false;\n if (arg === '-d' || arg === '--detach') return false;\n return true;\n });\n\n out(`⏳ starting devup in detached mode for \"${projectName}\"...`);\n\n // Preserve any node-level args (e.g. --loader tsx in dev) so the child can be re-executed.\n const child = spawn(process.execPath, [...process.execArgv, process.argv[1]!, ...filteredArgs], {\n detached: true,\n stdio: 'ignore',\n env: { ...process.env, DEVUP_DAEMON_CHILD: '1' },\n cwd: opts.baseCwd,\n });\n child.unref();\n\n // Poll for the PID file (success) or boot-error file (failure). Max wait: 90s.\n const deadline = Date.now() + 90_000;\n while (Date.now() < deadline) {\n if (existsSync(pidPath)) {\n const pid = Number(readFileSync(pidPath, 'utf8').trim());\n out('');\n out(`🚀 devup detached (PID ${pid})`);\n out(' inspect: devup ctl status');\n out(' logs: devup ctl logs <svc> --follow');\n out(' stop: devup down');\n return 0;\n }\n if (existsSync(errPath)) {\n const msg = readFileSync(errPath, 'utf8').trim();\n out(`❌ daemon boot failed: ${msg}`);\n try { unlinkSync(errPath); } catch { /* ignore */ }\n return 1;\n }\n await sleep(200);\n }\n\n out(`❌ daemon did not become ready within 90s. Killing child (pid=${child.pid}).`);\n if (child.pid) { try { process.kill(child.pid, 'SIGTERM'); } catch { /* ignore */ } }\n return 1;\n}\n\n// ── devup down ─────────────────────────────────────────────────────────────\n\nexport async function stopDaemon(\n projectName: string,\n opts: { out?: (line: string) => void; gracePeriodMs?: number } = {},\n): Promise<number> {\n const out = opts.out ?? ((l: string) => process.stdout.write(l + '\\n'));\n const grace = opts.gracePeriodMs ?? 10_000;\n const status = isDaemonRunning(projectName);\n\n if (!status.pid) {\n out(`ℹ no daemon running for \"${projectName}\".`);\n return 1;\n }\n if (status.stale) {\n out(`ℹ stale pid file for \"${projectName}\" (pid=${status.pid} not alive). Removing.`);\n try { unlinkSync(pidPathFor(projectName)); } catch { /* ignore */ }\n return 1;\n }\n\n out(`⏳ stopping daemon (pid=${status.pid})...`);\n try {\n process.kill(status.pid, 'SIGTERM');\n } catch (e: any) {\n out(`❌ cannot signal pid=${status.pid}: ${e.message}`);\n return 1;\n }\n\n const deadline = Date.now() + grace;\n while (Date.now() < deadline) {\n if (!pidAlive(status.pid)) {\n out(`✓ stopped daemon (pid=${status.pid})`);\n const p = pidPathFor(projectName);\n if (existsSync(p)) { try { unlinkSync(p); } catch { /* ignore */ } }\n return 0;\n }\n await sleep(200);\n }\n\n out(`⚠ daemon did not exit within ${(grace / 1000).toFixed(0)}s; sending SIGKILL.`);\n try { process.kill(status.pid, 'SIGKILL'); } catch { /* ignore */ }\n const p = pidPathFor(projectName);\n if (existsSync(p)) { try { unlinkSync(p); } catch { /* ignore */ } }\n return 0;\n}\n","import { join } from 'node:path';\nimport type { ChildProcess } from 'node:child_process';\nimport type { Platform } from '../platform/types.js';\nimport type { ServiceConfig } from '../config/types.js';\nimport type { ProcessState, ProcessManagerEvents } from './types.js';\nimport { installService } from './installer.js';\nimport { Spawner } from './spawner.js';\nimport { Restarter } from './restarter.js';\nimport { HealthPoller } from './health-poller.js';\nimport { Lifecycle } from './lifecycle.js';\n\n// Re-export the helpers + constants so existing imports keep working.\nexport { compileReadyPattern, extractWatchPaths } from './internals.js';\n\n/** Thin facade composing Spawner, Restarter, HealthPoller, and Lifecycle.\n * All four components share the same `state` Map and `procs` Set, so\n * mutations from one are visible to the others.\n *\n * Public API is unchanged from the pre-refactor monolithic class —\n * every TUI / orchestrator / control-plane call site keeps working. */\nexport class ProcessManager {\n readonly state = new Map<string, ProcessState>();\n private readonly procs = new Set<ChildProcess>();\n private readonly baseCwd: string;\n private readonly env: Record<string, string>;\n private readonly events: ProcessManagerEvents;\n private readonly spawner: Spawner;\n private readonly restarter: Restarter;\n private readonly healthPoller: HealthPoller;\n private readonly lifecycle: Lifecycle;\n\n constructor(opts: {\n baseCwd: string;\n env: Record<string, string>;\n platform: Platform;\n events: ProcessManagerEvents;\n }) {\n this.baseCwd = opts.baseCwd;\n this.env = opts.env;\n this.events = opts.events;\n\n this.lifecycle = new Lifecycle({\n state: this.state, procs: this.procs, platform: opts.platform,\n });\n\n // Forward declaration: the spawner needs onCrash, which the restarter implements.\n // We assign after both exist via the closure below.\n let restarterRef: Restarter | null = null;\n this.spawner = new Spawner({\n baseCwd: opts.baseCwd, env: opts.env,\n state: this.state, procs: this.procs,\n events: opts.events, lifecycle: this.lifecycle,\n onCrash: (svc, state, colorIdx) => restarterRef?.scheduleAutoRestart(svc, state, colorIdx),\n });\n this.restarter = new Restarter({\n state: this.state, events: opts.events,\n spawner: this.spawner, lifecycle: this.lifecycle,\n });\n restarterRef = this.restarter;\n\n this.healthPoller = new HealthPoller({\n state: this.state, events: opts.events,\n });\n }\n\n install(svc: ServiceConfig, colorIdx?: number): Promise<boolean> {\n const cwd = join(this.baseCwd, svc.cwd);\n const idx = colorIdx ?? this.state.get(svc.name)?.colorIdx ?? 0;\n return installService(cwd, this.env, msg => this.events.onLog(svc.name, msg, idx));\n }\n\n start(svc: ServiceConfig, colorIdx: number, isRestart = false): Promise<void> {\n return this.spawner.start(svc, colorIdx, isRestart);\n }\n\n stop(name: string): void {\n this.lifecycle.stop(name);\n }\n\n restart(name: string): Promise<void> {\n return this.restarter.restart(name);\n }\n\n checkAllHealth(): Promise<void> {\n return this.healthPoller.checkAll();\n }\n\n cleanup(opts: { gracePeriodMs?: number } = {}): Promise<void> {\n return this.lifecycle.cleanup(opts);\n }\n}\n","import { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { needsInstall, writeInstallStamp } from '../utils.js';\n\nexport function installService(\n cwd: string, env: Record<string, string>,\n onLog?: (msg: string) => void,\n): Promise<boolean> {\n if (!existsSync(cwd)) {\n onLog?.(`⚠ directory not found: ${cwd}`);\n return Promise.resolve(false);\n }\n if (!needsInstall(cwd)) {\n onLog?.('✅ dependencies up to date');\n return Promise.resolve(true);\n }\n onLog?.('📦 npm install...');\n return new Promise(resolve => {\n // En Windows, npm es usualmente npm.cmd\n const command = process.platform === 'win32' ? 'npm.cmd' : 'npm';\n const proc = spawn(command, ['install'], { cwd, env, stdio: ['ignore', 'ignore', 'pipe'] });\n let stderr = '';\n proc.stderr?.on('data', (d: Buffer) => { stderr += d.toString(); });\n proc.on('close', code => {\n if (code !== 0) {\n onLog?.(`⚠ npm install failed: ${stderr.split('\\n')[0]}`);\n resolve(false);\n } else {\n writeInstallStamp(cwd);\n onLog?.('✅ dependencies ready');\n resolve(true);\n }\n });\n proc.on('error', (err) => {\n onLog?.(`⚠ spawn error: ${err.message}`);\n resolve(false);\n });\n });\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport type { ServiceConfig } from '../config/types.js';\nimport type { ProcessState, ProcessManagerEvents } from './types.js';\nimport { isPortBindable } from './health.js';\nimport { buildProcessArgs, buildProcessEnv } from '../utils.js';\nimport { lineBuffer, compileReadyPattern, extractWatchPaths } from './internals.js';\nimport type { Lifecycle } from './lifecycle.js';\n\ninterface SpawnerOpts {\n baseCwd: string;\n env: Record<string, string>;\n state: Map<string, ProcessState>;\n procs: Set<ChildProcess>;\n events: ProcessManagerEvents;\n lifecycle: Lifecycle;\n /** Called when a service exits non-zero, so the Restarter can schedule auto-restart. */\n onCrash: (svc: ServiceConfig, state: ProcessState, colorIdx: number) => void;\n}\n\n/** Owns the spawn lifecycle: port check → preBuild → watch-path pre-flight →\n * spawn → wire stdio (readyPattern + errorPattern + log) → watchBuild → close\n * handler. On crash, delegates to `onCrash` (the Restarter wires this). */\nexport class Spawner {\n private readonly baseCwd: string;\n private readonly env: Record<string, string>;\n private readonly state: Map<string, ProcessState>;\n private readonly procs: Set<ChildProcess>;\n private readonly events: ProcessManagerEvents;\n private readonly lifecycle: Lifecycle;\n private readonly onCrash: SpawnerOpts['onCrash'];\n\n constructor(opts: SpawnerOpts) {\n this.baseCwd = opts.baseCwd;\n this.env = opts.env;\n this.state = opts.state;\n this.procs = opts.procs;\n this.events = opts.events;\n this.lifecycle = opts.lifecycle;\n this.onCrash = opts.onCrash;\n }\n\n async start(svc: ServiceConfig, colorIdx: number, isRestart = false): Promise<void> {\n const cwd = join(this.baseCwd, svc.cwd);\n\n // Port occupied check (APIs only — webs are assumed to manage their own).\n // Use bind-based test so we catch every state that would EADDRINUSE the\n // spawned service, not just sockets that already accept connections.\n if (svc.type === 'api') {\n const bindable = await isPortBindable(svc.port);\n if (!bindable && !isRestart) {\n this.log(svc.name, `⚠ port ${svc.port} already in use — skipping`, colorIdx);\n this.recordCrashedState(svc, colorIdx);\n return;\n }\n }\n\n // preBuild: run synchronously before spawning the service.\n if (svc.preBuild) {\n const built = await this.runPreBuild(svc, cwd, colorIdx);\n if (!built) {\n this.recordCrashedState(svc, colorIdx);\n return;\n }\n }\n\n const args = buildProcessArgs(svc);\n\n // Pre-flight: every --watch / --watch-path must resolve to an existing path.\n const missingWatchPaths = extractWatchPaths(args)\n .filter(p => !existsSync(resolve(cwd, p)));\n if (missingWatchPaths.length) {\n this.log(svc.name, `⚠ missing watch paths: ${missingWatchPaths.join(', ')}`, colorIdx);\n this.recordCrashedState(svc, colorIdx);\n return;\n }\n\n const env = buildProcessEnv(svc, this.env);\n const proc = spawn(svc.cmd, args, { cwd, env, detached: true, stdio: ['ignore', 'pipe', 'pipe'] });\n\n const prev = this.state.get(svc.name);\n const state: ProcessState = {\n svc, proc, pid: proc.pid ?? null,\n status: 'starting', health: 'wait',\n errors: prev?.errors ?? 0,\n restarts: prev?.restarts ?? 0,\n startedAt: Date.now(),\n intentionalStop: false,\n colorIdx,\n };\n this.state.set(svc.name, state);\n this.procs.add(proc);\n this.events.onStateChange(svc.name, state);\n\n this.wireStdio(proc, svc, state, colorIdx);\n this.wireCloseHandler(proc, svc, state, colorIdx);\n\n // watchBuild: side-car process running alongside the service.\n if (svc.watchBuild) {\n state.watchProc = this.spawnWatchBuild(svc, cwd, env, colorIdx);\n }\n\n this.log(svc.name, isRestart ? `🔄 restarted (:${svc.port})` : `🚀 started (:${svc.port})`, colorIdx);\n }\n\n private wireStdio(proc: ChildProcess, svc: ServiceConfig, state: ProcessState, colorIdx: number): void {\n const readyRegex = compileReadyPattern(svc.readyPattern);\n const markReadyIfMatch = (line: string) => {\n if (!readyRegex || state.health === 'up') return;\n if (readyRegex.test(line)) {\n state.health = 'up';\n if (state.status === 'starting') state.status = 'running';\n this.events.onStateChange(svc.name, state);\n }\n };\n const errorRegex = compileReadyPattern(svc.errorPattern);\n const countsAsError = (line: string) => errorRegex ? errorRegex.test(line) : true;\n\n const stdoutBuf = lineBuffer(line => { markReadyIfMatch(line); this.log(svc.name, line, colorIdx); });\n const stderrBuf = lineBuffer(line => {\n if (countsAsError(line)) state.errors += 1;\n markReadyIfMatch(line);\n this.log(svc.name, line, colorIdx);\n });\n\n proc.stdout?.on('data', (d: Buffer) => stdoutBuf.push(d));\n proc.stderr?.on('data', (d: Buffer) => stderrBuf.push(d));\n proc.stdout?.on('end', () => stdoutBuf.flush());\n proc.stderr?.on('end', () => stderrBuf.flush());\n }\n\n private wireCloseHandler(proc: ChildProcess, svc: ServiceConfig, state: ProcessState, colorIdx: number): void {\n proc.on('close', code => {\n this.procs.delete(proc);\n this.lifecycle.stopWatchProc(state);\n if (state.intentionalStop) { state.intentionalStop = false; return; }\n if (code === 0) {\n state.status = 'stopped'; state.health = 'down';\n this.events.onStateChange(svc.name, state);\n return;\n }\n state.status = 'crashed'; state.health = 'down';\n this.log(svc.name, `❌ exited with code ${code}`, colorIdx);\n this.events.onStateChange(svc.name, state);\n this.onCrash(svc, state, colorIdx);\n });\n }\n\n private runPreBuild(svc: ServiceConfig, cwd: string, colorIdx: number): Promise<boolean> {\n this.log(svc.name, `🔨 preBuild: ${svc.preBuild}`, colorIdx);\n return new Promise(res => {\n const isWin = process.platform === 'win32';\n const shell = isWin ? 'cmd.exe' : 'sh';\n const shellFlag = isWin ? '/c' : '-c';\n const env = buildProcessEnv(svc, this.env);\n const child = spawn(shell, [shellFlag, svc.preBuild!], { cwd, env, stdio: ['ignore', 'pipe', 'pipe'] });\n\n const outBuf = lineBuffer(line => this.log(svc.name, `[build] ${line}`, colorIdx));\n const errBuf = lineBuffer(line => this.log(svc.name, `[build] ${line}`, colorIdx));\n child.stdout?.on('data', (d: Buffer) => outBuf.push(d));\n child.stderr?.on('data', (d: Buffer) => errBuf.push(d));\n\n child.on('error', err => {\n this.log(svc.name, `[build] ❌ ${err.message}`, colorIdx);\n res(false);\n });\n child.on('close', code => {\n outBuf.flush(); errBuf.flush();\n if (code === 0) {\n this.log(svc.name, `[build] ✅ done`, colorIdx);\n res(true);\n } else {\n this.log(svc.name, `[build] ❌ exited with code ${code}`, colorIdx);\n res(false);\n }\n });\n });\n }\n\n private spawnWatchBuild(svc: ServiceConfig, cwd: string, env: Record<string, string>, colorIdx: number): ChildProcess {\n this.log(svc.name, `👀 watchBuild: ${svc.watchBuild}`, colorIdx);\n const isWin = process.platform === 'win32';\n const shell = isWin ? 'cmd.exe' : 'sh';\n const shellFlag = isWin ? '/c' : '-c';\n const child = spawn(shell, [shellFlag, svc.watchBuild!], {\n cwd, env, detached: true, stdio: ['ignore', 'pipe', 'pipe'],\n });\n const outBuf = lineBuffer(line => this.log(svc.name, `[watch] ${line}`, colorIdx));\n const errBuf = lineBuffer(line => this.log(svc.name, `[watch] ${line}`, colorIdx));\n child.stdout?.on('data', (d: Buffer) => outBuf.push(d));\n child.stderr?.on('data', (d: Buffer) => errBuf.push(d));\n child.on('error', err => this.log(svc.name, `[watch] ❌ ${err.message}`, colorIdx));\n return child;\n }\n\n /** Create a state entry in 'crashed' status without spawning a process\n * (used when preBuild fails or pre-flight checks fail). */\n private recordCrashedState(svc: ServiceConfig, colorIdx: number): void {\n const prev = this.state.get(svc.name);\n this.state.set(svc.name, {\n svc, proc: null, pid: null,\n status: 'crashed', health: 'down',\n errors: prev?.errors ?? 0,\n restarts: prev?.restarts ?? 0,\n startedAt: null,\n intentionalStop: false,\n colorIdx,\n });\n this.events.onStateChange(svc.name, this.state.get(svc.name)!);\n }\n\n private log(name: string, text: string, colorIdx: number): void {\n this.events.onLog(name, text, colorIdx);\n }\n}\n","/** Buffered line splitter. Calls `onLine` for every newline-terminated chunk,\n * preserves leftover for the next push. `flush()` emits any remaining tail. */\nexport function lineBuffer(onLine: (line: string) => void) {\n let buf = '';\n return {\n push(chunk: Buffer) {\n buf += chunk.toString();\n let idx;\n while ((idx = buf.indexOf('\\n')) !== -1) {\n const line = buf.slice(0, idx).replace(/\\r$/, '');\n buf = buf.slice(idx + 1);\n if (line.length) onLine(line);\n }\n },\n flush() {\n if (buf.length) { onLine(buf); buf = ''; }\n },\n };\n}\n\n/** Accepts both '/foo/' (vim-style) and bare 'foo'. Case-insensitive by default. */\nexport function compileReadyPattern(pattern: string | undefined): RegExp | null {\n if (!pattern) return null;\n const slashed = /^\\/(.+)\\/([gimsuy]*)$/.exec(pattern);\n try {\n if (slashed) return new RegExp(slashed[1]!, slashed[2] || 'i');\n return new RegExp(pattern, 'i');\n } catch {\n return null;\n }\n}\n\n/** Extracts the value tokens of `--watch` / `--watch-path` / `--watch=X` / `--watch-path=X`\n * from a command's args list. Accepts both `--flag value` and `--flag=value` forms. */\nexport function extractWatchPaths(args: string[]): string[] {\n const watchFlags = new Set(['--watch', '--watch-path']);\n const out: string[] = [];\n for (let i = 0; i < args.length; i++) {\n const a = args[i]!;\n if (watchFlags.has(a)) {\n const v = args[i + 1];\n if (v && !v.startsWith('-')) { out.push(v); i++; }\n continue;\n }\n const eq = a.indexOf('=');\n if (eq > 0 && watchFlags.has(a.slice(0, eq))) {\n out.push(a.slice(eq + 1));\n }\n }\n return out;\n}\n\nexport const MAX_RESTARTS = 3;\nexport const BACKOFF_BASE_MS = 2000;\n","import type { ServiceConfig } from '../config/types.js';\nimport type { ProcessState, ProcessManagerEvents } from './types.js';\nimport type { Spawner } from './spawner.js';\nimport type { Lifecycle } from './lifecycle.js';\nimport { MAX_RESTARTS, BACKOFF_BASE_MS } from './internals.js';\n\ninterface RestarterOpts {\n state: Map<string, ProcessState>;\n events: ProcessManagerEvents;\n spawner: Spawner;\n lifecycle: Lifecycle;\n}\n\n/** Two responsibilities:\n * 1. Manual restart (`restart(name)`) — full stop + respawn, **resets** the\n * auto-restart counter so the user gets a fresh budget.\n * 2. Auto-restart on crash (`scheduleAutoRestart`) — exponential backoff,\n * capped at MAX_RESTARTS. Spawner invokes this in its close handler. */\nexport class Restarter {\n private readonly state: Map<string, ProcessState>;\n private readonly events: ProcessManagerEvents;\n private readonly spawner: Spawner;\n private readonly lifecycle: Lifecycle;\n\n constructor(opts: RestarterOpts) {\n this.state = opts.state;\n this.events = opts.events;\n this.spawner = opts.spawner;\n this.lifecycle = opts.lifecycle;\n }\n\n async restart(name: string): Promise<void> {\n const st = this.state.get(name);\n if (!st) return;\n this.lifecycle.stop(name);\n // Manual restart: reset auto-restart counter so user gets a fresh budget\n st.restarts = 0;\n const delay = st.proc ? 1500 : 100;\n await new Promise(r => setTimeout(r, delay));\n await this.spawner.start(st.svc, st.colorIdx, true);\n this.events.onLog(name, '🔄 manual restart', st.colorIdx);\n }\n\n scheduleAutoRestart(svc: ServiceConfig, state: ProcessState, colorIdx: number): void {\n if (state.restarts >= MAX_RESTARTS) {\n this.events.onLog(svc.name, '⛔ max restarts reached', colorIdx);\n return;\n }\n state.restarts++;\n const delay = BACKOFF_BASE_MS * Math.pow(2, state.restarts - 1);\n this.events.onLog(svc.name, `🔄 auto-restart ${state.restarts}/${MAX_RESTARTS} in ${delay}ms...`, colorIdx);\n setTimeout(() => void this.spawner.start(svc, colorIdx, true), delay);\n }\n}\n","import type { ProcessState, ProcessManagerEvents } from './types.js';\nimport { checkHealth, deriveHealth } from './health.js';\n\ninterface HealthPollerOpts {\n state: Map<string, ProcessState>;\n events: ProcessManagerEvents;\n}\n\n/** Runs one round of health probes across every service in `state`.\n * Suppresses probes during `healthCheck.startPeriod` grace window. */\nexport class HealthPoller {\n private readonly state: Map<string, ProcessState>;\n private readonly events: ProcessManagerEvents;\n\n constructor(opts: HealthPollerOpts) {\n this.state = opts.state;\n this.events = opts.events;\n }\n\n async checkAll(): Promise<void> {\n for (const [name, st] of this.state) {\n if (!st.pid || st.status === 'idle') {\n st.health = st.status === 'idle' ? 'idle' : 'down';\n continue;\n }\n // Grace period: suppress probes during the first N seconds after startedAt.\n // Keeps state.errors clean during slow boots (Angular cold-start, etc.).\n const startPeriodMs = (st.svc.healthCheck?.startPeriod ?? 0) * 1000;\n if (startPeriodMs > 0 && st.startedAt && Date.now() - st.startedAt < startPeriodMs) {\n continue; // status stays 'starting', health stays 'wait'\n }\n const isUp = await checkHealth(st.svc.port, st.svc.healthCheck);\n const prev = st.health;\n st.health = deriveHealth(isUp, st.status);\n if (st.health === 'up' && st.status === 'starting') st.status = 'running';\n if (prev !== st.health) this.events.onStateChange(name, st);\n }\n }\n}\n","import type { ChildProcess } from 'node:child_process';\nimport type { Platform } from '../platform/types.js';\nimport type { ProcessState } from './types.js';\n\ninterface LifecycleOpts {\n state: Map<string, ProcessState>;\n procs: Set<ChildProcess>;\n platform: Platform;\n}\n\n/** Owns the kill-tree, watchBuild teardown, and graceful cleanup with SIGKILL\n * fallback. Stateless beyond what's passed in via opts. */\nexport class Lifecycle {\n private readonly state: Map<string, ProcessState>;\n private readonly procs: Set<ChildProcess>;\n private readonly platform: Platform;\n\n constructor(opts: LifecycleOpts) {\n this.state = opts.state;\n this.procs = opts.procs;\n this.platform = opts.platform;\n }\n\n /** Manual / external stop of a single service. Marks `intentionalStop` so the\n * close handler doesn't auto-restart, kills the process tree, tears down the\n * side-car watchBuild process if any. */\n stop(name: string): void {\n const st = this.state.get(name);\n if (!st?.proc || !st.pid) return;\n st.intentionalStop = true;\n this.platform.killTree(st.pid);\n this.stopWatchProc(st);\n }\n\n /** Tears down the side-car `watchBuild` process for a service (if any) and\n * clears the reference. Safe to call repeatedly. */\n stopWatchProc(state: ProcessState): void {\n const wp = state.watchProc;\n if (!wp || !wp.pid) return;\n try { this.platform.killTree(wp.pid); } catch { /* already dead */ }\n state.watchProc = null;\n }\n\n /** Graceful shutdown of every spawned process. Waits `gracePeriodMs` (default\n * 3000) for clean exits, then SIGKILLs anything still alive. */\n async cleanup(opts: { gracePeriodMs?: number } = {}): Promise<void> {\n const grace = opts.gracePeriodMs ?? 3000;\n const procs = [...this.procs];\n if (!procs.length) return;\n\n for (const proc of procs) {\n const st = this.findStateByProc(proc);\n if (st) {\n st.intentionalStop = true;\n this.stopWatchProc(st);\n }\n if (proc.pid) this.platform.killTree(proc.pid);\n }\n // Any side-car watch processes whose service hasn't been seen above\n // (e.g. preBuild-failed services).\n for (const st of this.state.values()) this.stopWatchProc(st);\n\n const waits = procs.map(p =>\n p.exitCode !== null || p.signalCode !== null\n ? Promise.resolve()\n : new Promise<void>(resolve => p.once('close', () => resolve())),\n );\n\n let timedOut = false;\n await Promise.race([\n Promise.all(waits),\n new Promise<void>(resolve => setTimeout(() => { timedOut = true; resolve(); }, grace)),\n ]);\n\n if (timedOut) {\n for (const proc of procs) {\n if (proc.pid && proc.exitCode === null && proc.signalCode === null) {\n this.platform.killTree(proc.pid, 'SIGKILL');\n }\n }\n await Promise.race([\n Promise.all(waits),\n new Promise<void>(resolve => setTimeout(resolve, 1000)),\n ]);\n }\n }\n\n private findStateByProc(proc: ChildProcess): ProcessState | undefined {\n for (const st of this.state.values()) if (st.proc === proc) return st;\n return undefined;\n }\n}\n","import { existsSync, mkdirSync, renameSync, createWriteStream, type WriteStream } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { homedir } from 'node:os';\n\nexport interface LogSinkOpts {\n /** Project name used as a subdirectory under the log root. */\n projectName: string;\n /** Root directory (default: ~/.devup/logs). */\n rootDir?: string;\n /** Rotate the previous run's file to <svc>.log.prev on first write. Default: true. */\n rotateOnStart?: boolean;\n}\n\n/** Persist service logs to disk, one file per service, append-only.\n * On the first write for a service, rotates any previous <svc>.log to <svc>.log.prev. */\nexport class LogSink {\n private readonly dir: string;\n private readonly rotateOnStart: boolean;\n private readonly streams = new Map<string, WriteStream>();\n private readonly seen = new Set<string>();\n\n constructor(opts: LogSinkOpts) {\n const root = opts.rootDir ?? join(homedir(), '.devup', 'logs');\n this.dir = join(root, sanitize(opts.projectName));\n this.rotateOnStart = opts.rotateOnStart ?? true;\n mkdirSync(this.dir, { recursive: true });\n }\n\n /** Returns the file path for a service log (useful for tests / UI). */\n pathFor(svcName: string): string {\n return join(this.dir, `${sanitize(svcName)}.log`);\n }\n\n write(svcName: string, line: string): void {\n const stream = this.streamFor(svcName);\n stream.write(`${new Date().toISOString()} ${line}\\n`);\n }\n\n async close(): Promise<void> {\n const closes = [...this.streams.values()].map(\n s => new Promise<void>(r => s.end(() => r())),\n );\n this.streams.clear();\n this.seen.clear();\n await Promise.all(closes);\n }\n\n private streamFor(svcName: string): WriteStream {\n let s = this.streams.get(svcName);\n if (s) return s;\n const file = this.pathFor(svcName);\n if (this.rotateOnStart && !this.seen.has(svcName) && existsSync(file)) {\n try {\n mkdirSync(dirname(file), { recursive: true });\n renameSync(file, file + '.prev');\n } catch { /* best effort */ }\n }\n this.seen.add(svcName);\n s = createWriteStream(file, { flags: 'a' });\n s.on('error', () => { /* swallow — disk full / permission, etc. */ });\n this.streams.set(svcName, s);\n return s;\n }\n}\n\nfunction sanitize(name: string): string {\n return name.replace(/[^a-zA-Z0-9._-]+/g, '_').replace(/^_+|_+$/g, '') || 'devup';\n}\n","export class Broadcaster<T> {\n private readonly subs = new Set<(v: T) => void>();\n\n subscribe(fn: (v: T) => void): () => void {\n this.subs.add(fn);\n return () => this.subs.delete(fn);\n }\n\n emit(v: T): void {\n for (const fn of this.subs) {\n try { fn(v); } catch { /* subscriber errors must not kill the bus */ }\n }\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { join } from 'node:path';\nimport type { ExternalService } from '../config/types.js';\nimport type { Platform } from '../platform/types.js';\nimport { checkHealth } from './health.js';\n\nconst DEFAULT_START_TIMEOUT_S = 60;\n\nexport interface ExternalProc {\n svc: ExternalService;\n proc: ChildProcess;\n pid: number | null;\n}\n\nexport interface StartExternalsOpts {\n baseCwd: string;\n env: Record<string, string>;\n platform: Platform;\n onLog?: (svcName: string, msg: string) => void;\n}\n\nexport interface StartExternalsResult {\n procs: ExternalProc[];\n allHealthy: boolean;\n failed: string[];\n}\n\n/** Spawn each external sequentially; for those with healthCheck, wait until it passes\n * (up to startTimeout seconds) before moving on. Returns the spawned handles and a\n * failure summary the caller can act on. */\nexport async function startExternals(\n externals: ExternalService[],\n opts: StartExternalsOpts,\n): Promise<StartExternalsResult> {\n const procs: ExternalProc[] = [];\n const failed: string[] = [];\n\n for (const svc of externals) {\n const proc = spawnExternal(svc, opts);\n procs.push({ svc, proc, pid: proc.pid ?? null });\n\n if (!svc.healthCheck) {\n opts.onLog?.(svc.name, '✅ started (no healthCheck)');\n continue;\n }\n\n if (svc.healthCheck.type === 'tcp' && !svc.port) {\n opts.onLog?.(svc.name, '⚠ tcp healthCheck requires `port` — skipping wait');\n continue;\n }\n\n const timeoutMs = (svc.startTimeout ?? DEFAULT_START_TIMEOUT_S) * 1000;\n const ok = await waitHealthy(svc, timeoutMs);\n if (ok) {\n opts.onLog?.(svc.name, '✅ healthy');\n } else {\n opts.onLog?.(svc.name, `❌ never became healthy (timeout ${timeoutMs / 1000}s)`);\n failed.push(svc.name);\n }\n }\n\n return { procs, allHealthy: failed.length === 0, failed };\n}\n\n/** Kill the externals and run any `stopCmd`s. Best-effort, fire-and-forget for the stopCmds. */\nexport async function stopExternals(\n procs: ExternalProc[],\n platform: Platform,\n opts: { baseCwd: string; env: Record<string, string>; onLog?: (svc: string, msg: string) => void } = {} as any,\n): Promise<void> {\n for (const { svc, proc, pid } of procs) {\n try {\n if (pid) platform.killTree(pid);\n if (svc.stopCmd) {\n opts.onLog?.(svc.name, `🧹 ${svc.stopCmd}`);\n await new Promise<void>(resolve => {\n const isWin = process.platform === 'win32';\n const shell = isWin ? 'cmd.exe' : 'sh';\n const flag = isWin ? '/c' : '-c';\n const cwd = svc.cwd ? join(opts.baseCwd, svc.cwd) : opts.baseCwd;\n const env = { ...opts.env, ...(svc.extraEnv ?? {}) };\n const child = spawn(shell, [flag, svc.stopCmd!], { cwd, env, stdio: 'ignore' });\n child.on('close', () => resolve());\n child.on('error', () => resolve());\n // 10s hard cap so a hung docker stop doesn't block forever\n setTimeout(() => resolve(), 10_000);\n });\n }\n } catch { /* best-effort */ }\n void proc; // keep TS happy\n }\n}\n\nfunction spawnExternal(svc: ExternalService, opts: StartExternalsOpts): ChildProcess {\n const isWin = process.platform === 'win32';\n const shell = isWin ? 'cmd.exe' : 'sh';\n const flag = isWin ? '/c' : '-c';\n const cwd = svc.cwd ? join(opts.baseCwd, svc.cwd) : opts.baseCwd;\n const env = { ...opts.env, ...(svc.extraEnv ?? {}) };\n\n opts.onLog?.(svc.name, `🚀 ${svc.cmd}`);\n const child = spawn(shell, [flag, svc.cmd], {\n cwd, env, detached: true, stdio: ['ignore', 'pipe', 'pipe'],\n });\n child.stdout?.on('data', (d: Buffer) => opts.onLog?.(svc.name, d.toString().trimEnd()));\n child.stderr?.on('data', (d: Buffer) => opts.onLog?.(svc.name, d.toString().trimEnd()));\n child.on('error', err => opts.onLog?.(svc.name, `❌ spawn error: ${err.message}`));\n return child;\n}\n\nasync function waitHealthy(svc: ExternalService, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n const port = svc.port!;\n while (Date.now() < deadline) {\n if (await checkHealth(port, svc.healthCheck)) return true;\n await new Promise(r => setTimeout(r, 500));\n }\n return false;\n}\n","import net from 'node:net';\nimport { waitForPort } from '../process/health.js';\n\nexport interface LazyProxyOpts {\n listenPort: number;\n targetPort: number;\n timeoutMin: number;\n onDemandStart: () => Promise<void>;\n onIdleStop: () => void;\n isAlive: () => boolean;\n onLog?: (msg: string) => void;\n}\n\nexport interface LazyProxy {\n server: net.Server;\n resetTimer: () => void;\n destroy: () => void;\n}\n\nexport function createLazyProxy(opts: LazyProxyOpts): LazyProxy {\n const { listenPort, targetPort, timeoutMin, onDemandStart, onIdleStop, isAlive, onLog } = opts;\n let idleTimer: ReturnType<typeof setTimeout> | null = null;\n let lastActivity = Date.now();\n let starting = false;\n let serviceReady = false;\n let pendingConns: net.Socket[] = [];\n const activeConns = new Set<net.Socket>();\n\n function bumpActivity() {\n lastActivity = Date.now();\n }\n\n function scheduleIdleCheck() {\n if (idleTimer) clearTimeout(idleTimer);\n if (timeoutMin <= 0) return;\n const periodMs = timeoutMin * 60_000;\n idleTimer = setTimeout(() => {\n const elapsed = Date.now() - lastActivity;\n if (activeConns.size > 0 || elapsed < periodMs) {\n // Aún activa o tráfico reciente — re-agenda\n scheduleIdleCheck();\n return;\n }\n serviceReady = false;\n onLog?.(`💤 idle ${timeoutMin}min — stopping`);\n onIdleStop();\n }, periodMs);\n }\n\n function pipeToTarget(client: net.Socket) {\n const target = net.createConnection({ port: targetPort, host: '127.0.0.1', allowHalfOpen: true });\n activeConns.add(client);\n\n const cleanup = () => {\n activeConns.delete(client);\n bumpActivity();\n };\n\n target.on('error', () => { client.destroy(); cleanup(); });\n client.on('error', () => { target.destroy(); cleanup(); });\n client.on('close', cleanup);\n target.on('close', cleanup);\n\n target.on('connect', () => {\n target.on('data', (chunk) => { bumpActivity(); if (!client.destroyed) client.write(chunk); });\n client.on('data', (chunk) => { bumpActivity(); if (!target.destroyed) target.write(chunk); });\n target.on('end', () => { if (!client.destroyed) client.end(); });\n client.on('end', () => { if (!target.destroyed) target.end(); });\n });\n }\n\n async function handleConnection(client: net.Socket) {\n bumpActivity();\n client.on('error', () => {}); // Prevent uncaught ECONNRESET\n\n if (serviceReady && isAlive()) {\n pipeToTarget(client);\n return;\n }\n\n pendingConns.push(client);\n client.on('close', () => { pendingConns = pendingConns.filter(s => s !== client); });\n\n if (starting) return;\n starting = true;\n\n onLog?.('⚡ on-demand start');\n let ok = false;\n try {\n await onDemandStart();\n ok = await waitForPort(targetPort, { timeout: 45000, interval: 500 });\n if (ok) serviceReady = true;\n else onLog?.('⚠ timeout waiting for service');\n } catch (e: unknown) {\n onLog?.(`❌ start failed: ${(e as Error).message}`);\n }\n starting = false;\n\n const conns = pendingConns.splice(0);\n if (!ok) {\n for (const conn of conns) {\n if (!conn.destroyed) conn.destroy();\n }\n return;\n }\n for (const conn of conns) {\n if (!conn.destroyed) pipeToTarget(conn);\n }\n }\n\n const server = net.createServer({ allowHalfOpen: true }, socket => handleConnection(socket));\n server.listen(listenPort, '0.0.0.0');\n scheduleIdleCheck();\n\n return {\n server,\n resetTimer: bumpActivity,\n destroy: () => {\n if (idleTimer) clearTimeout(idleTimer);\n pendingConns.forEach(s => s.destroy());\n activeConns.forEach(s => s.destroy());\n server.close();\n },\n };\n}\n","import { watchFile, unwatchFile, type Stats } from 'node:fs';\nimport { loadConfig } from '../config/loader.js';\nimport { validateConfig, formatValidationErrors } from '../config/validator.js';\nimport { diffServices, summariseDiff } from '../config/diff.js';\nimport type { ProcessManager } from '../process/manager.js';\n\nexport interface ConfigWatchOpts {\n configPath: string;\n baseCwd: string;\n manager: ProcessManager;\n /** Receives status lines: success, validation errors, reload errors. */\n log: (msg: string) => void;\n}\n\n/** Re-loads the config, validates it, diffs against the running set, and\n * applies add/remove/restart at the service level. A failed validation\n * leaves the running set untouched. Pure (idempotent given the same\n * config file + manager state), so both the TUI hook and the daemon\n * can call it directly. */\nexport async function applyConfigChange(opts: ConfigWatchOpts): Promise<void> {\n const { configPath, baseCwd, manager, log } = opts;\n try {\n const nextCfg = await loadConfig(configPath);\n const errs = validateConfig(nextCfg, baseCwd);\n if (errs.length) {\n log(`⚠ config reload failed:\\n${formatValidationErrors(errs)}`);\n return;\n }\n const currentSvcs = [...manager.state.values()].map(s => s.svc);\n const diff = diffServices(currentSvcs, nextCfg.services);\n if (!diff.added.length && !diff.removed.length && !diff.changed.length) return;\n\n for (const name of diff.removed) {\n manager.stop(name);\n manager.state.delete(name);\n }\n let colorIdx = currentSvcs.length;\n for (const { next } of diff.changed) {\n const prev = manager.state.get(next.name);\n const ci = prev?.colorIdx ?? colorIdx++;\n manager.stop(next.name);\n // Brief pause so the previous process releases its port before the new one starts.\n await new Promise(r => setTimeout(r, 800));\n await manager.install(next, ci);\n await manager.start(next, ci, true);\n }\n for (const next of diff.added) {\n const ci = colorIdx++;\n await manager.install(next, ci);\n await manager.start(next, ci);\n }\n log(`🔁 config reloaded: ${summariseDiff(diff)}`);\n } catch (e: any) {\n log(`⚠ config reload error: ${e.message}`);\n }\n}\n\n/** Watch a config file and call applyConfigChange on each save, debounced\n * to 250 ms. Uses `fs.watchFile` (polling, 500 ms) rather than `fs.watch`\n * for cross-platform reliability — `fs.watch` on a single file is flaky\n * on macOS (FSEvents) and has its own quirks on Windows. Polling a single\n * file every 500 ms is negligible cost for a long-running daemon.\n * In-flight guard coalesces back-to-back saves. Returns a cleanup function. */\nexport function watchConfig(opts: ConfigWatchOpts): () => void {\n let debounceTimer: NodeJS.Timeout | null = null;\n let reloadInFlight = false;\n let reloadAgain = false;\n\n const trigger = async () => {\n if (reloadInFlight) { reloadAgain = true; return; }\n reloadInFlight = true;\n try {\n await applyConfigChange(opts);\n } finally {\n reloadInFlight = false;\n if (reloadAgain) { reloadAgain = false; void trigger(); }\n }\n };\n\n const listener = (curr: Stats, prev: Stats) => {\n // watchFile fires on every poll; skip when nothing actually changed.\n if (curr.mtimeMs === prev.mtimeMs && curr.size === prev.size) return;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => void trigger(), 250);\n };\n\n watchFile(opts.configPath, { interval: 500 }, listener);\n\n return () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n unwatchFile(opts.configPath, listener);\n };\n}\n","import type { ServiceConfig } from './types.js';\n\nexport interface ServiceDiff {\n added: ServiceConfig[];\n removed: string[];\n changed: Array<{ next: ServiceConfig; prev: ServiceConfig }>;\n unchanged: string[];\n}\n\n/** Fields whose change requires a respawn. Anything else (icon, etc.) is metadata. */\nconst SPAWN_RELEVANT: (keyof ServiceConfig)[] = [\n 'cwd', 'cmd', 'args', 'port', 'phase', 'maxMem', 'preBuild', 'watchBuild',\n 'nodeArgs', 'extraEnv', 'healthCheck', 'readyPattern', 'errorPattern', 'type',\n];\n\nfunction hasSpawnRelevantChange(prev: ServiceConfig, next: ServiceConfig): boolean {\n for (const k of SPAWN_RELEVANT) {\n if (JSON.stringify(prev[k]) !== JSON.stringify(next[k])) return true;\n }\n return false;\n}\n\n/** Computes the set-difference between two service lists by name.\n * - added: in `next` but not in `prev`\n * - removed: in `prev` but not in `next`\n * - changed: in both but with a spawn-relevant field change\n * - unchanged: in both with identical spawn-relevant fields */\nexport function diffServices(prev: ServiceConfig[], next: ServiceConfig[]): ServiceDiff {\n const prevByName = new Map(prev.map(s => [s.name, s]));\n const nextByName = new Map(next.map(s => [s.name, s]));\n\n const added: ServiceConfig[] = [];\n const removed: string[] = [];\n const changed: Array<{ next: ServiceConfig; prev: ServiceConfig }> = [];\n const unchanged: string[] = [];\n\n for (const [name, p] of prevByName) {\n if (!nextByName.has(name)) { removed.push(name); continue; }\n const n = nextByName.get(name)!;\n if (hasSpawnRelevantChange(p, n)) changed.push({ prev: p, next: n });\n else unchanged.push(name);\n }\n for (const [name, n] of nextByName) {\n if (!prevByName.has(name)) added.push(n);\n }\n return { added, removed, changed, unchanged };\n}\n\n/** Short human-readable summary for the TUI banner. */\nexport function summariseDiff(d: ServiceDiff): string {\n const parts: string[] = [];\n if (d.added.length) parts.push(`+${d.added.length} added`);\n if (d.removed.length) parts.push(`-${d.removed.length} removed`);\n if (d.changed.length) parts.push(`~${d.changed.length} changed`);\n if (!parts.length) parts.push('no changes');\n return parts.join(', ');\n}\n","/** Find and resolve conflicts on devup-managed ports — i.e. some other\n * process is already listening on a port we want, so the spawn would\n * fail with EADDRINUSE.\n *\n * Resolution is offered as a pre-boot step in three flavours:\n * 1. `--kill-port-conflicts` flag → auto-kill, no prompt.\n * 2. Interactive TTY → list conflicts, ask for confirmation.\n * 3. Non-interactive (CI, piped) → fail with the list as instructions.\n *\n * Detection uses `lsof` on Linux/macOS. Windows support is intentionally\n * out of scope for v1 (daemon mode itself doesn't run on Windows yet).\n * When `lsof` is unavailable the conflict is reported without a holder\n * (the user gets the port number but not the PID). */\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { isPortBindable } from './health.js';\nimport type { ServiceConfig } from '../config/types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface PortHolder {\n pid: number;\n command: string;\n}\n\nexport interface PortConflict {\n service: string;\n port: number;\n holder: PortHolder | null;\n}\n\nconst isUnix = process.platform === 'linux' || process.platform === 'darwin';\n\n/** Run `lsof` to find what's listening on a port. Returns the first matching\n * PID + command, or null if nothing's there (or lsof isn't available). */\nexport async function findPortHolder(port: number): Promise<PortHolder | null> {\n if (!isUnix) return null;\n try {\n // -nP no DNS / port-name resolution (fast)\n // -iTCP:N restrict to TCP port N\n // -sTCP:LISTEN only LISTEN state (skip established/closed)\n // -F pcn output: pid + command, machine-readable\n const { stdout } = await execAsync(`lsof -nP -iTCP:${port} -sTCP:LISTEN -F pcn`);\n return parseLsof(stdout);\n } catch {\n // lsof exits non-zero when nothing matches OR when lsof is missing.\n return null;\n }\n}\n\nfunction parseLsof(stdout: string): PortHolder | null {\n // -F output: groups of fields, one per line, prefixed by a tag char.\n // p<pid> c<command> n<name> …\n let pid: number | null = null;\n let cmd = '';\n for (const line of stdout.split('\\n')) {\n if (!line) continue;\n const tag = line[0];\n const value = line.slice(1);\n if (tag === 'p') {\n // New record. Emit the previous one if complete.\n if (pid != null) return { pid, command: cmd || 'unknown' };\n pid = Number(value);\n } else if (tag === 'c') {\n cmd = value;\n }\n }\n if (pid != null) return { pid, command: cmd || 'unknown' };\n return null;\n}\n\n/** Scan every configured service for port conflicts. APIs and webs both —\n * pre-boot we want to surface any conflict the user will hit during spawn,\n * regardless of service type. Web dev servers (Vite, ng serve, etc.) handle\n * port-collision retry at runtime, but pre-boot the user typically wants to\n * reclaim THE configured port, not let the dev server roll it. */\nexport async function scanPortConflicts(services: ServiceConfig[]): Promise<PortConflict[]> {\n const conflicts: PortConflict[] = [];\n for (const svc of services) {\n const bindable = await isPortBindable(svc.port);\n if (bindable) continue;\n const holder = await findPortHolder(svc.port);\n conflicts.push({ service: svc.name, port: svc.port, holder });\n }\n return conflicts;\n}\n\n/** SIGTERM with grace, falling back to SIGKILL after `graceMs`. */\nexport async function killHolder(pid: number, graceMs = 3000): Promise<boolean> {\n try { process.kill(pid, 'SIGTERM'); } catch { return false; }\n const deadline = Date.now() + graceMs;\n while (Date.now() < deadline) {\n if (!pidAlive(pid)) return true;\n await sleep(100);\n }\n try { process.kill(pid, 'SIGKILL'); } catch { /* already dead */ }\n // Final check: did SIGKILL land?\n await sleep(100);\n return !pidAlive(pid);\n}\n\nfunction pidAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\nexport interface ResolveOpts {\n autoKill: boolean;\n out: (line: string) => void;\n /** Returns true if user confirms, false otherwise. Skipped when autoKill or\n * when stdin is not a TTY. */\n prompt?: () => Promise<boolean>;\n /** If stdin is not a TTY and autoKill is false, resolution fails by default.\n * Tests pass `isInteractive: true` with a mocked prompt to bypass. */\n isInteractive?: boolean;\n}\n\n/** Returns true if all conflicts were resolved (no holders left), false if the\n * user declined or some kills failed. */\nexport async function resolvePortConflicts(\n conflicts: PortConflict[],\n opts: ResolveOpts,\n): Promise<boolean> {\n if (!conflicts.length) return true;\n\n const { autoKill, out, prompt, isInteractive = process.stdin.isTTY ?? false } = opts;\n\n // Render the conflict list.\n out('⚠ Port conflicts detected on the following services:');\n out('');\n const maxName = Math.max(...conflicts.map(c => c.service.length), 8);\n for (const c of conflicts) {\n const holder = c.holder\n ? `pid=${c.holder.pid} process=${c.holder.command}`\n : `(unable to identify holder${isUnix ? '' : ' — Windows not supported'})`;\n out(` :${String(c.port).padEnd(6)} ${c.service.padEnd(maxName)} ${holder}`);\n }\n out('');\n\n if (autoKill) {\n return await killAll(conflicts, out);\n }\n\n if (!isInteractive || !prompt) {\n out('Re-run with --kill-port-conflicts to take them over, or stop them yourself.');\n return false;\n }\n\n const confirmed = await prompt();\n if (!confirmed) {\n out('Aborted — no processes killed.');\n return false;\n }\n return await killAll(conflicts, out);\n}\n\nasync function killAll(conflicts: PortConflict[], out: (l: string) => void): Promise<boolean> {\n let allOk = true;\n for (const c of conflicts) {\n if (!c.holder) {\n out(`✗ :${c.port} ${c.service}: holder unknown, cannot kill — skipped`);\n allOk = false;\n continue;\n }\n const ok = await killHolder(c.holder.pid);\n if (ok) {\n out(`✓ :${c.port} ${c.service}: killed pid=${c.holder.pid}`);\n } else {\n out(`✗ :${c.port} ${c.service}: pid=${c.holder.pid} survived SIGKILL`);\n allOk = false;\n }\n }\n return allOk;\n}\n","import type { Platform } from './types.js';\n\nexport async function detectPlatform(): Promise<Platform> {\n switch (process.platform) {\n case 'linux': {\n const { LinuxPlatform } = await import('./linux.js');\n return new LinuxPlatform();\n }\n case 'darwin': {\n const { DarwinPlatform } = await import('./darwin.js');\n return new DarwinPlatform();\n }\n case 'win32': {\n const { Win32Platform } = await import('./win32.js');\n return new Win32Platform();\n }\n default:\n throw new Error(`Unsupported platform: ${process.platform}`);\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from './types.js';\n\nconst EMPTY_CONFIG = 'http:\\n routers: {}\\n services: {}\\n';\n\nexport class TraefikProvider implements ProxyConfigProvider {\n readonly name = 'traefik';\n\n generate(services: Map<string, ServiceState>, opts: ProxyOpts): string {\n const routers: string[] = [];\n const svcs: string[] = [];\n\n for (const [name, st] of services) {\n if (st.health !== 'up') continue;\n const sub = opts.routes[name];\n if (sub === undefined) continue;\n\n const rule = sub ? `Host(\\`${sub}.${opts.domain}\\`)` : `Host(\\`${opts.domain}\\`)`;\n const safe = name.replace(/[^a-z0-9-]/g, '-');\n const port = st.realPort ?? st.port;\n\n let router = ` ${safe}:\\n rule: \"${rule}\"\\n service: ${safe}\\n entryPoints:\\n - ${opts.entrypoint}`;\n if (opts.tls) router += `\\n tls:\\n certResolver: le`;\n routers.push(router);\n\n svcs.push(` ${safe}:\\n loadBalancer:\\n servers:\\n - url: \"http://${opts.host}:${port}\"`);\n }\n\n if (!routers.length) return EMPTY_CONFIG;\n return `http:\\n routers:\\n${routers.join('\\n')}\\n services:\\n${svcs.join('\\n')}\\n`;\n }\n\n write(content: string, opts: ProxyOpts): void {\n const dir = dirname(opts.confPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(opts.confPath, content);\n }\n\n clear(opts: ProxyOpts): void {\n this.write(EMPTY_CONFIG, opts);\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from './types.js';\n\nconst EMPTY_CONFIG = '# devup: no healthy services\\n';\n\n/** Generates an Nginx server-block config file.\n * Drop it into /etc/nginx/conf.d/ or include from your main nginx.conf. */\nexport class NginxProvider implements ProxyConfigProvider {\n readonly name = 'nginx';\n\n generate(services: Map<string, ServiceState>, opts: ProxyOpts): string {\n const blocks: string[] = [];\n\n for (const [name, st] of services) {\n if (st.health !== 'up') continue;\n const sub = opts.routes[name];\n if (sub === undefined) continue;\n\n const serverName = sub ? `${sub}.${opts.domain}` : opts.domain;\n const port = st.realPort ?? st.port;\n const listen = opts.tls ? '443 ssl' : '80';\n\n const tlsBlock = opts.tls\n ? ` ssl_certificate /etc/nginx/certs/${serverName}.crt;\\n` +\n ` ssl_certificate_key /etc/nginx/certs/${serverName}.key;\\n`\n : '';\n\n blocks.push(\n `server {\\n` +\n ` listen ${listen};\\n` +\n ` server_name ${serverName};\\n` +\n tlsBlock +\n ` location / {\\n` +\n ` proxy_pass http://${opts.host}:${port};\\n` +\n ` proxy_set_header Host $host;\\n` +\n ` proxy_set_header X-Real-IP $remote_addr;\\n` +\n ` proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\\n` +\n ` proxy_set_header X-Forwarded-Proto $scheme;\\n` +\n ` proxy_http_version 1.1;\\n` +\n ` proxy_set_header Upgrade $http_upgrade;\\n` +\n ` proxy_set_header Connection \"upgrade\";\\n` +\n ` }\\n` +\n `}`,\n );\n }\n\n if (!blocks.length) return EMPTY_CONFIG;\n return blocks.join('\\n\\n') + '\\n';\n }\n\n write(content: string, opts: ProxyOpts): void {\n const dir = dirname(opts.confPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(opts.confPath, content);\n }\n\n clear(opts: ProxyOpts): void {\n this.write(EMPTY_CONFIG, opts);\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from './types.js';\n\nconst EMPTY_CONFIG = '# devup: no healthy services\\n';\n\n/** Generates a Caddyfile.\n * Tip: point Caddy at it with `caddy run --config <path> --adapter caddyfile` or include it. */\nexport class CaddyProvider implements ProxyConfigProvider {\n readonly name = 'caddy';\n\n generate(services: Map<string, ServiceState>, opts: ProxyOpts): string {\n const blocks: string[] = [];\n\n for (const [name, st] of services) {\n if (st.health !== 'up') continue;\n const sub = opts.routes[name];\n if (sub === undefined) continue;\n\n const host = sub ? `${sub}.${opts.domain}` : opts.domain;\n const port = st.realPort ?? st.port;\n const siteAddr = opts.tls ? host : `http://${host}`;\n\n blocks.push(\n `${siteAddr} {\\n` +\n ` reverse_proxy ${opts.host}:${port}\\n` +\n `}`,\n );\n }\n\n if (!blocks.length) return EMPTY_CONFIG;\n return blocks.join('\\n\\n') + '\\n';\n }\n\n write(content: string, opts: ProxyOpts): void {\n const dir = dirname(opts.confPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(opts.confPath, content);\n }\n\n clear(opts: ProxyOpts): void {\n this.write(EMPTY_CONFIG, opts);\n }\n}\n","import type { ProxyConfigProvider } from './types.js';\nimport { TraefikProvider } from './traefik.js';\nimport { NginxProvider } from './nginx.js';\nimport { CaddyProvider } from './caddy.js';\n\nconst providers: Record<string, () => ProxyConfigProvider> = {\n traefik: () => new TraefikProvider(),\n nginx: () => new NginxProvider(),\n caddy: () => new CaddyProvider(),\n};\n\nexport function detectProxyProvider(name: string): ProxyConfigProvider {\n const factory = providers[name];\n if (!factory) {\n const available = Object.keys(providers).join(', ');\n throw new Error(`Unknown proxy provider: \"${name}\". Available: ${available}`);\n }\n return factory();\n}\n","import React, { useCallback, useRef } from 'react';\nimport { Box, Text } from 'ink';\nimport type { Platform } from '../platform/types.js';\nimport type { DevStackConfig, ServiceConfig } from '../config/types.js';\nimport type { CliArgs } from '../config/cli.js';\nimport type { ProxyConfigProvider, ProxyOpts } from '../proxy-config/types.js';\nimport type { LogSink } from '../process/log-sink.js';\nimport { useProcessManager } from './hooks/useProcessManager.js';\nimport { useKeyBindings } from './hooks/useKeyBindings.js';\nimport { useProxySync } from './hooks/useProxySync.js';\nimport { useTerminalSize } from './hooks/useTerminalSize.js';\nimport { useLogsPause } from './hooks/useLogsPause.js';\nimport { useControlPlane } from './hooks/useControlPlane.js';\nimport { useHotReload } from './hooks/useHotReload.js';\nimport { useContextualTips } from './hooks/useContextualTips.js';\nimport { useBootSequence } from './hooks/useBootSequence.js';\nimport { LogsPanel } from './LogsPanel.js';\nimport { StatsPanel } from './StatsPanel.js';\nimport { StatusBar } from './StatusBar.js';\nimport { ServiceList } from './ServiceList.js';\nimport { SearchInput } from './SearchInput.js';\nimport type { LazyProxy } from '../lazy/proxy.js';\nimport { stopExternals, type ExternalProc } from '../process/external.js';\n\n/** Builds the URL to open in the browser when the user picks a service.\n * Honors the proxy + TLS settings: if --proxy is active and the service has\n * a route, opens https://<sub>.<domain>; otherwise falls back to http://localhost:<port>. */\nexport function buildServiceUrl(\n name: string,\n port: number,\n proxyActive: boolean,\n proxyOpts: ProxyOpts | null,\n): string {\n if (proxyActive && proxyOpts) {\n const sub = proxyOpts.routes[name];\n if (sub !== undefined) {\n const host = sub ? `${sub}.${proxyOpts.domain}` : proxyOpts.domain;\n const scheme = proxyOpts.tls ? 'https' : 'http';\n return `${scheme}://${host}`;\n }\n }\n return `http://localhost:${port}`;\n}\n\ninterface Props {\n config: DevStackConfig;\n services: ServiceConfig[];\n cliArgs: CliArgs;\n platform: Platform;\n env: Record<string, string>;\n baseCwd: string;\n proxyProvider: ProxyConfigProvider | null;\n proxyOpts: ProxyOpts | null;\n logSink: LogSink | null;\n}\n\nexport function App({ config, services, cliArgs, platform, env, baseCwd, proxyProvider, proxyOpts, logSink }: Props) {\n const rows = useTerminalSize();\n const logsHeight = Math.floor(rows * 0.65);\n const statsHeight = rows - logsHeight - 2; // 2 for header + statusbar\n const maxNameLen = Math.max(...services.map(s => s.name.length), 10);\n\n const pm = useProcessManager(platform, baseCwd, env, logSink);\n const lazyProxies = useRef<Map<string, LazyProxy>>(new Map());\n const externals = useRef<ExternalProc[]>([]);\n\n const kb = useKeyBindings({\n onQuit: () => { void shutdown(); },\n onClearLogs: pm.clearLogs,\n onToggleProxy: () => {},\n });\n\n const proxyCtx = proxyProvider && proxyOpts ? { provider: proxyProvider, opts: proxyOpts } : null;\n const socketServer = useControlPlane(pm.manager, config.name, logSink, pm.pushLog, pm.logBus, pm.stateBus, platform, proxyCtx);\n\n const shutdown = useCallback(async () => {\n lazyProxies.current.forEach(p => p.destroy());\n await socketServer.current?.close();\n await pm.cleanup();\n if (externals.current.length) {\n await stopExternals(externals.current, platform, {\n baseCwd, env,\n onLog: (svc, msg) => pm.pushLog(`ext:${svc}`, msg, 12),\n });\n externals.current = [];\n }\n await logSink?.close();\n process.exit(0);\n }, [pm, logSink, platform, baseCwd, env, socketServer]);\n\n useHotReload(pm.manager, cliArgs, baseCwd, pm.pushLog);\n useLogsPause(pm.setPaused, kb.logsPaused, kb.logsScrollOffset);\n const activeTip = useContextualTips(pm.logs.length, !!kb.searchTerm, !!kb.logFilter, pm.states);\n useProxySync(proxyProvider, proxyOpts, pm.states, kb.proxyEnabled);\n useBootSequence(pm.manager, config, services, cliArgs, platform, env, baseCwd,\n { lazyProxies, externals }, pm.pushLog);\n\n const handleFilterSelect = useCallback((name: string) => kb.setFilter(name), [kb]);\n const handleRestartSelect = useCallback((name: string) => { pm.restart(name); kb.setModal('none'); }, [pm, kb]);\n const handleOpenSelect = useCallback((name: string) => {\n const st = pm.states.get(name);\n if (st) {\n const url = buildServiceUrl(name, st.svc.port, cliArgs.proxy, proxyOpts);\n platform.openBrowser(url);\n }\n kb.setModal('none');\n }, [pm, platform, kb, cliArgs.proxy, proxyOpts]);\n\n const icon = config.icon ?? '📦';\n const modeLabel = cliArgs.lazy && config.lazy ? 'lazy' : 'normal';\n\n return (\n <Box flexDirection=\"column\" height={rows}>\n <Box>\n <Text bold color=\"cyan\"> {icon} {config.name} — devup — {services.length} services ({modeLabel}) </Text>\n {activeTip && <Text dimColor> · {activeTip}</Text>}\n </Box>\n\n <LogsPanel\n logs={pm.logs} filter={kb.logFilter} searchTerm={kb.searchTerm}\n paused={kb.logsPaused} showTimestamps={kb.showTimestamps}\n maxNameLen={maxNameLen} height={logsHeight} focused={kb.panel === 'logs'}\n scrollOffset={kb.logsScrollOffset} resetScroll={kb.resetLogsScroll}\n levelFilter={kb.levelFilter}\n filteredColorIdx={kb.logFilter ? (pm.states.get(kb.logFilter)?.colorIdx ?? null) : null}\n />\n\n <StatsPanel\n states={pm.states} stats={pm.stats} sortMode={kb.sortMode}\n maxNameLen={maxNameLen} height={statsHeight} focused={kb.panel === 'stats'}\n scrollOffset={kb.statsScrollOffset} resetScroll={kb.resetStatsScroll}\n verbose={kb.verboseStats}\n />\n\n {kb.modal === 'filter' && (\n <ServiceList title=\"Filter by service\" services={pm.states} onSelect={handleFilterSelect} onClose={() => kb.setModal('none')} />\n )}\n {kb.modal === 'restart' && (\n <ServiceList title=\"Restart service\" services={pm.states} onSelect={handleRestartSelect} onClose={() => kb.setModal('none')} />\n )}\n {kb.modal === 'open' && (\n <ServiceList title=\"Open in browser\" services={pm.states} onSelect={handleOpenSelect} onClose={() => kb.setModal('none')} filterType=\"web\" />\n )}\n {kb.modal === 'search' && (\n <SearchInput onSubmit={kb.setSearch} onClose={() => kb.setModal('none')} />\n )}\n\n <StatusBar />\n </Box>\n );\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { ProcessManager } from '../../process/manager.js';\nimport type { ProcessState } from '../../process/types.js';\nimport type { Platform } from '../../platform/types.js';\nimport type { ServiceConfig } from '../../config/types.js';\nimport { calcCpuPercent, detectLogLevel, type LogLevel } from '../../utils.js';\nimport { LogSink } from '../../process/log-sink.js';\nimport { Broadcaster } from '../../utils/broadcaster.js';\n\nexport interface LogEntry {\n svcName: string;\n text: string;\n colorIdx: number;\n ts: number;\n level: LogLevel;\n}\n\nexport interface ServiceStats {\n cpu: string;\n mem: string;\n}\n\nexport function useProcessManager(\n platform: Platform,\n baseCwd: string,\n env: Record<string, string>,\n logSink: LogSink | null = null,\n) {\n const [states, setStates] = useState<Map<string, ProcessState>>(new Map());\n const [logs, setLogs] = useState<LogEntry[]>([]);\n const [stats, setStats] = useState<Map<string, ServiceStats>>(new Map());\n const mgrRef = useRef<ProcessManager | null>(null);\n const prevCpu = useRef<Map<string, { time: number; cpu: number }>>(new Map());\n const pausedRef = useRef(false);\n const pendingLogsRef = useRef<LogEntry[]>([]);\n const sinkRef = useRef<LogSink | null>(logSink);\n sinkRef.current = logSink;\n\n // Stable broadcaster instances — control plane subscribers tap into these.\n const logBus = useRef(new Broadcaster<{ svc: string; text: string }>());\n const stateBus = useRef(new Broadcaster<{ name: string; state: ProcessState }>());\n\n useEffect(() => {\n const mgr = new ProcessManager({\n baseCwd, env, platform,\n events: {\n onLog: (svcName, text, colorIdx) => {\n sinkRef.current?.write(svcName, text);\n logBus.current.emit({ svc: svcName, text });\n const entry: LogEntry = { svcName, text, colorIdx, ts: Date.now(), level: detectLogLevel(text) };\n if (pausedRef.current) {\n pendingLogsRef.current.push(entry);\n if (pendingLogsRef.current.length > 5000) {\n pendingLogsRef.current = pendingLogsRef.current.slice(-5000);\n }\n return;\n }\n setLogs(prev => {\n const next = prev.concat(entry);\n return next.length > 5000 ? next.slice(-5000) : next;\n });\n },\n onStateChange: (name, state) => {\n stateBus.current.emit({ name, state });\n setStates(new Map(mgr.state));\n },\n },\n });\n mgrRef.current = mgr;\n return () => { mgr.cleanup(); };\n }, [baseCwd, env, platform]);\n\n // Health + stats polling\n useEffect(() => {\n const id = setInterval(async () => {\n const mgr = mgrRef.current;\n if (!mgr) return;\n await mgr.checkAllHealth();\n setStates(new Map(mgr.state));\n\n const pids: number[] = [];\n const pidMap = new Map<number, string>();\n for (const [name, st] of mgr.state) {\n if (st.pid) { pids.push(st.pid); pidMap.set(st.pid, name); }\n }\n if (pids.length) {\n const raw = await platform.getProcessStats(pids);\n const next = new Map<string, ServiceStats>();\n for (const [pid, data] of raw) {\n const name = pidMap.get(pid);\n if (!name) continue;\n const prev = prevCpu.current.get(name) ?? { time: Date.now(), cpu: 0 };\n const cpuPct = calcCpuPercent(data.cpuSeconds, prev.cpu, prev.time);\n prevCpu.current.set(name, { time: Date.now(), cpu: data.cpuSeconds });\n next.set(name, { cpu: cpuPct.toFixed(1) + '%', mem: (data.rss / 1024).toFixed(1) + ' MB' });\n }\n setStats(next);\n }\n }, 3000);\n return () => clearInterval(id);\n }, [platform]);\n\n const mgr = mgrRef.current;\n\n const clearLogs = useCallback(() => { pendingLogsRef.current = []; setLogs([]); }, []);\n\n /** Push a log line not tied to a ProcessManager-managed service (e.g. externals). */\n const pushLog = useCallback((svcName: string, text: string, colorIdx = 0) => {\n sinkRef.current?.write(svcName, text);\n logBus.current.emit({ svc: svcName, text });\n const entry: LogEntry = { svcName, text, colorIdx, ts: Date.now(), level: detectLogLevel(text) };\n if (pausedRef.current) {\n pendingLogsRef.current.push(entry);\n if (pendingLogsRef.current.length > 5000) {\n pendingLogsRef.current = pendingLogsRef.current.slice(-5000);\n }\n return;\n }\n setLogs(prev => {\n const next = prev.concat(entry);\n return next.length > 5000 ? next.slice(-5000) : next;\n });\n }, []);\n\n const setPaused = useCallback((paused: boolean) => {\n pausedRef.current = paused;\n if (!paused && pendingLogsRef.current.length) {\n const flush = pendingLogsRef.current;\n pendingLogsRef.current = [];\n setLogs(prev => {\n const next = prev.concat(flush);\n return next.length > 5000 ? next.slice(-5000) : next;\n });\n }\n }, []);\n\n return {\n states, logs, stats,\n start: useCallback((svc: ServiceConfig, colorIdx: number) => mgr?.start(svc, colorIdx), [mgr]),\n stop: useCallback((name: string) => mgr?.stop(name), [mgr]),\n restart: useCallback((name: string) => mgr?.restart(name), [mgr]),\n install: useCallback((svc: ServiceConfig, colorIdx: number) => mgr?.install(svc, colorIdx), [mgr]),\n cleanup: useCallback(() => mgr?.cleanup(), [mgr]),\n clearLogs,\n setPaused,\n pushLog,\n manager: mgr,\n logBus: logBus.current,\n stateBus: stateBus.current,\n };\n}\n","import { useInput } from 'ink';\nimport React, { useState, useCallback } from 'react';\n\nexport type Modal = 'none' | 'filter' | 'restart' | 'open' | 'search';\nexport type Panel = 'logs' | 'stats';\n\nexport type LevelFilter = 'all' | 'error' | 'warn';\n\nexport interface KeyState {\n panel: Panel;\n modal: Modal;\n logFilter: string | null;\n searchTerm: string | null;\n logsPaused: boolean;\n showTimestamps: boolean;\n sortIdx: number;\n proxyEnabled: boolean;\n logsScrollOffset: number;\n statsScrollOffset: number;\n levelFilter: LevelFilter;\n verboseStats: boolean;\n}\n\nconst SORT_MODES = ['name', 'mem', 'errors'] as const;\n\n// delta < 0 = mover vista hacia arriba; delta > 0 = hacia abajo.\n// Para logs el offset crece hacia atrás (más viejo), para stats crece hacia abajo (siguientes filas).\nfunction scrollBy(setState: React.Dispatch<React.SetStateAction<KeyState>>, delta: number) {\n setState(s => {\n if (s.panel === 'logs') {\n // up visual → más viejas → bottomOffset + |delta|\n const next = s.logsScrollOffset - delta;\n return { ...s, logsScrollOffset: Math.max(0, next) };\n }\n const next = s.statsScrollOffset + delta;\n return { ...s, statsScrollOffset: Math.max(0, next) };\n });\n}\n\nfunction scrollTo(setState: React.Dispatch<React.SetStateAction<KeyState>>, target: 'top' | 'bottom') {\n setState(s => {\n if (s.panel === 'logs') {\n // top visual = línea más vieja = bottomOffset máximo\n return { ...s, logsScrollOffset: target === 'top' ? Number.MAX_SAFE_INTEGER : 0 };\n }\n return { ...s, statsScrollOffset: target === 'top' ? 0 : Number.MAX_SAFE_INTEGER };\n });\n}\n\nexport function useKeyBindings(opts: {\n onQuit: () => void;\n onClearLogs: () => void;\n onToggleProxy: () => void;\n}) {\n const [state, setState] = useState<KeyState>({\n panel: 'logs', modal: 'none', logFilter: null, searchTerm: null,\n logsPaused: false, showTimestamps: false, sortIdx: 0, proxyEnabled: false,\n logsScrollOffset: 0, statsScrollOffset: 0, levelFilter: 'all', verboseStats: false,\n });\n\n const LEVEL_CYCLE: LevelFilter[] = ['all', 'error', 'warn'];\n\n const setModal = useCallback((modal: Modal) => setState(s => ({ ...s, modal })), []);\n const setFilter = useCallback((f: string | null) => setState(s => ({ ...s, logFilter: f, modal: 'none' })), []);\n const setSearch = useCallback((t: string | null) => setState(s => ({ ...s, searchTerm: t, modal: 'none' })), []);\n\n const isActive = process.stdin.isTTY ?? false;\n\n useInput((input, key) => {\n if (state.modal !== 'none') return;\n\n if (input === 'q' || (key.ctrl && input === 'c')) opts.onQuit();\n // ── Scroll (ctrl + tecla evaluado primero para no chocar con letras simples) ──\n else if (key.ctrl && input === 'a') scrollTo(setState, 'top');\n else if (key.ctrl && input === 'e') scrollTo(setState, 'bottom');\n else if (key.ctrl && input === 'b') scrollBy(setState, -10); // PgUp\n else if (key.ctrl && input === 'f') scrollBy(setState, +10); // PgDn\n else if (key.upArrow) scrollBy(setState, -1);\n else if (key.downArrow) scrollBy(setState, +1);\n else if (input === '[') scrollBy(setState, -10);\n else if (input === ']') scrollBy(setState, +10);\n // ── Acciones ──\n else if (input === 'c') opts.onClearLogs();\n else if (key.tab) setState(s => ({ ...s, panel: s.panel === 'logs' ? 'stats' : 'logs' }));\n else if (input === 'f') setModal('filter');\n else if (input === 'r') setModal('restart');\n else if (input === 'o') setModal('open');\n else if (input === '/') setModal('search');\n else if (input === 'a') setState(s => ({ ...s, logFilter: null, searchTerm: null, levelFilter: 'all' }));\n else if (input === 'p') setState(s => ({ ...s, logsPaused: !s.logsPaused }));\n else if (input === 't') setState(s => ({ ...s, showTimestamps: !s.showTimestamps }));\n else if (input === 's') setState(s => ({ ...s, sortIdx: (s.sortIdx + 1) % SORT_MODES.length }));\n else if (input === 'T') { opts.onToggleProxy(); setState(s => ({ ...s, proxyEnabled: !s.proxyEnabled })); }\n else if (input === 'L') setState(s => ({ ...s, levelFilter: LEVEL_CYCLE[(LEVEL_CYCLE.indexOf(s.levelFilter) + 1) % LEVEL_CYCLE.length]! }));\n else if (input === 'v') setState(s => ({ ...s, verboseStats: !s.verboseStats }));\n }, { isActive });\n\n return { \n ...state, \n setModal, \n setFilter, \n setSearch, \n sortMode: SORT_MODES[state.sortIdx]!,\n // Funciones para resetear el scroll cuando cambia el contenido\n resetLogsScroll: useCallback(() => setState(s => ({ ...s, logsScrollOffset: 0 })), []),\n resetStatsScroll: useCallback(() => setState(s => ({ ...s, statsScrollOffset: 0 })), []),\n };\n}\n","import { useEffect, useRef } from 'react';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from '../../proxy-config/types.js';\nimport type { ProcessState } from '../../process/types.js';\n\nexport function useProxySync(\n provider: ProxyConfigProvider | null,\n opts: ProxyOpts | null,\n states: Map<string, ProcessState>,\n enabled: boolean,\n) {\n const statesRef = useRef(states);\n const lastContentRef = useRef<string | null>(null);\n statesRef.current = states;\n\n useEffect(() => {\n if (!provider || !opts || !enabled) return;\n\n const sync = () => {\n const svcStates = new Map<string, ServiceState>();\n for (const [name, st] of statesRef.current) {\n svcStates.set(name, { port: st.svc.port, health: st.health, realPort: (st.svc as any).realPort });\n }\n const content = provider.generate(svcStates, opts);\n if (content === lastContentRef.current) return;\n lastContentRef.current = content;\n provider.write(content, opts);\n };\n\n sync();\n const id = setInterval(sync, 3000);\n return () => {\n clearInterval(id);\n lastContentRef.current = null;\n };\n }, [provider, opts, enabled]);\n}\n","import { useEffect, useState } from 'react';\nimport { useStdout } from 'ink';\n\n/** Returns the current terminal row count, re-rendering on resize.\n * Falls back to 40 when stdout isn't available (non-TTY mode). */\nexport function useTerminalSize(): number {\n const { stdout } = useStdout();\n const [rows, setRows] = useState(stdout?.rows ?? 40);\n useEffect(() => {\n if (!stdout) return;\n const onResize = () => setRows(stdout.rows ?? 40);\n stdout.on('resize', onResize);\n return () => { stdout.off('resize', onResize); };\n }, [stdout]);\n return rows;\n}\n","import { useEffect } from 'react';\n\n/** Couples the keyboard pause state (explicit `p` toggle OR auto-pause when\n * scrolled up) with the process manager's logs sink. */\nexport function useLogsPause(\n setPaused: (paused: boolean) => void,\n logsPaused: boolean,\n logsScrollOffset: number,\n): void {\n useEffect(() => {\n setPaused(logsPaused || logsScrollOffset > 0);\n }, [logsPaused, logsScrollOffset, setPaused]);\n}\n","import { useEffect, useRef } from 'react';\nimport { createInterface } from 'node:readline';\nimport { createReadStream, existsSync } from 'node:fs';\nimport { totalmem, freemem, cpus } from 'node:os';\nimport type { ProcessManager } from '../../process/manager.js';\nimport type { LogSink } from '../../process/log-sink.js';\nimport type { Broadcaster } from '../../utils/broadcaster.js';\nimport type { ProcessState } from '../../process/types.js';\nimport type { Platform } from '../../platform/types.js';\nimport type { ProxyConfigProvider, ProxyOpts } from '../../proxy-config/types.js';\nimport { startSocketServer, type SocketServerHandle } from '../../control-plane/socket-server.js';\nimport { calcCpuPercent } from '../../utils.js';\n\n/** Lifecycle of the Unix-socket JSON-RPC control plane. Mounts when the\n * manager is ready; tears down on unmount.\n *\n * On listen failure (perms, dir missing, port already-in-use on the inode)\n * devup keeps running without the control plane and logs a single notice. */\nexport function useControlPlane(\n manager: ProcessManager | null,\n projectName: string,\n logSink: LogSink | null,\n pushLog: (svc: string, msg: string, colorIdx?: number) => void,\n logBus: Broadcaster<{ svc: string; text: string }>,\n stateBus: Broadcaster<{ name: string; state: ProcessState }>,\n platform: Platform,\n proxy: { provider: ProxyConfigProvider; opts: ProxyOpts } | null,\n): React.RefObject<SocketServerHandle | null> {\n const handleRef = useRef<SocketServerHandle | null>(null);\n const prevCpuMap = useRef(new Map<string, { time: number; cpu: number }>());\n\n useEffect(() => {\n if (!manager) return;\n let handle: SocketServerHandle | null = null;\n (async () => {\n try {\n handle = await startSocketServer(projectName, {\n states: () => manager.state,\n restart: (name) => manager.restart(name),\n stop: (name) => manager.stop(name),\n tailLogs: async (svcName, lines) => {\n if (!logSink) return [];\n const file = logSink.pathFor(svcName);\n if (!existsSync(file)) return [];\n return new Promise<string[]>((resolve, reject) => {\n const buf: string[] = [];\n const rl = createInterface({ input: createReadStream(file, { encoding: 'utf8' }) });\n rl.on('line', l => { buf.push(l); if (buf.length > lines) buf.shift(); });\n rl.on('close', () => resolve(buf));\n rl.on('error', reject);\n });\n },\n watchLogs: (svcName, onLine) => {\n return logBus.subscribe(({ svc, text }) => {\n if (svcName === null || svc === svcName) onLine(svc, text);\n });\n },\n watchStatus: (onUpdate) => {\n return stateBus.subscribe(({ name, state }) => onUpdate(name, state));\n },\n async getStats() {\n const pids: number[] = [];\n const pidToName = new Map<number, string>();\n for (const [name, st] of manager.state) {\n if (st.pid) { pids.push(st.pid); pidToName.set(st.pid, name); }\n }\n const raw = pids.length ? await platform.getProcessStats(pids) : new Map();\n const services: Record<string, { cpu: number; memMB: number }> = {};\n for (const [name] of manager.state) {\n services[name] = { cpu: 0, memMB: 0 };\n }\n for (const [pid, data] of raw) {\n const name = pidToName.get(pid);\n if (!name) continue;\n const prev = prevCpuMap.current.get(name) ?? { time: Date.now(), cpu: 0 };\n const cpu = calcCpuPercent(data.cpuSeconds, prev.cpu, prev.time);\n prevCpuMap.current.set(name, { time: Date.now(), cpu: data.cpuSeconds });\n services[name] = { cpu: Math.round(cpu * 10) / 10, memMB: Math.round((data.rss / 1024) * 10) / 10 };\n }\n return {\n services,\n system: {\n totalMemMB: Math.round(totalmem() / 1024 / 1024),\n freeMemMB: Math.round(freemem() / 1024 / 1024),\n cpuCores: cpus().length,\n },\n };\n },\n getProxyInfo() {\n if (!proxy) return null;\n return {\n active: true,\n provider: proxy.provider.name,\n domain: proxy.opts.domain,\n tls: proxy.opts.tls,\n routes: proxy.opts.routes,\n };\n },\n }, { onLog: msg => pushLog('devup', msg, 12) });\n handleRef.current = handle;\n } catch (e: any) {\n pushLog('devup', `⚠ control plane disabled: ${e.message}`, 5);\n }\n })();\n return () => { void handle?.close(); handleRef.current = null; };\n }, [manager, projectName, logSink, pushLog, logBus, stateBus, platform, proxy]);\n return handleRef;\n}\n","import { useEffect } from 'react';\nimport type { ProcessManager } from '../../process/manager.js';\nimport type { CliArgs } from '../../config/cli.js';\nimport { findConfigFile } from '../../config/loader.js';\nimport { watchConfig } from '../../orchestrator/config-watcher.js';\n\n/** Watches the resolved config file when --watch-config is on. Bridge between\n * React's lifecycle and the pure `watchConfig` helper used by the daemon. */\nexport function useHotReload(\n manager: ProcessManager | null,\n cliArgs: CliArgs,\n baseCwd: string,\n pushLog: (svc: string, msg: string, colorIdx?: number) => void,\n): void {\n useEffect(() => {\n if (!cliArgs.watchConfig || !manager) return;\n let configPath: string;\n try {\n configPath = findConfigFile(baseCwd, cliArgs.configPath);\n } catch (e: any) {\n pushLog('devup', `⚠ watch-config disabled: ${e.message}`, 5);\n return;\n }\n pushLog('devup', `👀 watching ${configPath}`, 12);\n return watchConfig({\n configPath, baseCwd, manager,\n log: msg => pushLog('devup', msg, msg.startsWith('⚠') ? 5 : 12),\n });\n }, [cliArgs.watchConfig, cliArgs.configPath, baseCwd, manager, pushLog]);\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { ProcessState } from '../../process/types.js';\nimport { pickTip } from '../tips.js';\nimport { isCrashLooped } from '../StatsPanel.js';\n\n/** Surfaces a one-liner tip in teachable moments (high log volume, crash\n * loop, etc.). Each tip shows at most once per session and auto-clears\n * after 12 s. */\nexport function useContextualTips(\n totalLogs: number,\n hasSearch: boolean,\n hasFilter: boolean,\n states: Map<string, ProcessState>,\n): string | null {\n const shownTips = useRef<Set<string>>(new Set());\n const [activeTip, setActiveTip] = useState<string | null>(null);\n\n useEffect(() => {\n const tip = pickTip({\n totalLogs,\n hasSearch,\n hasFilter,\n crashLoopedCount: [...states.values()].filter(isCrashLooped).length,\n shown: shownTips.current,\n });\n if (tip && tip.message !== activeTip) {\n shownTips.current.add(tip.id);\n setActiveTip(tip.message);\n const timer = setTimeout(() => setActiveTip(null), 12_000);\n return () => clearTimeout(timer);\n }\n }, [totalLogs, states, hasSearch, hasFilter, activeTip]);\n\n return activeTip;\n}\n","/** Contextual tips for new users. Pure function — easy to test, easy to extend. */\n\nexport interface TipState {\n totalLogs: number;\n hasSearch: boolean;\n hasFilter: boolean;\n crashLoopedCount: number;\n /** IDs of tips already shown this session — they don't repeat. */\n shown: Set<string>;\n}\n\nexport interface Tip {\n id: string;\n message: string;\n}\n\n/** Picks the highest-priority unseen tip whose conditions are met,\n * or null if no tip applies right now. */\nexport function pickTip(state: TipState): Tip | null {\n // Order = priority. Higher-impact first.\n if (state.crashLoopedCount > 0 && !state.shown.has('crashed')) {\n return { id: 'crashed', message: 'tip: press r to restart, or check the log of the failing service' };\n }\n if (state.totalLogs > 1000 && !state.hasSearch && !state.shown.has('search')) {\n return { id: 'search', message: 'tip: press / to search in logs' };\n }\n if (state.totalLogs > 500 && !state.hasFilter && !state.shown.has('filter')) {\n return { id: 'filter', message: 'tip: press f to filter logs by service' };\n }\n return null;\n}\n","import React, { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport type { ProcessState } from '../process/types.js';\nimport type { ServiceStats } from './hooks/useProcessManager.js';\nimport { fmtUptime, sortServiceNames, tagColors, redactSecrets, buildProcessArgs, nextRamBannerVisibility } from '../utils.js';\nimport os from 'node:os';\n\ninterface Props {\n states: Map<string, ProcessState>;\n stats: Map<string, ServiceStats>;\n sortMode: string;\n maxNameLen: number;\n height: number;\n focused: boolean;\n scrollOffset: number;\n resetScroll: () => void;\n verbose?: boolean;\n}\n\nconst H: Record<string, { c: string; color: string }> = {\n up: { c: '●', color: 'green' }, wait: { c: '●', color: 'yellow' },\n down: { c: '●', color: 'red' }, idle: { c: '○', color: 'blue' },\n};\n\n/** Matches the constant in ProcessManager — kept in sync manually. */\nexport const MAX_RESTARTS = 3;\n\nexport function isCrashLooped(st: ProcessState): boolean {\n return st.status === 'crashed' && st.restarts >= MAX_RESTARTS;\n}\n\nfunction Row({ name, st, stat, ml, verbose }: { name: string; st: ProcessState; stat?: ServiceStats; ml: number; verbose?: boolean }) {\n const looped = isCrashLooped(st);\n const indicator = looped\n ? <Text color=\"red\" bold>✖</Text>\n : <Text color={(H[st.health] ?? H['down']!).color}>{(H[st.health] ?? H['down']!).c}</Text>;\n const color = tagColors[st.colorIdx % tagColors.length]!;\n const sc = looped ? 'red' : st.status === 'running' ? 'green' : st.status === 'starting' ? 'yellow' : st.status === 'idle' ? 'blue' : 'red';\n const statusLabel = looped ? 'looping' : st.status;\n const up = st.startedAt ? fmtUptime(Date.now() - st.startedAt) : '-';\n\n if (!verbose) {\n return (\n <Text>\n {indicator} <Text color={color}>{name.padEnd(ml)}</Text> {String(st.svc.port).padStart(5)} <Text color={sc} bold={looped}>{statusLabel.padEnd(8)}</Text> {(stat?.cpu ?? '-').padStart(6)} {(stat?.mem ?? '-').padStart(8)} {String(st.errors).padStart(3)} {String(st.restarts).padStart(3)} {up.padStart(6)}\n </Text>\n );\n }\n\n // Verbose: row + 2 indented lines with the resolved cmd/args and extraEnv.\n const resolvedArgs = buildProcessArgs(st.svc).join(' ');\n const env = redactSecrets(st.svc.extraEnv);\n const envStr = Object.entries(env).map(([k, v]) => `${k}=${v}`).join(' ');\n return (\n <Box flexDirection=\"column\">\n <Text>\n {indicator} <Text color={color}>{name.padEnd(ml)}</Text> {String(st.svc.port).padStart(5)} <Text color={sc} bold={looped}>{statusLabel.padEnd(8)}</Text> {(stat?.cpu ?? '-').padStart(6)} {(stat?.mem ?? '-').padStart(8)} {String(st.errors).padStart(3)} {String(st.restarts).padStart(3)} {up.padStart(6)}\n </Text>\n <Text dimColor> cmd: {st.svc.cmd} {resolvedArgs}</Text>\n {envStr && <Text dimColor> env: {envStr}</Text>}\n </Box>\n );\n}\n\nfunction ColHeader({ ml }: { ml: number }) {\n return <Text bold>H {'Service'.padEnd(ml)} {'Port'.padStart(5)} {'Status'.padEnd(8)} {'CPU'.padStart(6)} {'Mem'.padStart(8)} Err Rst {'Up'.padStart(6)}</Text>;\n}\n\nexport function StatsPanel({ states, stats, sortMode, maxNameLen, height, focused, scrollOffset, resetScroll, verbose = false }: Props) {\n const names = [...states.keys()];\n const stObj = Object.fromEntries([...states].map(([k, v]) => [k, { errors: v.errors }]));\n const statsObj = Object.fromEntries([...stats].map(([k, v]) => [k, v]));\n\n const apis = sortServiceNames(names.filter(n => states.get(n)!.svc.type === 'api'), sortMode, statsObj, stObj);\n const webs = sortServiceNames(names.filter(n => states.get(n)!.svc.type === 'web'), sortMode, statsObj, stObj);\n\n // System stats\n const cpus = os.cpus().length;\n const totalGB = (os.totalmem() / 1024 / 1024 / 1024).toFixed(1);\n const usedGB = (parseFloat(totalGB) - os.freemem() / 1024 / 1024 / 1024).toFixed(1);\n const load = os.loadavg()[0]!.toFixed(2);\n\n // Stack totals\n let totalCpu = 0, totalMemMB = 0, totalErrors = 0, totalRestarts = 0;\n for (const name of names) {\n const s = stats.get(name);\n if (s) {\n const c = parseFloat(s.cpu); if (!isNaN(c)) totalCpu += c;\n const m = parseFloat(s.mem); if (!isNaN(m)) totalMemMB += m;\n }\n totalErrors += states.get(name)?.errors ?? 0;\n totalRestarts += states.get(name)?.restarts ?? 0;\n }\n const stackMem = totalMemMB >= 1024 ? (totalMemMB / 1024).toFixed(2) + ' GB' : totalMemMB.toFixed(1) + ' MB';\n\n const ml = maxNameLen;\n const contentHeight = Math.max(1, height - 2);\n const rowsPerCol = Math.max(1, contentHeight - 2); // header row + col header\n\n // scrollOffset = topOffset (filas por debajo de la primera, 0 = primera fila)\n const maxRows = Math.max(0, Math.max(apis.length, webs.length) - rowsPerCol);\n const effectiveOffset = scrollOffset === Number.MAX_SAFE_INTEGER\n ? maxRows\n : Math.min(scrollOffset, maxRows);\n const apiStartIndex = Math.min(effectiveOffset, Math.max(0, apis.length - rowsPerCol));\n const webStartIndex = Math.min(effectiveOffset, Math.max(0, webs.length - rowsPerCol));\n\n const visibleApis = apis.slice(apiStartIndex, apiStartIndex + rowsPerCol);\n const visibleWebs = webs.slice(webStartIndex, webStartIndex + rowsPerCol);\n\n // Reset scroll cuando cambia el modo de ordenamiento\n useEffect(() => {\n resetScroll();\n }, [sortMode, resetScroll]);\n\n const totalRowsLong = Math.max(apis.length, webs.length);\n const positionInfo = focused && totalRowsLong > 0\n ? `(${effectiveOffset + 1}-${Math.min(effectiveOffset + rowsPerCol, totalRowsLong)}/${totalRowsLong})`\n : '';\n const scrolled = effectiveOffset > 0;\n const loopedCount = [...states.values()].filter(isCrashLooped).length;\n\n // RAM pressure banner with hysteresis (80% on, 75% off).\n const ramPct = (parseFloat(usedGB) / parseFloat(totalGB)) * 100;\n const [ramBanner, setRamBanner] = useState(false);\n useEffect(() => {\n setRamBanner(prev => nextRamBannerVisibility(ramPct, prev));\n }, [ramPct]);\n\n // Top consumers when the banner is active.\n const topConsumers = ramBanner\n ? [...stats.entries()]\n .map(([n, s]) => ({ name: n, mb: parseFloat(s.mem) || 0 }))\n .sort((a, b) => b.mb - a.mb)\n .slice(0, 3)\n : [];\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={focused ? 'green' : 'gray'} height={height}>\n <Box>\n <Text bold color=\"green\"> Stats {positionInfo}</Text>\n {scrolled && <Text color=\"yellow\"> [SCROLL]</Text>}\n {loopedCount > 0 && <Text color=\"red\" bold> ⚠ {loopedCount} need attention</Text>}\n <Text dimColor> System: {cpus}c Load {load} RAM {usedGB}/{totalGB}GB</Text>\n <Text dimColor> │ </Text>\n <Text dimColor>Stack: CPU {totalCpu.toFixed(1)}% RAM {stackMem} Err {totalErrors} Rst {totalRestarts} Svcs {names.length}</Text>\n {sortMode !== 'name' && <Text dimColor> │ Sort: {sortMode}</Text>}\n </Box>\n {ramBanner && (\n <Box>\n <Text color=\"yellow\" bold> ⚠ RAM {ramPct.toFixed(0)}% — top: </Text>\n <Text color=\"yellow\">{topConsumers.map(c => `${c.name} ${c.mb.toFixed(0)}MB`).join(', ')}</Text>\n </Box>\n )}\n <Box flexGrow={1}>\n {/* Left column: APIs */}\n <Box flexDirection=\"column\" flexGrow={1} flexBasis={0}>\n <Text bold color=\"cyan\"> APIs ({apis.length})</Text>\n <ColHeader ml={ml} />\n {visibleApis.map(n => (\n <Row key={n} name={n} st={states.get(n)!} stat={stats.get(n)} ml={ml} verbose={verbose} />\n ))}\n </Box>\n {/* Separator */}\n <Box flexDirection=\"column\" width={1}>\n {Array.from({ length: contentHeight }, (_, i) => <Text key={i} dimColor>│</Text>)}\n </Box>\n {/* Right column: Webs */}\n <Box flexDirection=\"column\" flexGrow={1} flexBasis={0}>\n <Text bold color=\"magenta\"> Webs ({webs.length})</Text>\n <ColHeader ml={ml} />\n {visibleWebs.map(n => (\n <Row key={n} name={n} st={states.get(n)!} stat={stats.get(n)} ml={ml} verbose={verbose} />\n ))}\n </Box>\n </Box>\n </Box>\n );\n}\n","import { useEffect, useState } from 'react';\nimport type { Platform } from '../../platform/types.js';\nimport type { DevStackConfig, ServiceConfig } from '../../config/types.js';\nimport type { CliArgs } from '../../config/cli.js';\nimport type { ProcessManager } from '../../process/manager.js';\nimport type { ProcessState } from '../../process/types.js';\nimport { groupByPhase } from '../../utils.js';\nimport { waitForPort } from '../../process/health.js';\nimport { classifyServices, rewriteServicePort } from '../../lazy/classifier.js';\nimport { createLazyProxy, type LazyProxy } from '../../lazy/proxy.js';\nimport { startExternals, type ExternalProc } from '../../process/external.js';\n\ninterface BootRefs {\n lazyProxies: React.RefObject<Map<string, LazyProxy>>;\n externals: React.RefObject<ExternalProc[]>;\n}\n\n/** Orchestrates the boot:\n * 1. Externals first (docker compose etc.) — abort if any unhealthy.\n * 2. In lazy mode: start always-on services in phase order, register lazy\n * TCP proxies for the rest.\n * 3. In normal mode: start every service in phase order.\n *\n * Within each phase, APIs are awaited via waitForPort; webs are not. */\nexport function useBootSequence(\n manager: ProcessManager | null,\n config: DevStackConfig,\n services: ServiceConfig[],\n cliArgs: CliArgs,\n platform: Platform,\n env: Record<string, string>,\n baseCwd: string,\n refs: BootRefs,\n pushLog: (svc: string, msg: string, colorIdx?: number) => void,\n): void {\n const [booted, setBooted] = useState(false);\n\n useEffect(() => {\n if (booted || !manager) return;\n setBooted(true);\n const mgr = manager;\n\n (async () => {\n const lazyMode = cliArgs.lazy;\n const lazyTimeout = cliArgs.lazyTimeout;\n\n // External dependencies (DBs, queues, etc.) — must be healthy before phase 0.\n if (config.external?.length) {\n const result = await startExternals(config.external, {\n baseCwd, env, platform,\n onLog: (svc, msg) => pushLog(`ext:${svc}`, msg, 12),\n });\n refs.externals.current = result.procs;\n if (!result.allHealthy) {\n pushLog('devup', `❌ external(s) failed: ${result.failed.join(', ')}. Aborting boot.`, 5);\n return;\n }\n }\n\n if (lazyMode && config.lazy) {\n // ── Lazy mode ──\n const { alwaysOn, lazy } = classifyServices(services, config.lazy);\n\n // Boot always-on services normally\n const aoPhases = groupByPhase(alwaysOn);\n let colorIdx = 0;\n for (const num of Object.keys(aoPhases).map(Number).sort((a, b) => a - b)) {\n const svcs = aoPhases[num]!;\n for (const svc of svcs) {\n const ci = colorIdx++;\n await mgr.install(svc, ci);\n await mgr.start(svc, ci);\n }\n const apis = svcs.filter(s => s.type === 'api');\n if (apis.length) await Promise.all(apis.map(s => waitForPort(s.port, { timeout: 45000 })));\n svcs.filter(s => s.type === 'web').forEach(s => {\n const st = mgr.state.get(s.name);\n if (st) st.status = 'running';\n });\n }\n\n // Set up lazy proxies\n for (const svc of lazy) {\n const ci = colorIdx++;\n const rewritten = rewriteServicePort(svc);\n\n // Register as idle in process state\n const idleState: ProcessState = {\n svc: rewritten, proc: null, pid: null,\n status: 'idle', health: 'idle',\n errors: 0, restarts: 0, startedAt: null,\n intentionalStop: false, colorIdx: ci,\n };\n mgr.state.set(svc.name, idleState);\n\n const proxy = createLazyProxy({\n listenPort: svc.port,\n targetPort: rewritten.realPort,\n timeoutMin: lazyTimeout,\n onDemandStart: async () => {\n await mgr.install(rewritten, ci);\n await mgr.start(rewritten, ci);\n const ok = await waitForPort(rewritten.realPort, { timeout: 45000 });\n const st = mgr.state.get(svc.name);\n if (st) {\n st.status = ok ? 'running' : 'timeout';\n if (ok) st.health = 'up';\n }\n },\n onIdleStop: () => {\n mgr.stop(svc.name);\n const st = mgr.state.get(svc.name);\n if (st) { st.status = 'idle'; st.health = 'idle'; st.pid = null; st.proc = null; st.startedAt = null; }\n },\n isAlive: () => {\n const st = mgr.state.get(svc.name);\n return !!st && !!st.proc && !st.proc.killed && st.health === 'up';\n },\n });\n\n refs.lazyProxies.current!.set(svc.name, proxy);\n }\n } else {\n // ── Normal mode ──\n const phases = groupByPhase(services);\n let colorIdx = 0;\n for (const num of Object.keys(phases).map(Number).sort((a, b) => a - b)) {\n const svcs = phases[num]!;\n for (const svc of svcs) {\n const ci = colorIdx++;\n await mgr.install(svc, ci);\n await mgr.start(svc, ci);\n }\n const apis = svcs.filter(s => s.type === 'api');\n if (apis.length) await Promise.all(apis.map(s => waitForPort(s.port, { timeout: 45000 })));\n svcs.filter(s => s.type === 'web').forEach(s => {\n const st = mgr.state.get(s.name);\n if (st) st.status = 'running';\n });\n }\n }\n })();\n }, [booted, manager, services, cliArgs, config.lazy, config.external, baseCwd, env, platform, refs, pushLog]);\n}\n","import React, { useEffect, useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport type { LogEntry } from './hooks/useProcessManager.js';\nimport { tagColors, compileSearchPattern } from '../utils.js';\n\n/** Border color resolution rules:\n * - focused wins (cyan), so the active-pane affordance is never lost\n * - filtered + we know the service color → use it (subtle reinforcement)\n * - otherwise gray */\nexport function resolveBorder(focused: boolean, filter: string | null, filteredColorIdx: number | null): string {\n if (focused) return 'cyan';\n if (filter && filteredColorIdx !== null && filteredColorIdx >= 0) {\n return tagColors[filteredColorIdx % tagColors.length]!;\n }\n return 'gray';\n}\n\ninterface Props {\n logs: LogEntry[];\n filter: string | null;\n searchTerm: string | null;\n paused: boolean;\n showTimestamps: boolean;\n maxNameLen: number;\n height: number;\n focused: boolean;\n scrollOffset: number;\n resetScroll: () => void;\n levelFilter?: 'all' | 'error' | 'warn';\n /** When non-null, used to tint the panel border with the filtered service's tag color\n * (subtle reinforcement of \"you're seeing only this service\"). */\n filteredColorIdx?: number | null;\n}\n\nexport function LogsPanel({ logs, filter, searchTerm, paused, showTimestamps, maxNameLen, height, focused, scrollOffset, resetScroll, levelFilter = 'all', filteredColorIdx = null }: Props) {\n const byService = filter ? logs.filter(l => l.svcName === filter) : logs;\n const filtered = levelFilter === 'all'\n ? byService\n : levelFilter === 'error'\n ? byService.filter(l => l.level === 'error')\n : byService.filter(l => l.level === 'error' || l.level === 'warn');\n const contentHeight = Math.max(1, height - 2);\n const totalLines = filtered.length;\n\n // scrollOffset = \"líneas por encima del fondo\": 0 = follow latest, N = N líneas atrás.\n const maxOffset = Math.max(0, totalLines - contentHeight);\n const effectiveOffset = scrollOffset === Number.MAX_SAFE_INTEGER\n ? maxOffset\n : Math.min(scrollOffset, maxOffset);\n const startIndex = Math.max(0, totalLines - contentHeight - effectiveOffset);\n const endIndex = Math.min(startIndex + contentHeight, totalLines);\n const visible = filtered.slice(startIndex, endIndex);\n\n // Reset scroll cuando cambia el filtro o búsqueda — vuelve a seguir lo último.\n useEffect(() => {\n resetScroll();\n }, [filter, searchTerm, resetScroll]);\n\n const matcher = useMemo(() => compileSearchPattern(searchTerm), [searchTerm]);\n\n const scrolled = effectiveOffset > 0;\n const label = [\n 'Logs',\n filter ? `[${filter}]` : '',\n searchTerm ? `/${searchTerm}` : '',\n matcher?.invalid ? '(invalid regex)' : '',\n levelFilter !== 'all' ? `[level: ${levelFilter}${levelFilter === 'warn' ? '+error' : ''}]` : '',\n paused ? '[PAUSED]' : '',\n scrolled ? '[SCROLL]' : '',\n `${filtered.length} lines`,\n focused && totalLines > 0 ? `(${startIndex + 1}-${endIndex}/${totalLines})` : '',\n ].filter(Boolean).join(' ');\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={resolveBorder(focused, filter, filteredColorIdx)} height={height}>\n <Box><Text bold color=\"cyan\"> {label} </Text></Box>\n {visible.map((entry, i) => {\n const color = tagColors[entry.colorIdx % tagColors.length]!;\n const ts = showTimestamps ? new Date(entry.ts).toLocaleTimeString('en-GB') + ' ' : '';\n const line = entry.text;\n const isMatch = matcher ? matcher.test(line) : false;\n return (\n <Box key={i}>\n {showTimestamps && <Text dimColor>{ts}</Text>}\n <Text color={color}>[{entry.svcName.padEnd(maxNameLen)}]</Text>\n <Text> </Text>\n {isMatch ? <Text backgroundColor=\"yellow\" color=\"black\">{line}</Text> : <Text>{line}</Text>}\n </Box>\n );\n })}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nexport function StatusBar() {\n return (\n <Box>\n <Text>\n <Text bold>q</Text> Quit <Text bold>Tab</Text> Switch <Text bold>↑↓</Text> Scroll <Text bold>PgUp/PgDn</Text> Page <Text bold>Ctrl+A/E</Text> Home/End <Text bold>c</Text> Clear <Text bold>f</Text> Filter <Text bold>L</Text> Level <Text bold>a</Text> All <Text bold>r</Text> Restart <Text bold>/</Text> Search <Text bold>s</Text> Sort <Text bold>o</Text> Open <Text bold>p</Text> Pause <Text bold>t</Text> Time <Text bold>v</Text> Verbose <Text bold>T</Text> Proxy\n </Text>\n </Box>\n );\n}\n","import React, { useState, useMemo } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { ProcessState } from '../process/types.js';\n\ninterface Props {\n title: string;\n services: Map<string, ProcessState>;\n onSelect: (name: string) => void;\n onClose: () => void;\n filterType?: 'api' | 'web';\n}\n\nexport function ServiceList({ title, services, onSelect, onClose, filterType }: Props) {\n const allNames = useMemo(\n () => [...services.keys()].filter(n => !filterType || services.get(n)!.svc.type === filterType),\n [services, filterType],\n );\n const [idx, setIdx] = useState(0);\n const [query, setQuery] = useState('');\n\n const names = useMemo(() => {\n if (!query) return allNames;\n const q = query.toLowerCase();\n return allNames.filter(n => n.toLowerCase().includes(q));\n }, [allNames, query]);\n\n // Clamp selected index when the list shrinks\n const clamped = Math.min(idx, Math.max(0, names.length - 1));\n\n useInput((input, key) => {\n if (key.escape) {\n if (query) setQuery(''); // first Esc clears filter\n else onClose(); // second Esc closes\n return;\n }\n if (key.return) {\n if (names[clamped]) onSelect(names[clamped]!);\n return;\n }\n if (key.upArrow) { setIdx(i => Math.max(0, i - 1)); return; }\n if (key.downArrow) { setIdx(i => Math.min(names.length - 1, i + 1)); return; }\n if (key.backspace || key.delete) { setQuery(q => q.slice(0, -1)); setIdx(0); return; }\n if (input && !key.ctrl && !key.meta && input.length === 1) {\n setQuery(q => q + input);\n setIdx(0);\n }\n }, { isActive: process.stdin.isTTY ?? false });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\"> {title} {query && <Text color=\"yellow\">[{query}]</Text>}</Text>\n {names.length === 0 ? (\n <Text dimColor> (no matches) </Text>\n ) : (\n names.map((name, i) => (\n <Box key={name}>\n <Text color={i === clamped ? 'cyan' : undefined} inverse={i === clamped}> {name} :{services.get(name)!.svc.port} </Text>\n </Box>\n ))\n )}\n <Text dimColor>type to filter ↑↓ navigate Enter select Esc clear/close</Text>\n </Box>\n );\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\n\ninterface Props {\n onSubmit: (term: string | null) => void;\n onClose: () => void;\n}\n\nexport function SearchInput({ onSubmit, onClose }: Props) {\n const [value, setValue] = useState('');\n\n useInput((input, key) => {\n if (key.escape) onClose();\n else if (key.return) onSubmit(value.trim() || null);\n else if (key.backspace || key.delete) setValue(v => v.slice(0, -1));\n else if (input && !key.ctrl && !key.meta) setValue(v => v + input);\n }, { isActive: process.stdin.isTTY ?? false });\n\n return (\n <Box borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text bold color=\"yellow\">Search: </Text>\n <Text>{value}</Text>\n <Text dimColor>█</Text>\n </Box>\n );\n}\n","import type { DevStackConfig, ServiceConfig } from '../config/types.js';\nimport type { CliArgs } from '../config/cli.js';\nimport type { ProxyConfigProvider, ProxyOpts } from '../proxy-config/types.js';\nimport type { ServiceState } from '../proxy-config/types.js';\nimport { groupByPhase, buildProcessArgs, buildProcessEnv } from '../utils.js';\nimport { classifyServices, rewriteServicePort, getLazyRealPort } from '../lazy/classifier.js';\n\nexport interface DryRunOpts {\n config: DevStackConfig;\n services: ServiceConfig[];\n cliArgs: CliArgs;\n env: Record<string, string>;\n baseCwd: string;\n proxyProvider: ProxyConfigProvider | null;\n proxyOpts: ProxyOpts | null;\n}\n\nexport function renderDryRun(opts: DryRunOpts): string {\n const { config, services, cliArgs, env, proxyProvider, proxyOpts } = opts;\n const lines: string[] = [];\n\n lines.push(`Project: ${config.icon ?? '📦'} ${config.name}`);\n lines.push(`Mode: ${cliArgs.lazy && config.lazy ? 'lazy' : 'normal'}`);\n if (cliArgs.profile) lines.push(`Profile: ${cliArgs.profile}`);\n lines.push(`Services: ${services.length}`);\n lines.push('');\n\n if (config.external?.length) {\n lines.push(`Externals (${config.external.length}):`);\n for (const ext of config.external) {\n const hc = ext.healthCheck;\n const hcTag = hc\n ? ` health=${hc.type}${hc.type === 'http' ? ' ' + (hc.path ?? '/') : ''} :${ext.port ?? '?'}`\n : '';\n lines.push(` - ${ext.name.padEnd(20)} ${ext.cmd}${hcTag}`);\n }\n lines.push('');\n }\n\n const lazyMode = cliArgs.lazy && !!config.lazy;\n let alwaysOn: ServiceConfig[] = services;\n let lazy: ServiceConfig[] = [];\n if (lazyMode) {\n const c = classifyServices(services, config.lazy!);\n alwaysOn = c.alwaysOn;\n lazy = c.lazy;\n }\n\n const phases = groupByPhase(alwaysOn);\n const phaseNums = Object.keys(phases).map(Number).sort((a, b) => a - b);\n for (const num of phaseNums) {\n lines.push(`Phase ${num}:`);\n for (const svc of phases[num]!) {\n lines.push(formatService(svc, env, false));\n }\n }\n\n if (lazy.length) {\n lines.push('');\n lines.push('Lazy (on-demand):');\n for (const svc of lazy) {\n const rewritten = rewriteServicePort(svc);\n lines.push(formatService(rewritten, env, true));\n lines.push(` proxy :${svc.port} → :${getLazyRealPort(svc.port)} (idle timeout ${cliArgs.lazyTimeout}m)`);\n }\n }\n\n if (proxyProvider && proxyOpts) {\n lines.push('');\n lines.push(`Proxy: ${proxyProvider.name} → ${proxyOpts.confPath}`);\n // Simulamos todas las rutas como \"up\" para mostrar el output\n const svcStates = new Map<string, ServiceState>();\n for (const svc of services) {\n const real = lazyMode && !alwaysOn.includes(svc) ? getLazyRealPort(svc.port) : undefined;\n svcStates.set(svc.name, { port: svc.port, health: 'up', realPort: real });\n }\n const content = proxyProvider.generate(svcStates, proxyOpts);\n lines.push('');\n lines.push('--- generated config ---');\n lines.push(content);\n }\n\n return lines.join('\\n');\n}\n\nfunction formatService(svc: ServiceConfig, env: Record<string, string>, isLazy: boolean): string {\n const args = buildProcessArgs(svc);\n const cmdLine = [svc.cmd, ...args].join(' ');\n const built = buildProcessEnv(svc, env);\n const extraEnv = Object.keys(svc.extraEnv ?? {}).length\n ? ' env=' + Object.entries(svc.extraEnv!).map(([k, v]) => `${k}=${v}`).join(' ')\n : '';\n const memTag = svc.maxMem ? ` mem=${svc.maxMem}MB` : '';\n const hc = svc.healthCheck;\n const hcTag = hc?.type === 'http' ? ` health=http ${hc.path ?? '/'}` : '';\n const lazyTag = isLazy ? ' [lazy]' : '';\n void built;\n return ` - ${svc.name.padEnd(20)} (${svc.type}) :${svc.port} ${cmdLine}${memTag}${hcTag}${lazyTag}${extraEnv}`;\n}\n\nexport function runDryRun(opts: DryRunOpts): void {\n // eslint-disable-next-line no-console\n console.log(renderDryRun(opts));\n}\n","import { ProcessManager } from '../process/manager.js';\nimport { checkHealth } from '../process/health.js';\nimport { groupByPhase } from '../utils.js';\nimport type { DevStackConfig, ServiceConfig } from '../config/types.js';\nimport type { CliArgs } from '../config/cli.js';\nimport type { Platform } from '../platform/types.js';\nimport type { LogSink } from '../process/log-sink.js';\nimport { startExternals, stopExternals, type ExternalProc } from '../process/external.js';\n\nexport interface OnceOpts {\n config: DevStackConfig;\n services: ServiceConfig[];\n cliArgs: CliArgs;\n platform: Platform;\n env: Record<string, string>;\n baseCwd: string;\n logSink: LogSink | null;\n /** For testing: override stdout. */\n out?: (line: string) => void;\n}\n\n/** Boots services phase-by-phase, waits until each API is healthy, then returns.\n * Returns 0 if everything came up within onceTimeout, 1 otherwise. */\nexport async function runOnce(opts: OnceOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => console.log(l));\n const { config, services, cliArgs, platform, env, baseCwd, logSink } = opts;\n\n const mgr = new ProcessManager({\n baseCwd, env, platform,\n events: {\n onLog: (svc, text) => { logSink?.write(svc, text); out(`[${svc}] ${text}`); },\n onStateChange: () => {},\n },\n });\n\n // External dependencies (DBs, queues, etc.) before phase 0.\n let externals: ExternalProc[] = [];\n if (config.external?.length) {\n out(`▶ externals (${config.external.length})`);\n const result = await startExternals(config.external, {\n baseCwd, env, platform,\n onLog: (svc, msg) => { logSink?.write(`ext:${svc}`, msg); out(`[ext:${svc}] ${msg}`); },\n });\n externals = result.procs;\n if (!result.allHealthy) {\n out(`✗ externals failed: ${result.failed.join(', ')}`);\n await stopExternals(externals, platform, { baseCwd, env });\n await mgr.cleanup();\n return 1;\n }\n }\n\n const phases = groupByPhase(services);\n const phaseNums = Object.keys(phases).map(Number).sort((a, b) => a - b);\n const apiNames = services.filter(s => s.type === 'api').map(s => s.name);\n const deadline = Date.now() + cliArgs.onceTimeout * 1000;\n let colorIdx = 0;\n\n for (const num of phaseNums) {\n out(`▶ phase ${num}`);\n for (const svc of phases[num]!) {\n const ci = colorIdx++;\n const installed = await mgr.install(svc, ci);\n if (!installed) {\n out(`✗ install failed for ${svc.name}`);\n await mgr.cleanup();\n await stopExternals(externals, platform, { baseCwd, env });\n return 1;\n }\n await mgr.start(svc, ci);\n }\n\n // Wait for all APIs in this phase\n const apis = phases[num]!.filter(s => s.type === 'api');\n for (const api of apis) {\n const ok = await waitHealthy(api, deadline);\n if (!ok) {\n out(`✗ ${api.name} did not become healthy within ${cliArgs.onceTimeout}s`);\n await mgr.cleanup();\n await stopExternals(externals, platform, { baseCwd, env });\n return 1;\n }\n out(`✓ ${api.name} ready`);\n const st = mgr.state.get(api.name);\n if (st) { st.status = 'running'; st.health = 'up'; }\n }\n }\n\n const summary = `ready: ${apiNames.length} APIs in ${((cliArgs.onceTimeout * 1000 - (deadline - Date.now())) / 1000).toFixed(1)}s`;\n out(summary);\n await mgr.cleanup();\n await stopExternals(externals, platform, { baseCwd, env });\n return 0;\n}\n\nasync function waitHealthy(svc: ServiceConfig, deadline: number): Promise<boolean> {\n while (Date.now() < deadline) {\n const ok = await checkHealth(svc.port, svc.healthCheck);\n if (ok) return true;\n await new Promise(r => setTimeout(r, 500));\n }\n return false;\n}\n","export interface ServiceConfig {\n name: string;\n cwd: string;\n cmd: string;\n args: string[];\n type: 'api' | 'web';\n port: number;\n phase: number;\n maxMem?: number;\n preBuild?: string;\n watchBuild?: string;\n nodeArgs?: string[];\n extraEnv?: Record<string, string>;\n healthCheck?: HealthCheckConfig;\n /** Case-insensitive regex. When a line of the service's stdout/stderr matches,\n * the service is immediately marked as `up` without waiting for the next\n * health-check poll. Speeds up phase transitions on cold boots.\n * Examples: '/ready in \\\\d+ ms/' (Vite), '/compiled successfully/' (Angular). */\n readyPattern?: string;\n /** Case-insensitive regex. When set, only stderr lines matching this pattern\n * bump `state.errors`. Without it, every non-empty stderr line counts.\n * Useful for libraries that write info messages to stderr (Angular CLI). */\n errorPattern?: string;\n}\n\nexport interface HealthCheckConfig {\n /** 'tcp' (default) checks that the port accepts connections. 'http' makes an HTTP GET. */\n type: 'tcp' | 'http';\n /** HTTP-only: request path. Default: '/' */\n path?: string;\n /** HTTP-only: acceptable status code(s). Default: 200-299 */\n expect?: number | number[];\n /** Override host for the HTTP check. Default: 127.0.0.1 */\n host?: string;\n /** Per-check socket timeout in ms. Default: 2000 */\n timeoutMs?: number;\n /** Grace period (seconds) before the first probe runs. Useful for slow boots\n * (Angular cold-start, big webpack builds) so failed probes during boot don't\n * pollute state.errors. Default: 0 (no grace). */\n startPeriod?: number;\n}\n\nexport interface LazyConfig {\n alwaysOn: string[];\n timeout?: number;\n}\n\nexport interface ProxyConfig {\n provider: string;\n routes: Record<string, string>;\n confPath?: string;\n host?: string;\n tls?: boolean;\n entrypoint?: string;\n}\n\nexport interface ExternalService {\n /** Friendly name (used in logs and the stats panel). Must be unique within `external`. */\n name: string;\n /** Shell command to start. Will be passed through `sh -c` / `cmd /c`. */\n cmd: string;\n /** Optional working directory (relative to the project root). */\n cwd?: string;\n /** Extra env vars merged on top of the project env. */\n extraEnv?: Record<string, string>;\n /** Optional readiness probe. devup waits for this to return `up` before starting phase 0. */\n healthCheck?: HealthCheckConfig;\n /** Port to probe when `healthCheck` is set. Required for tcp checks. */\n port?: number;\n /** Max seconds to wait for healthCheck to pass before giving up. Default: 60. */\n startTimeout?: number;\n /** Optional shell command run on shutdown (e.g. `docker compose down`). */\n stopCmd?: string;\n}\n\nexport interface DevStackConfig {\n name: string;\n icon?: string;\n envFile?: string;\n env?: Record<string, string>;\n services: ServiceConfig[];\n lazy?: LazyConfig;\n proxy?: ProxyConfig;\n /** Named lists of service names — selectable with --profile <name>. */\n profiles?: Record<string, string[]>;\n /** Optional external dependencies (DBs, queues) started before phase 0. */\n external?: ExternalService[];\n}\n\nexport function defineConfig(config: DevStackConfig): DevStackConfig {\n return config;\n}\n"],"mappings":";;;AAAA,OAAOA,YAAW;AAClB,SAAS,cAAc;AACvB,SAAS,gBAAAC,eAAc,oBAAoB;AAC3C,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAC9B,SAAS,iBAAAC,sBAAqB;AAC9B,SAAS,WAAAC,gBAAe;;;ACLxB,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAG9B,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,eAAe,KAAa,UAA2B;AACrE,MAAI,UAAU;AACZ,UAAM,OAAO,QAAQ,KAAK,QAAQ;AAClC,QAAI,CAAC,WAAW,IAAI,EAAG,OAAM,IAAI,MAAM,qBAAqB,IAAI,EAAE;AAClE,WAAO;AAAA,EACT;AACA,aAAW,QAAQ,cAAc;AAC/B,UAAM,OAAO,KAAK,KAAK,IAAI;AAC3B,QAAI,WAAW,IAAI,EAAG,QAAO;AAAA,EAC/B;AACA,QAAM,IAAI;AAAA,IACR,mCAAmC,aAAa,KAAK,IAAI,CAAC;AAAA;AAAA,EAE5D;AACF;AAEA,eAAsB,WAAW,YAA6C;AAC5E,MAAI,WAAW,SAAS,OAAO,GAAG;AAChC,UAAM,MAAM,MAAM,SAAS,YAAY,MAAM;AAC7C,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB;AAGA,QAAM,MAAM,cAAc,UAAU,EAAE;AACtC,QAAM,MAAM,MAAM,OAAO;AACzB,QAAM,SAAS,IAAI,WAAW;AAE9B,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,OAAO,QAAQ,GAAG;AAC5E,UAAM,IAAI,MAAM,uFAAuF;AAAA,EACzG;AAEA,SAAO;AACT;;;AC5CA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,WAAAC,gBAAe;;;ACCjB,IAAM,mBAAmB;AAQzB,SAAS,iBAAiB,UAA2B,QAAyC;AACnG,QAAM,cAAc,IAAI,IAAI,QAAQ,YAAY,CAAC,CAAC;AAClD,QAAM,WAA4B,CAAC;AACnC,QAAM,OAAwB,CAAC;AAE/B,aAAW,OAAO,UAAU;AAC1B,QAAI,YAAY,IAAI,IAAI,IAAI,EAAG,UAAS,KAAK,GAAG;AAAA,QAC3C,MAAK,KAAK,GAAG;AAAA,EACpB;AACA,SAAO,EAAE,UAAU,KAAK;AAC1B;AAEO,SAAS,gBAAgB,cAA8B;AAC5D,SAAO,eAAe;AACxB;AAEO,SAAS,mBAAmB,KAAgF;AACjH,QAAM,WAAW,gBAAgB,IAAI,IAAI;AACzC,QAAM,OAAO,IAAI,KAAK,IAAI,OAAK,MAAM,OAAO,IAAI,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC;AAC5E,QAAM,WAAW,EAAE,GAAG,IAAI,UAAU,eAAe,OAAO,QAAQ,EAAE;AACpE,SAAO,EAAE,GAAG,KAAK,MAAM,UAAU,MAAM,UAAU,UAAU,cAAc,IAAI,KAAK;AACpF;;;ADbO,SAAS,gBAAgB,QAA6C;AAC3E,QAAM,WAAgC,CAAC;AACvC,MAAI,CAAC,OAAO,UAAU,OAAQ,QAAO;AAErC,aAAW,OAAO,OAAO,UAAU;AAGjC,UAAM,KAAK,IAAI,WAAW,MAAM;AAChC,QAAI,OAAO,QAAW;AACpB,YAAM,WAAW,OAAO,IAAI,IAAI;AAChC,UAAI,OAAO,UAAU;AACnB,iBAAS,KAAK;AAAA,UACZ,OAAO,YAAY,IAAI,IAAI;AAAA,UAC3B,SAAS,kBAAkB,EAAE,yBAAyB,IAAI,IAAI,8BAA8B,IAAI,IAAI,2CAA2C,EAAE;AAAA,QACnJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,yBAAyB,UAAuC;AAC9E,SAAO,SAAS,IAAI,OAAK,YAAO,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AACpE;AAEO,SAAS,eAAe,QAAwB,KAAgC;AACrF,QAAM,SAA4B,CAAC;AAEnC,MAAI,CAAC,OAAO,MAAM,KAAK,GAAG;AACxB,WAAO,KAAK,EAAE,OAAO,QAAQ,SAAS,2BAA2B,CAAC;AAAA,EACpE;AAEA,MAAI,CAAC,OAAO,UAAU,QAAQ;AAC5B,WAAO,KAAK,EAAE,OAAO,YAAY,SAAS,mCAAmC,CAAC;AAC9E,WAAO;AAAA,EACT;AAGA,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,OAAO,OAAO,UAAU;AACjC,QAAI,MAAM,IAAI,IAAI,IAAI,GAAG;AACvB,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,2BAA2B,IAAI,IAAI,GAAG,CAAC;AAAA,IACrG;AACA,UAAM,IAAI,IAAI,IAAI;AAAA,EACpB;AAGA,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,OAAO,OAAO,UAAU;AACjC,UAAM,WAAW,MAAM,IAAI,IAAI,IAAI;AACnC,QAAI,UAAU;AACZ,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,QAAQ,IAAI,IAAI,oBAAoB,QAAQ,GAAG,CAAC;AAAA,IAC9G;AACA,UAAM,IAAI,IAAI,MAAM,IAAI,IAAI;AAAA,EAC9B;AAGA,aAAW,OAAO,OAAO,UAAU;AACjC,QAAI,CAAC,IAAI,MAAM,KAAK,EAAG,QAAO,KAAK,EAAE,OAAO,mBAAmB,SAAS,2BAA2B,CAAC;AACpG,QAAI,CAAC,IAAI,KAAK,KAAK,EAAG,QAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,SAAS,SAAS,kBAAkB,CAAC;AACpG,QAAI,CAAC,IAAI,KAAK,KAAK,EAAG,QAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,SAAS,SAAS,kBAAkB,CAAC;AACpG,QAAI,CAAC,IAAI,QAAQ,CAAC,CAAC,OAAO,KAAK,EAAE,SAAS,IAAI,IAAI,GAAG;AACnD,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,iBAAiB,IAAI,IAAI,4BAA4B,CAAC;AAAA,IACpH;AACA,QAAI,OAAO,IAAI,SAAS,YAAY,IAAI,QAAQ,GAAG;AACjD,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,iBAAiB,IAAI,IAAI,GAAG,CAAC;AAAA,IAC3F;AACA,QAAI,OAAO,IAAI,UAAU,YAAY,IAAI,QAAQ,GAAG;AAClD,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,WAAW,SAAS,kBAAkB,IAAI,KAAK,GAAG,CAAC;AAAA,IAC9F;AAGA,QAAI,IAAI,OAAO,CAACC,YAAWC,SAAQ,KAAK,IAAI,GAAG,CAAC,GAAG;AACjD,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,SAAS,SAAS,wBAAwB,IAAI,GAAG,GAAG,CAAC;AAAA,IAChG;AAGA,QAAI,IAAI,iBAAiB,QAAW;AAClC,UAAI,OAAO,IAAI,iBAAiB,YAAY,CAAC,IAAI,aAAa,QAAQ;AACpE,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,kBAAkB,SAAS,0CAA0C,CAAC;AAAA,MACjH,OAAO;AACL,cAAM,UAAU,wBAAwB,KAAK,IAAI,YAAY;AAC7D,YAAI;AACF,cAAI,QAAS,KAAI,OAAO,QAAQ,CAAC,GAAI,QAAQ,CAAC,KAAK,GAAG;AAAA,cACjD,KAAI,OAAO,IAAI,cAAc,GAAG;AAAA,QACvC,SAAS,GAAQ;AACf,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,kBAAkB,SAAS,kBAAkB,EAAE,OAAO,GAAG,CAAC;AAAA,QACrG;AAAA,MACF;AAAA,IACF;AAGA,QAAI,IAAI,iBAAiB,QAAW;AAClC,UAAI,OAAO,IAAI,iBAAiB,YAAY,CAAC,IAAI,aAAa,QAAQ;AACpE,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,kBAAkB,SAAS,0CAA0C,CAAC;AAAA,MACjH,OAAO;AACL,cAAM,UAAU,wBAAwB,KAAK,IAAI,YAAY;AAC7D,YAAI;AACF,cAAI,QAAS,KAAI,OAAO,QAAQ,CAAC,GAAI,QAAQ,CAAC,KAAK,GAAG;AAAA,cACjD,KAAI,OAAO,IAAI,cAAc,GAAG;AAAA,QACvC,SAAS,GAAQ;AACf,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,kBAAkB,SAAS,kBAAkB,EAAE,OAAO,GAAG,CAAC;AAAA,QACrG;AAAA,MACF;AAAA,IACF;AAGA,QAAI,IAAI,aAAa,WAAc,OAAO,IAAI,aAAa,YAAY,CAAC,IAAI,SAAS,KAAK,IAAI;AAC5F,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,cAAc,SAAS,sCAAsC,CAAC;AAAA,IACzG;AACA,QAAI,IAAI,eAAe,WAAc,OAAO,IAAI,eAAe,YAAY,CAAC,IAAI,WAAW,KAAK,IAAI;AAClG,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,gBAAgB,SAAS,wCAAwC,CAAC;AAAA,IAC7G;AAGA,QAAI,IAAI,aAAa;AACnB,YAAM,KAAK,IAAI;AACf,UAAI,GAAG,SAAS,SAAS,GAAG,SAAS,QAAQ;AAC3C,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,sBAAsB,SAAS,6BAA6B,GAAG,IAAI,6BAA6B,CAAC;AAAA,MAC5I;AACA,UAAI,GAAG,gBAAgB,WAAc,OAAO,GAAG,gBAAgB,YAAY,GAAG,cAAc,IAAI;AAC9F,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,6BAA6B,SAAS,4DAA4D,GAAG,WAAW,GAAG,CAAC;AAAA,MAC/J;AACA,UAAI,GAAG,SAAS,UAAU,GAAG,QAAQ,CAAC,GAAG,KAAK,WAAW,GAAG,GAAG;AAC7D,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,sBAAsB,SAAS,8CAA8C,GAAG,IAAI,IAAI,CAAC;AAAA,MACpI;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,MAAM,UAAU;AACzB,eAAW,OAAO,OAAO,KAAK,UAAU;AACtC,UAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,eAAO,KAAK,EAAE,OAAO,iBAAiB,SAAS,oBAAoB,GAAG,GAAG,CAAC;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,MAAM;AACf,UAAM,WAAW,IAAI,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC;AACnD,UAAM,YAAY,oBAAI,IAAoB;AAC1C,eAAW,OAAO,OAAO,SAAU,WAAU,IAAI,IAAI,MAAM,IAAI,IAAI;AACnE,eAAW,OAAO,OAAO,UAAU;AACjC,UAAI,SAAS,IAAI,IAAI,IAAI,EAAG;AAC5B,YAAM,WAAW,IAAI,OAAO;AAC5B,YAAM,WAAW,UAAU,IAAI,QAAQ;AACvC,UAAI,YAAY,aAAa,IAAI,MAAM;AACrC,eAAO,KAAK;AAAA,UACV,OAAO,YAAY,IAAI,IAAI;AAAA,UAC3B,SAAS,kBAAkB,QAAQ,OAAO,IAAI,IAAI,IAAI,gBAAgB,2BAA2B,QAAQ;AAAA,QAC3G,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,UAAU;AACnB,UAAM,WAAW,oBAAI,IAAY;AACjC,eAAW,OAAO,OAAO,UAAU;AACjC,UAAI,CAAC,IAAI,MAAM,KAAK,GAAG;AACrB,eAAO,KAAK,EAAE,OAAO,mBAAmB,SAAS,oCAAoC,CAAC;AACtF;AAAA,MACF;AACA,UAAI,SAAS,IAAI,IAAI,IAAI,GAAG;AAC1B,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,4BAA4B,IAAI,IAAI,GAAG,CAAC;AAAA,MACtG;AACA,eAAS,IAAI,IAAI,IAAI;AACrB,UAAI,CAAC,IAAI,KAAK,KAAK,GAAG;AACpB,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,SAAS,SAAS,kBAAkB,CAAC;AAAA,MAChF;AACA,UAAI,IAAI,aAAa;AACnB,cAAM,KAAK,IAAI;AACf,YAAI,GAAG,SAAS,SAAS,GAAG,SAAS,QAAQ;AAC3C,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,sBAAsB,SAAS,6BAA6B,GAAG,IAAI,GAAG,CAAC;AAAA,QAClH;AACA,aAAK,GAAG,SAAS,SAAS,GAAG,SAAS,YAAY,OAAO,IAAI,SAAS,YAAY,IAAI,QAAQ,IAAI;AAChG,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,iDAAiD,IAAI,IAAI,IAAI,CAAC;AAAA,QAC5H;AACA,YAAI,GAAG,SAAS,UAAU,GAAG,QAAQ,CAAC,GAAG,KAAK,WAAW,GAAG,GAAG;AAC7D,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,sBAAsB,SAAS,sBAAsB,CAAC;AAAA,QACjG;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,OAAO,QAAQ;AACxB,eAAW,OAAO,OAAO,KAAK,OAAO,MAAM,MAAM,GAAG;AAClD,UAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,eAAO,KAAK,EAAE,OAAO,gBAAgB,SAAS,oBAAoB,GAAG,GAAG,CAAC;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,UAAU;AACnB,eAAW,CAAC,SAAS,QAAQ,KAAK,OAAO,QAAQ,OAAO,QAAQ,GAAG;AACjE,UAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,SAAS,QAAQ;AAChD,eAAO,KAAK,EAAE,OAAO,YAAY,OAAO,IAAI,SAAS,YAAY,OAAO,+CAA+C,CAAC;AACxH;AAAA,MACF;AACA,iBAAW,OAAO,UAAU;AAC1B,YAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,iBAAO,KAAK,EAAE,OAAO,YAAY,OAAO,IAAI,SAAS,oBAAoB,GAAG,GAAG,CAAC;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,uBAAuB,QAAmC;AACxE,SAAO,OAAO,IAAI,OAAK,YAAO,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAClE;;;AEjNA,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAEtB,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgDd,SAAS,aAAa,MAAyB;AACpD,QAAM,OAAgB;AAAA,IACpB,MAAM,CAAC;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,aAAa;AAAA,IACb,mBAAmB;AAAA,EACrB;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,OAAO,KAAK,IAAI,CAAC;AAEvB,YAAQ,KAAK;AAAA,MACX,KAAK;AAAgB,aAAK,aAAa;AAAM;AAAK;AAAA,MAClD,KAAK;AAAgB,aAAK,OAAO;AAAM;AAAK;AAAA,MAC5C,KAAK;AAAgB,aAAK,OAAO,MAAM,MAAM,GAAG,KAAK,CAAC;AAAG;AAAK;AAAA,MAC9D,KAAK;AAAgB,aAAK,WAAW,MAAM,MAAM,GAAG;AAAG;AAAK;AAAA,MAC5D,KAAK;AAAgB,aAAK,UAAU;AAAM;AAAK;AAAA,MAC/C,KAAK;AAAgB,aAAK,OAAO;AAAM;AAAA,MACvC,KAAK;AAAgB,aAAK,OAAO;AAAO;AAAA,MACxC,KAAK;AAAgB,aAAK,cAAc,SAAS,QAAQ,IAAI,EAAE,KAAK;AAAsB;AAAK;AAAA,MAC/F,KAAK;AAAgB,aAAK,QAAQ;AAAM;AAAA,MACxC,KAAK;AAAsB,aAAK,YAAY;AAAM;AAAK;AAAA,MACvD,KAAK;AAAsB,aAAK,YAAY;AAAM;AAAK;AAAA,MACvD,KAAK;AAAsB,aAAK,WAAW;AAAM;AAAA,MACjD,KAAK;AAAsB,aAAK,WAAW;AAAO;AAAA,MAClD,KAAK;AAAsB,aAAK,kBAAkB,QAAQ;AAAa;AAAK;AAAA,MAC5E,KAAK;AAAsB,aAAK,SAAS;AAAM;AAAA,MAC/C,KAAK;AAAsB,aAAK,OAAO;AAAM;AAAA,MAC7C,KAAK;AAAsB,aAAK,cAAc,SAAS,QAAQ,IAAI,EAAE,KAAK;AAAsB;AAAK;AAAA,MACrG,KAAK;AAAsB,aAAK,UAAU;AAAO;AAAA,MACjD,KAAK;AAAsB,aAAK,SAAS;AAAM;AAAK;AAAA,MACpD,KAAK;AAAsB,aAAK,cAAc;AAAM;AAAA,MACpD,KAAK;AAAyB,aAAK,oBAAoB;AAAM;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,eACd,UACA,MACA,QACiB;AACjB,MAAI,SAAS;AAEb,MAAI,KAAK,SAAS;AAChB,UAAM,eAAe,QAAQ,WAAW,KAAK,OAAO;AACpD,QAAI,CAAC,cAAc;AACjB,YAAM,YAAY,OAAO,KAAK,QAAQ,YAAY,CAAC,CAAC;AACpD,YAAM,OAAO,UAAU,SAAS,cAAc,UAAU,KAAK,IAAI,CAAC,KAAK;AACvE,YAAM,IAAI,MAAM,qBAAqB,KAAK,OAAO,MAAM,IAAI,EAAE;AAAA,IAC/D;AACA,UAAM,MAAM,IAAI,IAAI,YAAY;AAChC,aAAS,OAAO,OAAO,OAAK,IAAI,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7C,WAAW,KAAK,UAAU;AACxB,UAAM,WAAW,IAAI,IAAI,KAAK,QAAQ;AACtC,aAAS,OAAO,OAAO,OAAK,SAAS,IAAI,EAAE,IAAI,CAAC;AAAA,EAClD,WAAW,KAAK,MAAM;AACpB,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AAAQ,iBAAS,OAAO,OAAO,OAAK,EAAE,SAAS,KAAK;AAAG;AAAA,MAC5D,KAAK;AAAQ,iBAAS,OAAO,OAAO,OAAK,EAAE,SAAS,KAAK;AAAG;AAAA,MAC5D;AAAa,iBAAS,OAAO,OAAO,OAAK,EAAE,KAAK,WAAW,KAAK,IAAK,CAAC;AAAG;AAAA,IAC3E;AAAA,EACF;AAEA,MAAI,KAAK,KAAK,QAAQ;AACpB,UAAM,UAAU,IAAI,IAAI,KAAK,IAAI;AACjC,aAAS,OAAO,OAAO,OAAK,CAAC,QAAQ,IAAI,EAAE,IAAI,CAAC;AAAA,EAClD;AAEA,SAAO;AACT;;;AC5JA,SAAS,SAAAC,cAAa;AACtB,SAAS,oBAAAC,mBAAkB,aAAAC,YAAW,eAAAC,cAAa,cAAAC,cAAY,YAAAC,iBAAgB;AAC/E,SAAS,YAAAC,iBAAgB;AACzB,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,WAAAC,gBAAe;AACxB,SAAS,mBAAAC,wBAAuB;;;ACNhC,OAAO,SAAS;AAChB,OAAO,UAAU;AASV,SAAS,UAAU,MAAc,OAAO,aAAa,YAAY,KAAwB;AAC9F,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAC5B,UAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,WAAO,WAAW,SAAS;AAC3B,WAAO,KAAK,WAAW,MAAM;AAAE,aAAO,QAAQ;AAAG,MAAAA,SAAQ,IAAI;AAAA,IAAG,CAAC;AACjE,WAAO,KAAK,SAAS,MAAM;AAAE,aAAO,QAAQ;AAAG,MAAAA,SAAQ,KAAK;AAAA,IAAG,CAAC;AAChE,WAAO,KAAK,WAAW,MAAM;AAAE,aAAO,QAAQ;AAAG,MAAAA,SAAQ,KAAK;AAAA,IAAG,CAAC;AAClE,WAAO,QAAQ,MAAM,IAAI;AAAA,EAC3B,CAAC;AACH;AAaA,eAAsB,eAAe,MAAgC;AAInE,aAAW,QAAQ,CAAC,WAAW,IAAI,GAAG;AACpC,QAAI,CAAE,MAAM,QAAQ,MAAM,IAAI,EAAI,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,MAAc,MAAgC;AAC7D,SAAO,IAAI,QAAQ,CAAAA,aAAW;AAC5B,UAAM,SAAS,IAAI,aAAa;AAChC,WAAO,KAAK,SAAS,CAAC,QAA+B;AAGnD,UAAI,IAAI,SAAS,gBAAgB,IAAI,SAAS,SAAU,CAAAA,SAAQ,KAAK;AAAA,UAChE,CAAAA,SAAQ,IAAI;AAAA,IACnB,CAAC;AACD,WAAO,KAAK,aAAa,MAAM,OAAO,MAAM,MAAMA,SAAQ,IAAI,CAAC,CAAC;AAChE,WAAO,OAAO,MAAM,IAAI;AAAA,EAC1B,CAAC;AACH;AAEO,SAAS,UACd,MACA,OAAyF,CAAC,GACxE;AAClB,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,SAAS,CAAC,SAAiB;AAC/B,QAAI,KAAK,WAAW,OAAW,QAAO,QAAQ,OAAO,OAAO;AAC5D,QAAI,MAAM,QAAQ,KAAK,MAAM,EAAG,QAAO,KAAK,OAAO,SAAS,IAAI;AAChE,WAAO,SAAS,KAAK;AAAA,EACvB;AACA,SAAO,IAAI,QAAQ,CAAAA,aAAW;AAC5B,UAAM,MAAM,KAAK,IAAI,EAAE,MAAM,MAAM,MAAM,SAAS,UAAU,GAAG,SAAO;AACpE,YAAM,KAAK,OAAO,IAAI,eAAe,YAAY,OAAO,IAAI,UAAU;AACtE,UAAI,OAAO;AACX,MAAAA,SAAQ,EAAE;AAAA,IACZ,CAAC;AACD,QAAI,GAAG,SAAS,MAAMA,SAAQ,KAAK,CAAC;AACpC,QAAI,GAAG,WAAW,MAAM;AAAE,UAAI,QAAQ;AAAG,MAAAA,SAAQ,KAAK;AAAA,IAAG,CAAC;AAAA,EAC5D,CAAC;AACH;AAGO,SAAS,YAAY,MAAc,IAA0C;AAClF,MAAI,IAAI,SAAS,QAAQ;AACvB,WAAO,UAAU,MAAM;AAAA,MACrB,MAAM,GAAG;AAAA,MAAM,QAAQ,GAAG;AAAA,MAAQ,MAAM,GAAG;AAAA,MAAM,WAAW,GAAG;AAAA,IACjE,CAAC;AAAA,EACH;AACA,SAAO,UAAU,MAAM,aAAa,IAAI,SAAS;AACnD;AAEO,SAAS,YAAY,MAAc,OAAgD,CAAC,GAAqB;AAC9G,QAAM,EAAE,UAAU,MAAO,WAAW,IAAK,IAAI;AAC7C,SAAO,IAAI,QAAQ,CAAAA,aAAW;AAC5B,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,QAAQ,MAAM;AAClB,gBAAU,IAAI,EAAE,KAAK,QAAM;AACzB,YAAI,GAAI,QAAOA,SAAQ,IAAI;AAC3B,YAAI,KAAK,IAAI,IAAI,QAAQ,QAAS,QAAOA,SAAQ,KAAK;AACtD,mBAAW,OAAO,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR,CAAC;AACH;AAEO,SAAS,aAAa,MAAe,eAAqC;AAC/E,MAAI,kBAAkB,OAAQ,QAAO;AACrC,MAAI,KAAM,QAAO;AACjB,SAAO,kBAAkB,aAAa,SAAS;AACjD;;;AC5GA,SAAS,cAAAC,aAAY,oBAAoB;AAKlC,SAAS,aAAa,UAAkB,UAAkC,CAAC,GAA2B;AAC3G,QAAM,MAAM,EAAE,GAAG,QAAQ;AACzB,MAAI,CAACA,YAAW,QAAQ,EAAG,QAAO;AAElC,aAAW,QAAQ,aAAa,UAAU,MAAM,EAAE,MAAM,IAAI,GAAG;AAC7D,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AACzC,UAAM,QAAQ,QAAQ,QAAQ,GAAG;AACjC,QAAI,UAAU,GAAI;AAClB,UAAM,MAAM,QAAQ,MAAM,GAAG,KAAK,EAAE,KAAK;AACzC,QAAI,MAAM,QAAQ,MAAM,QAAQ,CAAC,EAAE,KAAK;AACxC,QAAK,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,KAAO,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAI;AAC5F,YAAM,IAAI,MAAM,GAAG,EAAE;AAAA,IACvB;AACA,QAAI,CAAC,IAAI,GAAG,EAAG,KAAI,GAAG,IAAI;AAAA,EAC5B;AACA,SAAO;AACT;;;ACrBO,SAAS,UAAU,IAAoB;AAC5C,MAAI,CAAC,MAAM,KAAK,EAAG,QAAO;AAC1B,QAAM,IAAI,KAAK,MAAM,KAAK,GAAI;AAC9B,MAAI,IAAI,GAAI,QAAO,GAAG,CAAC;AACvB,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,MAAI,IAAI,GAAI,QAAO,GAAG,CAAC,IAAI,IAAI,EAAE;AACjC,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,MAAI,IAAI,GAAI,QAAO,GAAG,CAAC,IAAI,IAAI,EAAE;AACjC,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,SAAO,GAAG,CAAC,IAAI,IAAI,EAAE;AACvB;;;ACCO,SAAS,qBAAqB,MAA2C;AAC9E,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,UAAU,wBAAwB,KAAK,IAAI;AACjD,MAAI,SAAS;AACX,UAAM,QAAQ,QAAQ,CAAC,EAAG,SAAS,GAAG,IAAI,QAAQ,CAAC,IAAK,QAAQ,CAAC,IAAK;AACtE,QAAI;AACF,YAAM,KAAK,IAAI,OAAO,QAAQ,CAAC,GAAI,KAAK;AACxC,aAAO,EAAE,MAAM,CAAC,MAAc,GAAG,KAAK,CAAC,GAAG,OAAO,GAAG;AAAA,IACtD,QAAQ;AACN,YAAMC,SAAQ,KAAK,YAAY;AAC/B,aAAO,EAAE,MAAM,CAAC,MAAc,EAAE,YAAY,EAAE,SAASA,MAAK,GAAG,SAAS,KAAK;AAAA,IAC/E;AAAA,EACF;AACA,QAAM,QAAQ,KAAK,YAAY;AAC/B,SAAO,EAAE,MAAM,CAAC,MAAc,EAAE,YAAY,EAAE,SAAS,KAAK,EAAE;AAChE;AAMO,SAAS,eAAe,MAAwB;AACrD,QAAM,IAAI,KAAK,YAAY;AAE3B,MAAI,2EAA2E,KAAK,CAAC,KAAK,QAAQ,KAAK,IAAI,EAAG,QAAO;AACrH,MAAI,wCAAwC,KAAK,CAAC,KAAK,IAAI,KAAK,IAAI,EAAG,QAAO;AAC9E,SAAO;AACT;;;ACrCO,SAAS,cAAc,KAAiE;AAC7F,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,CAAC,IAAI,0CAA0C,KAAK,CAAC,IAAI,QAAQ;AAAA,EACvE;AACA,SAAO;AACT;;;ACTA,SAAS,cAAAC,aAAY,gBAAAC,eAAc,qBAAqB;AACxD,SAAS,kBAAkB;AAC3B,SAAS,QAAAC,aAAY;AAId,SAAS,aAAa,SAA0B;AACrD,QAAM,KAAKA,MAAK,SAAS,cAAc;AACvC,MAAI,CAACF,YAAW,EAAE,EAAG,QAAO;AAC5B,MAAI;AACF,UAAM,UAAU,WAAW,KAAK,EAAE,OAAOC,cAAaC,MAAK,SAAS,cAAc,CAAC,CAAC,EAAE,OAAO,KAAK;AAClG,UAAM,YAAYA,MAAK,IAAI,gBAAgB;AAC3C,QAAIF,YAAW,SAAS,KAAKC,cAAa,WAAW,MAAM,MAAM,QAAS,QAAO;AAAA,EACnF,QAAQ;AAAA,EAAoC;AAC5C,SAAO;AACT;AAGO,SAAS,kBAAkB,SAAuB;AACvD,MAAI;AACF,UAAM,UAAU,WAAW,KAAK,EAAE,OAAOA,cAAaC,MAAK,SAAS,cAAc,CAAC,CAAC,EAAE,OAAO,KAAK;AAClG,kBAAcA,MAAK,SAAS,gBAAgB,gBAAgB,GAAG,OAAO;AAAA,EACxE,QAAQ;AAAA,EAAoB;AAC9B;;;ACnBO,SAAS,iBAAiB,KAA8B;AAC7D,QAAM,QAAQ,IAAI,YAAY,CAAC;AAC/B,MAAI,CAAC,IAAI,OAAQ,QAAO,CAAC,GAAG,OAAO,GAAG,IAAI,IAAI;AAC9C,MAAI,IAAI,QAAQ,OAAQ,QAAO,CAAC,wBAAwB,IAAI,MAAM,IAAI,GAAG,OAAO,GAAG,IAAI,IAAI;AAC3F,SAAO,CAAC,GAAG,OAAO,GAAG,IAAI,IAAI;AAC/B;AAIO,SAAS,gBAAgB,KAAoB,SAAyD;AAC3G,QAAM,MAAM,EAAE,GAAG,SAAS,GAAI,IAAI,YAAY,CAAC,EAAG;AAClD,MAAI,IAAI,UAAU,IAAI,QAAQ,QAAQ;AACpC,UAAM,WAAW,IAAI,cAAc,KAAK;AACxC,UAAM,OAAO,wBAAwB,IAAI,MAAM;AAC/C,QAAI,CAAC,SAAS,SAAS,oBAAoB,GAAG;AAC5C,UAAI,cAAc,IAAI,WAAW,GAAG,QAAQ,IAAI,IAAI,KAAK;AAAA,IAC3D;AAAA,EACF;AACA,SAAO;AACT;;;ACnBO,SAAS,iBACd,OAAiB,UACjB,UACA,WACU;AACV,MAAI,aAAa,OAAQ,QAAO,MAAM,MAAM,EAAE,KAAK;AACnD,SAAO,MAAM,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAClC,QAAI,aAAa,OAAO;AACtB,cAAQ,WAAW,SAAS,CAAC,GAAG,OAAO,GAAG,KAAK,MAAM,WAAW,SAAS,CAAC,GAAG,OAAO,GAAG,KAAK;AAAA,IAC9F;AACA,YAAQ,UAAU,CAAC,GAAG,UAAU,MAAM,UAAU,CAAC,GAAG,UAAU;AAAA,EAChE,CAAC;AACH;AAIO,SAAS,eAAe,aAAqB,SAAiB,UAA0B;AAC7F,QAAM,WAAW,KAAK,IAAI,IAAI,YAAY;AAC1C,QAAM,WAAW,cAAc;AAC/B,SAAO,UAAU,IAAK,WAAW,UAAW,MAAM;AACpD;AAMO,SAAS,wBACd,UACA,iBACA,gBAAgB,IAChB,eAAe,IACN;AACT,MAAI,YAAY,cAAe,QAAO;AACtC,MAAI,WAAW,aAAc,QAAO;AACpC,SAAO;AACT;;;ACpCO,SAAS,aAAa,UAA4D;AACvF,QAAM,SAA0C,CAAC;AACjD,aAAW,KAAK,UAAU;AACxB,KAAC,OAAO,EAAE,KAAK,MAAM,CAAC,GAAG,KAAK,CAAC;AAAA,EACjC;AACA,SAAO;AACT;;;ACPO,IAAM,YAAY;AAAA,EACvB;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAS;AAAA,EAAW;AAAA,EACtC;AAAA,EAAO;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EACxC;AAAA,EAAW;AAAA,EAAW;AACxB;;;ACNA,SAAS,wBAAwB;AACjC,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,cAAAC,mBAAkB;;;ACF3B,SAAS,oBAA8C;AACvD,SAAS,uBAAuB;AAChC,SAAS,cAAAC,aAAY,YAAY,WAAW,WAAW,gBAAgB;AACvE,SAAS,eAAe;AACxB,SAAS,QAAAC,aAAY;AACrB,SAAS,eAAe;AA6DjB,SAAS,kBAAkB,aAA6B;AAC7D,QAAM,OAAO,YAAY,QAAQ,qBAAqB,GAAG,KAAK;AAC9D,SAAOA,MAAK,QAAQ,GAAG,UAAU,QAAQ,IAAI,OAAO;AACtD;AAEA,eAAsB,kBACpB,aACA,KACA,OAAyD,CAAC,GAC7B;AAC7B,QAAM,OAAO,KAAK,QAAQ,kBAAkB,WAAW;AACvD,YAAU,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAG5C,MAAID,YAAW,IAAI,GAAG;AACpB,QAAI;AACF,YAAM,KAAK,SAAS,IAAI;AACxB,UAAI,GAAG,SAAS,EAAG,YAAW,IAAI;AAAA,IACpC,QAAQ;AAAA,IAAsD;AAAA,EAChE;AAQA,QAAM,gBAAgB,oBAAI,IAAY;AACtC,QAAM,SAAS,aAAa,YAAU;AACpC,kBAAc,IAAI,MAAM;AACxB,WAAO,KAAK,SAAS,MAAM,cAAc,OAAO,MAAM,CAAC;AACvD,iBAAa,QAAQ,GAAG;AAAA,EAC1B,CAAC;AACD,QAAM,IAAI,QAAc,CAACE,UAAS,WAAW;AAC3C,WAAO,KAAK,SAAS,MAAM;AAC3B,WAAO,OAAO,MAAM,MAAM;AACxB,aAAO,IAAI,SAAS,MAAM;AAC1B,UAAI;AAAE,kBAAU,MAAM,GAAK;AAAA,MAAG,QAAQ;AAAA,MAA+C;AACrF,WAAK,QAAQ,8BAAuB,IAAI,EAAE;AAC1C,MAAAA,SAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,QAAQ;AAEZ,iBAAW,QAAQ,cAAe,MAAK,QAAQ;AAC/C,oBAAc,MAAM;AACpB,YAAM,IAAI,QAAc,CAAAA,aAAW,OAAO,MAAM,MAAMA,SAAQ,CAAC,CAAC;AAChE,UAAIF,YAAW,IAAI,GAAG;AACpB,YAAI;AAAE,qBAAW,IAAI;AAAA,QAAG,QAAQ;AAAA,QAAe;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,QAAgB,KAAuB;AAC3D,QAAM,KAAK,gBAAgB,EAAE,OAAO,OAAO,CAAC;AAC5C,QAAM,SAAS,oBAAI,IAAgB;AAEnC,SAAO,GAAG,SAAS,MAAM;AACvB,eAAW,SAAS,OAAQ,OAAM;AAClC,WAAO,MAAM;AAAA,EACf,CAAC;AAED,KAAG,GAAG,QAAQ,OAAO,SAAiB;AACpC,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAI;AACJ,QAAI;AACF,YAAM,KAAK,MAAM,IAAI;AAAA,IACvB,SAAS,GAAQ;AACf,cAAQ,QAAQ,EAAE,OAAO,EAAE,MAAM,QAAQ,SAAS,gBAAgB,EAAE,OAAO,GAAG,EAAE,CAAC;AACjF;AAAA,IACF;AACA,QAAI,OAAO,IAAI,WAAW,UAAU;AAClC,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,EAAE,MAAM,QAAQ,SAAS,kBAAkB,EAAE,CAAC;AACnF;AAAA,IACF;AACA,UAAM,SAAU,IAAI,UAAU,CAAC;AAC/B,QAAI,IAAI,WAAW,iBAAiB,IAAI,WAAW,iBAAiB;AAClE,UAAI;AACF,cAAM,aAAa,QAAQ,KAAyC,QAAQ,KAAK,MAAM;AAAA,MACzF,SAAS,GAAQ;AACf,gBAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,EAAE,MAAM,QAAQ,SAAS,EAAE,WAAW,OAAO,CAAC,EAAE,EAAE,CAAC;AAAA,MAC1F;AACA;AAAA,IACF;AACA,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,IAAI,QAAQ,QAAQ,GAAG;AACrD,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,CAAC;AAAA,IACxC,SAAS,GAAQ;AACf,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,EAAE,MAAM,QAAQ,SAAS,EAAE,WAAW,OAAO,CAAC,EAAE,EAAE,CAAC;AAAA,IAC1F;AAAA,EACF,CAAC;AACD,SAAO,GAAG,SAAS,MAAM;AAAA,EAA8B,CAAC;AAC1D;AAEA,eAAe,aACb,QACA,KACA,QACA,KACA,QACe;AACf,MAAI,IAAI,WAAW,eAAe;AAChC,UAAM,SAAS,OAAO,KAAK,KAAK,OAAO,SAAS;AAChD,UAAM,UAAU,UAAU,OAAO,cAAc,QAAQ,KAAK,IAAI;AAChE,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAM,OAAO,OAAO,MAAM,KAAK,EAAE,CAAC,CAAC;AAErE,YAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,QAAQ,EAAE,IAAI,KAAK,EAAE,CAAC;AAGpD,QAAI,SAAS;AACX,YAAM,QAAQ,MAAM,IAAI,SAAS,SAAS,IAAI;AAC9C,iBAAW,KAAK,OAAO;AACrB,gBAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,OAAO,MAAM,EAAE,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,UAAU,SAAS,CAAC,KAAK,SAAS;AAClD,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,IAC/D,CAAC;AACD,WAAO,IAAI,KAAK;AAAA,EAElB,OAAO;AAEL,YAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,QAAQ,EAAE,IAAI,KAAK,EAAE,CAAC;AAGpD,UAAM,WAA2C,CAAC;AAClD,eAAW,CAAC,MAAM,EAAE,KAAK,IAAI,OAAO,GAAG;AACrC,eAAS,KAAK,eAAe,MAAM,EAAE,CAAC;AAAA,IACxC;AACA,QAAI,SAAS,QAAQ;AACnB,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,UAAU,MAAM,SAAS,CAAC;AAAA,IACjE;AAEA,UAAM,QAAQ,IAAI,YAAY,CAAC,MAAM,UAAU;AAC7C,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,UAAU,MAAM,CAAC,eAAe,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,IACtF,CAAC;AACD,WAAO,IAAI,KAAK;AAAA,EAClB;AACF;AAEA,SAAS,eAAe,MAAc,IAA2C;AAC/E,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,GAAG;AAAA,IACX,QAAQ,GAAG;AAAA,IACX,MAAM,GAAG,IAAI;AAAA,IACb,MAAM,GAAG,IAAI;AAAA,IACb,QAAQ,GAAG;AAAA,IACX,UAAU,GAAG;AAAA,IACb,KAAK,GAAG;AAAA,IACR,WAAW,GAAG;AAAA,EAChB;AACF;AAEA,SAAS,QAAQ,QAAgB,SAAuB;AACtD,MAAI,OAAO,SAAU,QAAO,MAAM,KAAK,UAAU,OAAO,IAAI,IAAI;AAClE;AAEA,eAAe,SACb,QACA,QACA,KACkB;AAClB,UAAQ,QAAQ;AAAA,IACd,KAAK,UAAU;AACb,YAAM,MAAsC,CAAC;AAC7C,iBAAW,CAAC,MAAM,EAAE,KAAK,IAAI,OAAO,GAAG;AACrC,YAAI,KAAK,eAAe,MAAM,EAAE,CAAC;AAAA,MACnC;AACA,aAAO,EAAE,UAAU,KAAK,OAAO,IAAI,aAAa,EAAE;AAAA,IACpD;AAAA,IACA,KAAK;AACH,aAAO,MAAM,IAAI,SAAS;AAAA,IAC5B,KAAK,WAAW;AACd,YAAM,MAAM,cAAc,OAAO,KAAK,KAAK,OAAO,SAAS,GAAG,KAAK;AACnE,YAAM,IAAI,QAAQ,GAAG;AACrB,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,MAAM,cAAc,OAAO,KAAK,KAAK,OAAO,SAAS,GAAG,KAAK;AACnE,UAAI,KAAK,GAAG;AACZ,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,MAAM,cAAc,OAAO,KAAK,KAAK,OAAO,SAAS,GAAG,KAAK;AACnE,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAQ,OAAO,OAAO,OAAO,KAAK,GAAG,CAAC,CAAC;AAC1E,aAAO,EAAE,OAAO,MAAM,IAAI,SAAS,KAAK,KAAK,EAAE;AAAA,IACjD;AAAA,IACA,KAAK;AACH,aAAO,EAAE,IAAI,MAAM,IAAI,KAAK,IAAI,EAAE;AAAA,IACpC;AACE,YAAM,IAAI,MAAM,mBAAmB,MAAM,EAAE;AAAA,EAC/C;AACF;AAEA,SAAS,cAAc,GAAY,WAA2B;AAC5D,MAAI,OAAO,MAAM,YAAY,CAAC,EAAE,KAAK,GAAG;AACtC,UAAM,IAAI,MAAM,UAAU,SAAS,8BAA8B;AAAA,EACnE;AACA,SAAO;AACT;;;ADxQO,SAAS,cAAc,aAAqB,cAA+B;AAChF,SAAO,gBAAgB,kBAAkB,WAAW;AACtD;AAGO,SAAS,mBAAmB,YAAoB,aAA2B;AAChF,MAAI,CAACG,YAAW,UAAU,GAAG;AAC3B,UAAM,IAAI;AAAA,MACR,qCAAqC,WAAW;AAAA;AAAA,IAClD;AAAA,EACF;AACF;AAGO,SAAS,QACd,YACA,QACA,SAAkC,CAAC,GACjB;AAClB,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,QAAI,UAAU;AACd,UAAM,OAAO,CAAC,QAAe;AAAE,UAAI,CAAC,SAAS;AAAE,kBAAU;AAAM,eAAO,GAAG;AAAA,MAAG;AAAA,IAAE;AAC9E,UAAM,KAAK,CAAC,MAAe;AAAE,UAAI,CAAC,SAAS;AAAE,kBAAU;AAAM,QAAAA,SAAQ,CAAC;AAAA,MAAG;AAAA,IAAE;AAE3E,UAAM,IAAI,iBAAiB,UAAU;AACrC,UAAM,KAAKC,iBAAgB,EAAE,OAAO,EAAE,CAAC;AAIvC,MAAE,GAAG,SAAS,IAAI;AAClB,OAAG,GAAG,SAAS,IAAI;AACnB,OAAG,KAAK,QAAQ,OAAK;AACnB,QAAE,IAAI;AACN,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,CAAC;AACxB,YAAI,IAAI,MAAO,MAAK,IAAI,MAAM,IAAI,MAAM,WAAW,OAAO,IAAI,KAAK,CAAC,CAAC;AAAA,YAChE,IAAG,IAAI,MAAM;AAAA,MACpB,SAAS,GAAQ;AACf,aAAK,CAAC;AAAA,MACR;AAAA,IACF,CAAC;AACD,MAAE,MAAM,KAAK,UAAU,EAAE,IAAI,GAAG,QAAQ,OAAO,CAAC,IAAI,IAAI;AAAA,EAC1D,CAAC;AACH;AAUO,SAAS,WACd,YACA,QACA,QACA,SACA,SACY;AACZ,QAAM,IAAI,iBAAiB,UAAU;AACrC,QAAM,KAAKA,iBAAgB,EAAE,OAAO,EAAE,CAAC;AACvC,MAAI,UAAU;AAKd,QAAM,QAAQ,CAAC,QAAe,UAAU,GAAG;AAC3C,IAAE,GAAG,SAAS,KAAK;AACnB,KAAG,GAAG,SAAS,KAAK;AACpB,IAAE,MAAM,KAAK,UAAU,EAAE,IAAI,GAAG,QAAQ,OAAO,CAAC,IAAI,IAAI;AAExD,KAAG,GAAG,QAAQ,OAAK;AACjB,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,CAAC;AACxB,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,YAAI,IAAI,OAAO;AAAE,oBAAU,IAAI,MAAM,IAAI,MAAM,WAAW,OAAO,IAAI,KAAK,CAAC,CAAC;AAAG,YAAE,QAAQ;AAAA,QAAG;AAC5F;AAAA,MACF;AACA,UAAI,IAAI,MAAO,SAAQ,GAAkB;AAAA,IAC3C,QAAQ;AAAA,IAAgC;AAAA,EAC1C,CAAC;AAED,SAAO,MAAM,EAAE,QAAQ;AACzB;;;AE7FA,SAAS,SAAAC,cAAa;AACtB,SAAS,iBAAAC,gBAAe,gBAAAC,eAAc,cAAAC,cAAY,cAAAC,aAAY,aAAAC,YAAW,wBAAwB;AACjG,SAAS,QAAAC,aAAY;AACrB,SAAS,WAAAC,UAAS,UAAU,SAAS,YAAY;AACjD,SAAS,cAAc,aAAa;AACpC,SAAS,mBAAAC,wBAAuB;;;ACLhC,SAAS,QAAAC,aAAY;;;ACArB,SAAS,aAAa;AACtB,SAAS,cAAAC,mBAAkB;AAGpB,SAAS,eACd,KAAa,KACb,OACkB;AAClB,MAAI,CAACC,YAAW,GAAG,GAAG;AACpB,YAAQ,+BAA0B,GAAG,EAAE;AACvC,WAAO,QAAQ,QAAQ,KAAK;AAAA,EAC9B;AACA,MAAI,CAAC,aAAa,GAAG,GAAG;AACtB,YAAQ,gCAA2B;AACnC,WAAO,QAAQ,QAAQ,IAAI;AAAA,EAC7B;AACA,UAAQ,0BAAmB;AAC3B,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAE5B,UAAM,UAAU,QAAQ,aAAa,UAAU,YAAY;AAC3D,UAAM,OAAO,MAAM,SAAS,CAAC,SAAS,GAAG,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,UAAU,MAAM,EAAE,CAAC;AAC1F,QAAI,SAAS;AACb,SAAK,QAAQ,GAAG,QAAQ,CAAC,MAAc;AAAE,gBAAU,EAAE,SAAS;AAAA,IAAG,CAAC;AAClE,SAAK,GAAG,SAAS,UAAQ;AACvB,UAAI,SAAS,GAAG;AACd,gBAAQ,8BAAyB,OAAO,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE;AACxD,QAAAA,SAAQ,KAAK;AAAA,MACf,OAAO;AACL,0BAAkB,GAAG;AACrB,gBAAQ,2BAAsB;AAC9B,QAAAA,SAAQ,IAAI;AAAA,MACd;AAAA,IACF,CAAC;AACD,SAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,cAAQ,uBAAkB,IAAI,OAAO,EAAE;AACvC,MAAAA,SAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH,CAAC;AACH;;;ACtCA,SAAS,SAAAC,cAAgC;AACzC,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,OAAM,WAAAC,gBAAe;;;ACAvB,SAAS,WAAW,QAAgC;AACzD,MAAI,MAAM;AACV,SAAO;AAAA,IACL,KAAK,OAAe;AAClB,aAAO,MAAM,SAAS;AACtB,UAAI;AACJ,cAAQ,MAAM,IAAI,QAAQ,IAAI,OAAO,IAAI;AACvC,cAAM,OAAO,IAAI,MAAM,GAAG,GAAG,EAAE,QAAQ,OAAO,EAAE;AAChD,cAAM,IAAI,MAAM,MAAM,CAAC;AACvB,YAAI,KAAK,OAAQ,QAAO,IAAI;AAAA,MAC9B;AAAA,IACF;AAAA,IACA,QAAQ;AACN,UAAI,IAAI,QAAQ;AAAE,eAAO,GAAG;AAAG,cAAM;AAAA,MAAI;AAAA,IAC3C;AAAA,EACF;AACF;AAGO,SAAS,oBAAoB,SAA4C;AAC9E,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,UAAU,wBAAwB,KAAK,OAAO;AACpD,MAAI;AACF,QAAI,QAAS,QAAO,IAAI,OAAO,QAAQ,CAAC,GAAI,QAAQ,CAAC,KAAK,GAAG;AAC7D,WAAO,IAAI,OAAO,SAAS,GAAG;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIO,SAAS,kBAAkB,MAA0B;AAC1D,QAAM,aAAa,oBAAI,IAAI,CAAC,WAAW,cAAc,CAAC;AACtD,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,WAAW,IAAI,CAAC,GAAG;AACrB,YAAM,IAAI,KAAK,IAAI,CAAC;AACpB,UAAI,KAAK,CAAC,EAAE,WAAW,GAAG,GAAG;AAAE,YAAI,KAAK,CAAC;AAAG;AAAA,MAAK;AACjD;AAAA,IACF;AACA,UAAM,KAAK,EAAE,QAAQ,GAAG;AACxB,QAAI,KAAK,KAAK,WAAW,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG;AAC5C,UAAI,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,eAAe;AACrB,IAAM,kBAAkB;;;AD7BxB,IAAM,UAAN,MAAc;AAAA,EACF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAmB;AAC7B,SAAK,UAAU,KAAK;AACpB,SAAK,MAAM,KAAK;AAChB,SAAK,QAAQ,KAAK;AAClB,SAAK,QAAQ,KAAK;AAClB,SAAK,SAAS,KAAK;AACnB,SAAK,YAAY,KAAK;AACtB,SAAK,UAAU,KAAK;AAAA,EACtB;AAAA,EAEA,MAAM,MAAM,KAAoB,UAAkB,YAAY,OAAsB;AAClF,UAAM,MAAMC,MAAK,KAAK,SAAS,IAAI,GAAG;AAKtC,QAAI,IAAI,SAAS,OAAO;AACtB,YAAM,WAAW,MAAM,eAAe,IAAI,IAAI;AAC9C,UAAI,CAAC,YAAY,CAAC,WAAW;AAC3B,aAAK,IAAI,IAAI,MAAM,eAAU,IAAI,IAAI,mCAA8B,QAAQ;AAC3E,aAAK,mBAAmB,KAAK,QAAQ;AACrC;AAAA,MACF;AAAA,IACF;AAGA,QAAI,IAAI,UAAU;AAChB,YAAM,QAAQ,MAAM,KAAK,YAAY,KAAK,KAAK,QAAQ;AACvD,UAAI,CAAC,OAAO;AACV,aAAK,mBAAmB,KAAK,QAAQ;AACrC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,iBAAiB,GAAG;AAGjC,UAAM,oBAAoB,kBAAkB,IAAI,EAC7C,OAAO,OAAK,CAACC,YAAWC,SAAQ,KAAK,CAAC,CAAC,CAAC;AAC3C,QAAI,kBAAkB,QAAQ;AAC5B,WAAK,IAAI,IAAI,MAAM,+BAA0B,kBAAkB,KAAK,IAAI,CAAC,IAAI,QAAQ;AACrF,WAAK,mBAAmB,KAAK,QAAQ;AACrC;AAAA,IACF;AAEA,UAAM,MAAM,gBAAgB,KAAK,KAAK,GAAG;AACzC,UAAM,OAAOC,OAAM,IAAI,KAAK,MAAM,EAAE,KAAK,KAAK,UAAU,MAAM,OAAO,CAAC,UAAU,QAAQ,MAAM,EAAE,CAAC;AAEjG,UAAM,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI;AACpC,UAAM,QAAsB;AAAA,MAC1B;AAAA,MAAK;AAAA,MAAM,KAAK,KAAK,OAAO;AAAA,MAC5B,QAAQ;AAAA,MAAY,QAAQ;AAAA,MAC5B,QAAQ,MAAM,UAAU;AAAA,MACxB,UAAU,MAAM,YAAY;AAAA,MAC5B,WAAW,KAAK,IAAI;AAAA,MACpB,iBAAiB;AAAA,MACjB;AAAA,IACF;AACA,SAAK,MAAM,IAAI,IAAI,MAAM,KAAK;AAC9B,SAAK,MAAM,IAAI,IAAI;AACnB,SAAK,OAAO,cAAc,IAAI,MAAM,KAAK;AAEzC,SAAK,UAAU,MAAM,KAAK,OAAO,QAAQ;AACzC,SAAK,iBAAiB,MAAM,KAAK,OAAO,QAAQ;AAGhD,QAAI,IAAI,YAAY;AAClB,YAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,KAAK,QAAQ;AAAA,IAChE;AAEA,SAAK,IAAI,IAAI,MAAM,YAAY,yBAAkB,IAAI,IAAI,MAAM,uBAAgB,IAAI,IAAI,KAAK,QAAQ;AAAA,EACtG;AAAA,EAEQ,UAAU,MAAoB,KAAoB,OAAqB,UAAwB;AACrG,UAAM,aAAa,oBAAoB,IAAI,YAAY;AACvD,UAAM,mBAAmB,CAAC,SAAiB;AACzC,UAAI,CAAC,cAAc,MAAM,WAAW,KAAM;AAC1C,UAAI,WAAW,KAAK,IAAI,GAAG;AACzB,cAAM,SAAS;AACf,YAAI,MAAM,WAAW,WAAY,OAAM,SAAS;AAChD,aAAK,OAAO,cAAc,IAAI,MAAM,KAAK;AAAA,MAC3C;AAAA,IACF;AACA,UAAM,aAAa,oBAAoB,IAAI,YAAY;AACvD,UAAM,gBAAgB,CAAC,SAAiB,aAAa,WAAW,KAAK,IAAI,IAAI;AAE7E,UAAM,YAAY,WAAW,UAAQ;AAAE,uBAAiB,IAAI;AAAG,WAAK,IAAI,IAAI,MAAM,MAAM,QAAQ;AAAA,IAAG,CAAC;AACpG,UAAM,YAAY,WAAW,UAAQ;AACnC,UAAI,cAAc,IAAI,EAAG,OAAM,UAAU;AACzC,uBAAiB,IAAI;AACrB,WAAK,IAAI,IAAI,MAAM,MAAM,QAAQ;AAAA,IACnC,CAAC;AAED,SAAK,QAAQ,GAAG,QAAQ,CAAC,MAAc,UAAU,KAAK,CAAC,CAAC;AACxD,SAAK,QAAQ,GAAG,QAAQ,CAAC,MAAc,UAAU,KAAK,CAAC,CAAC;AACxD,SAAK,QAAQ,GAAG,OAAO,MAAM,UAAU,MAAM,CAAC;AAC9C,SAAK,QAAQ,GAAG,OAAO,MAAM,UAAU,MAAM,CAAC;AAAA,EAChD;AAAA,EAEQ,iBAAiB,MAAoB,KAAoB,OAAqB,UAAwB;AAC5G,SAAK,GAAG,SAAS,UAAQ;AACvB,WAAK,MAAM,OAAO,IAAI;AACtB,WAAK,UAAU,cAAc,KAAK;AAClC,UAAI,MAAM,iBAAiB;AAAE,cAAM,kBAAkB;AAAO;AAAA,MAAQ;AACpE,UAAI,SAAS,GAAG;AACd,cAAM,SAAS;AAAW,cAAM,SAAS;AACzC,aAAK,OAAO,cAAc,IAAI,MAAM,KAAK;AACzC;AAAA,MACF;AACA,YAAM,SAAS;AAAW,YAAM,SAAS;AACzC,WAAK,IAAI,IAAI,MAAM,2BAAsB,IAAI,IAAI,QAAQ;AACzD,WAAK,OAAO,cAAc,IAAI,MAAM,KAAK;AACzC,WAAK,QAAQ,KAAK,OAAO,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH;AAAA,EAEQ,YAAY,KAAoB,KAAa,UAAoC;AACvF,SAAK,IAAI,IAAI,MAAM,uBAAgB,IAAI,QAAQ,IAAI,QAAQ;AAC3D,WAAO,IAAI,QAAQ,SAAO;AACxB,YAAM,QAAQ,QAAQ,aAAa;AACnC,YAAM,QAAQ,QAAQ,YAAY;AAClC,YAAM,YAAY,QAAQ,OAAO;AACjC,YAAM,MAAM,gBAAgB,KAAK,KAAK,GAAG;AACzC,YAAM,QAAQA,OAAM,OAAO,CAAC,WAAW,IAAI,QAAS,GAAG,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,QAAQ,MAAM,EAAE,CAAC;AAEtG,YAAM,SAAS,WAAW,UAAQ,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,IAAI,QAAQ,CAAC;AACjF,YAAM,SAAS,WAAW,UAAQ,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,IAAI,QAAQ,CAAC;AACjF,YAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AACtD,YAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AAEtD,YAAM,GAAG,SAAS,SAAO;AACvB,aAAK,IAAI,IAAI,MAAM,kBAAa,IAAI,OAAO,IAAI,QAAQ;AACvD,YAAI,KAAK;AAAA,MACX,CAAC;AACD,YAAM,GAAG,SAAS,UAAQ;AACxB,eAAO,MAAM;AAAG,eAAO,MAAM;AAC7B,YAAI,SAAS,GAAG;AACd,eAAK,IAAI,IAAI,MAAM,uBAAkB,QAAQ;AAC7C,cAAI,IAAI;AAAA,QACV,OAAO;AACL,eAAK,IAAI,IAAI,MAAM,mCAA8B,IAAI,IAAI,QAAQ;AACjE,cAAI,KAAK;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,gBAAgB,KAAoB,KAAa,KAA6B,UAAgC;AACpH,SAAK,IAAI,IAAI,MAAM,yBAAkB,IAAI,UAAU,IAAI,QAAQ;AAC/D,UAAM,QAAQ,QAAQ,aAAa;AACnC,UAAM,QAAQ,QAAQ,YAAY;AAClC,UAAM,YAAY,QAAQ,OAAO;AACjC,UAAM,QAAQA,OAAM,OAAO,CAAC,WAAW,IAAI,UAAW,GAAG;AAAA,MACvD;AAAA,MAAK;AAAA,MAAK,UAAU;AAAA,MAAM,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,IAC5D,CAAC;AACD,UAAM,SAAS,WAAW,UAAQ,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,IAAI,QAAQ,CAAC;AACjF,UAAM,SAAS,WAAW,UAAQ,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,IAAI,QAAQ,CAAC;AACjF,UAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AACtD,UAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AACtD,UAAM,GAAG,SAAS,SAAO,KAAK,IAAI,IAAI,MAAM,kBAAa,IAAI,OAAO,IAAI,QAAQ,CAAC;AACjF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAIQ,mBAAmB,KAAoB,UAAwB;AACrE,UAAM,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI;AACpC,SAAK,MAAM,IAAI,IAAI,MAAM;AAAA,MACvB;AAAA,MAAK,MAAM;AAAA,MAAM,KAAK;AAAA,MACtB,QAAQ;AAAA,MAAW,QAAQ;AAAA,MAC3B,QAAQ,MAAM,UAAU;AAAA,MACxB,UAAU,MAAM,YAAY;AAAA,MAC5B,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB;AAAA,IACF,CAAC;AACD,SAAK,OAAO,cAAc,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,IAAI,CAAE;AAAA,EAC/D;AAAA,EAEQ,IAAI,MAAc,MAAc,UAAwB;AAC9D,SAAK,OAAO,MAAM,MAAM,MAAM,QAAQ;AAAA,EACxC;AACF;;;AErMO,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAqB;AAC/B,SAAK,QAAQ,KAAK;AAClB,SAAK,SAAS,KAAK;AACnB,SAAK,UAAU,KAAK;AACpB,SAAK,YAAY,KAAK;AAAA,EACxB;AAAA,EAEA,MAAM,QAAQ,MAA6B;AACzC,UAAM,KAAK,KAAK,MAAM,IAAI,IAAI;AAC9B,QAAI,CAAC,GAAI;AACT,SAAK,UAAU,KAAK,IAAI;AAExB,OAAG,WAAW;AACd,UAAM,QAAQ,GAAG,OAAO,OAAO;AAC/B,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,KAAK,CAAC;AAC3C,UAAM,KAAK,QAAQ,MAAM,GAAG,KAAK,GAAG,UAAU,IAAI;AAClD,SAAK,OAAO,MAAM,MAAM,4BAAqB,GAAG,QAAQ;AAAA,EAC1D;AAAA,EAEA,oBAAoB,KAAoB,OAAqB,UAAwB;AACnF,QAAI,MAAM,YAAY,cAAc;AAClC,WAAK,OAAO,MAAM,IAAI,MAAM,+BAA0B,QAAQ;AAC9D;AAAA,IACF;AACA,UAAM;AACN,UAAM,QAAQ,kBAAkB,KAAK,IAAI,GAAG,MAAM,WAAW,CAAC;AAC9D,SAAK,OAAO,MAAM,IAAI,MAAM,0BAAmB,MAAM,QAAQ,IAAI,YAAY,OAAO,KAAK,SAAS,QAAQ;AAC1G,eAAW,MAAM,KAAK,KAAK,QAAQ,MAAM,KAAK,UAAU,IAAI,GAAG,KAAK;AAAA,EACtE;AACF;;;AC3CO,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EACA;AAAA,EAEjB,YAAY,MAAwB;AAClC,SAAK,QAAQ,KAAK;AAClB,SAAK,SAAS,KAAK;AAAA,EACrB;AAAA,EAEA,MAAM,WAA0B;AAC9B,eAAW,CAAC,MAAM,EAAE,KAAK,KAAK,OAAO;AACnC,UAAI,CAAC,GAAG,OAAO,GAAG,WAAW,QAAQ;AACnC,WAAG,SAAS,GAAG,WAAW,SAAS,SAAS;AAC5C;AAAA,MACF;AAGA,YAAM,iBAAiB,GAAG,IAAI,aAAa,eAAe,KAAK;AAC/D,UAAI,gBAAgB,KAAK,GAAG,aAAa,KAAK,IAAI,IAAI,GAAG,YAAY,eAAe;AAClF;AAAA,MACF;AACA,YAAM,OAAO,MAAM,YAAY,GAAG,IAAI,MAAM,GAAG,IAAI,WAAW;AAC9D,YAAM,OAAO,GAAG;AAChB,SAAG,SAAS,aAAa,MAAM,GAAG,MAAM;AACxC,UAAI,GAAG,WAAW,QAAQ,GAAG,WAAW,WAAY,IAAG,SAAS;AAChE,UAAI,SAAS,GAAG,OAAQ,MAAK,OAAO,cAAc,MAAM,EAAE;AAAA,IAC5D;AAAA,EACF;AACF;;;AC1BO,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAqB;AAC/B,SAAK,QAAQ,KAAK;AAClB,SAAK,QAAQ,KAAK;AAClB,SAAK,WAAW,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,MAAoB;AACvB,UAAM,KAAK,KAAK,MAAM,IAAI,IAAI;AAC9B,QAAI,CAAC,IAAI,QAAQ,CAAC,GAAG,IAAK;AAC1B,OAAG,kBAAkB;AACrB,SAAK,SAAS,SAAS,GAAG,GAAG;AAC7B,SAAK,cAAc,EAAE;AAAA,EACvB;AAAA;AAAA;AAAA,EAIA,cAAc,OAA2B;AACvC,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,CAAC,GAAG,IAAK;AACpB,QAAI;AAAE,WAAK,SAAS,SAAS,GAAG,GAAG;AAAA,IAAG,QAAQ;AAAA,IAAqB;AACnE,UAAM,YAAY;AAAA,EACpB;AAAA;AAAA;AAAA,EAIA,MAAM,QAAQ,OAAmC,CAAC,GAAkB;AAClE,UAAM,QAAQ,KAAK,iBAAiB;AACpC,UAAM,QAAQ,CAAC,GAAG,KAAK,KAAK;AAC5B,QAAI,CAAC,MAAM,OAAQ;AAEnB,eAAW,QAAQ,OAAO;AACxB,YAAM,KAAK,KAAK,gBAAgB,IAAI;AACpC,UAAI,IAAI;AACN,WAAG,kBAAkB;AACrB,aAAK,cAAc,EAAE;AAAA,MACvB;AACA,UAAI,KAAK,IAAK,MAAK,SAAS,SAAS,KAAK,GAAG;AAAA,IAC/C;AAGA,eAAW,MAAM,KAAK,MAAM,OAAO,EAAG,MAAK,cAAc,EAAE;AAE3D,UAAM,QAAQ,MAAM;AAAA,MAAI,OACtB,EAAE,aAAa,QAAQ,EAAE,eAAe,OACpC,QAAQ,QAAQ,IAChB,IAAI,QAAc,CAAAC,aAAW,EAAE,KAAK,SAAS,MAAMA,SAAQ,CAAC,CAAC;AAAA,IACnE;AAEA,QAAI,WAAW;AACf,UAAM,QAAQ,KAAK;AAAA,MACjB,QAAQ,IAAI,KAAK;AAAA,MACjB,IAAI,QAAc,CAAAA,aAAW,WAAW,MAAM;AAAE,mBAAW;AAAM,QAAAA,SAAQ;AAAA,MAAG,GAAG,KAAK,CAAC;AAAA,IACvF,CAAC;AAED,QAAI,UAAU;AACZ,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,OAAO,KAAK,aAAa,QAAQ,KAAK,eAAe,MAAM;AAClE,eAAK,SAAS,SAAS,KAAK,KAAK,SAAS;AAAA,QAC5C;AAAA,MACF;AACA,YAAM,QAAQ,KAAK;AAAA,QACjB,QAAQ,IAAI,KAAK;AAAA,QACjB,IAAI,QAAc,CAAAA,aAAW,WAAWA,UAAS,GAAI,CAAC;AAAA,MACxD,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,gBAAgB,MAA8C;AACpE,eAAW,MAAM,KAAK,MAAM,OAAO,EAAG,KAAI,GAAG,SAAS,KAAM,QAAO;AACnE,WAAO;AAAA,EACT;AACF;;;ANvEO,IAAM,iBAAN,MAAqB;AAAA,EACjB,QAAQ,oBAAI,IAA0B;AAAA,EAC9B,QAAQ,oBAAI,IAAkB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAKT;AACD,SAAK,UAAU,KAAK;AACpB,SAAK,MAAM,KAAK;AAChB,SAAK,SAAS,KAAK;AAEnB,SAAK,YAAY,IAAI,UAAU;AAAA,MAC7B,OAAO,KAAK;AAAA,MAAO,OAAO,KAAK;AAAA,MAAO,UAAU,KAAK;AAAA,IACvD,CAAC;AAID,QAAI,eAAiC;AACrC,SAAK,UAAU,IAAI,QAAQ;AAAA,MACzB,SAAS,KAAK;AAAA,MAAS,KAAK,KAAK;AAAA,MACjC,OAAO,KAAK;AAAA,MAAO,OAAO,KAAK;AAAA,MAC/B,QAAQ,KAAK;AAAA,MAAQ,WAAW,KAAK;AAAA,MACrC,SAAS,CAAC,KAAK,OAAO,aAAa,cAAc,oBAAoB,KAAK,OAAO,QAAQ;AAAA,IAC3F,CAAC;AACD,SAAK,YAAY,IAAI,UAAU;AAAA,MAC7B,OAAO,KAAK;AAAA,MAAO,QAAQ,KAAK;AAAA,MAChC,SAAS,KAAK;AAAA,MAAS,WAAW,KAAK;AAAA,IACzC,CAAC;AACD,mBAAe,KAAK;AAEpB,SAAK,eAAe,IAAI,aAAa;AAAA,MACnC,OAAO,KAAK;AAAA,MAAO,QAAQ,KAAK;AAAA,IAClC,CAAC;AAAA,EACH;AAAA,EAEA,QAAQ,KAAoB,UAAqC;AAC/D,UAAM,MAAMC,MAAK,KAAK,SAAS,IAAI,GAAG;AACtC,UAAM,MAAM,YAAY,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,YAAY;AAC9D,WAAO,eAAe,KAAK,KAAK,KAAK,SAAO,KAAK,OAAO,MAAM,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,EACnF;AAAA,EAEA,MAAM,KAAoB,UAAkB,YAAY,OAAsB;AAC5E,WAAO,KAAK,QAAQ,MAAM,KAAK,UAAU,SAAS;AAAA,EACpD;AAAA,EAEA,KAAK,MAAoB;AACvB,SAAK,UAAU,KAAK,IAAI;AAAA,EAC1B;AAAA,EAEA,QAAQ,MAA6B;AACnC,WAAO,KAAK,UAAU,QAAQ,IAAI;AAAA,EACpC;AAAA,EAEA,iBAAgC;AAC9B,WAAO,KAAK,aAAa,SAAS;AAAA,EACpC;AAAA,EAEA,QAAQ,OAAmC,CAAC,GAAkB;AAC5D,WAAO,KAAK,UAAU,QAAQ,IAAI;AAAA,EACpC;AACF;;;AO1FA,SAAS,cAAAC,aAAY,aAAAC,YAAW,YAAY,yBAA2C;AACvF,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,SAAS,WAAAC,gBAAe;AAajB,IAAM,UAAN,MAAc;AAAA,EACF;AAAA,EACA;AAAA,EACA,UAAU,oBAAI,IAAyB;AAAA,EACvC,OAAO,oBAAI,IAAY;AAAA,EAExC,YAAY,MAAmB;AAC7B,UAAM,OAAO,KAAK,WAAWF,MAAKE,SAAQ,GAAG,UAAU,MAAM;AAC7D,SAAK,MAAMF,MAAK,MAAM,SAAS,KAAK,WAAW,CAAC;AAChD,SAAK,gBAAgB,KAAK,iBAAiB;AAC3C,IAAAD,WAAU,KAAK,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACzC;AAAA;AAAA,EAGA,QAAQ,SAAyB;AAC/B,WAAOC,MAAK,KAAK,KAAK,GAAG,SAAS,OAAO,CAAC,MAAM;AAAA,EAClD;AAAA,EAEA,MAAM,SAAiB,MAAoB;AACzC,UAAM,SAAS,KAAK,UAAU,OAAO;AACrC,WAAO,MAAM,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,IAAI,IAAI;AAAA,CAAI;AAAA,EACtD;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,SAAS,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC,EAAE;AAAA,MACxC,OAAK,IAAI,QAAc,OAAK,EAAE,IAAI,MAAM,EAAE,CAAC,CAAC;AAAA,IAC9C;AACA,SAAK,QAAQ,MAAM;AACnB,SAAK,KAAK,MAAM;AAChB,UAAM,QAAQ,IAAI,MAAM;AAAA,EAC1B;AAAA,EAEQ,UAAU,SAA8B;AAC9C,QAAI,IAAI,KAAK,QAAQ,IAAI,OAAO;AAChC,QAAI,EAAG,QAAO;AACd,UAAM,OAAO,KAAK,QAAQ,OAAO;AACjC,QAAI,KAAK,iBAAiB,CAAC,KAAK,KAAK,IAAI,OAAO,KAAKF,YAAW,IAAI,GAAG;AACrE,UAAI;AACF,QAAAC,WAAUE,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,mBAAW,MAAM,OAAO,OAAO;AAAA,MACjC,QAAQ;AAAA,MAAoB;AAAA,IAC9B;AACA,SAAK,KAAK,IAAI,OAAO;AACrB,QAAI,kBAAkB,MAAM,EAAE,OAAO,IAAI,CAAC;AAC1C,MAAE,GAAG,SAAS,MAAM;AAAA,IAA+C,CAAC;AACpE,SAAK,QAAQ,IAAI,SAAS,CAAC;AAC3B,WAAO;AAAA,EACT;AACF;AAEA,SAAS,SAAS,MAAsB;AACtC,SAAO,KAAK,QAAQ,qBAAqB,GAAG,EAAE,QAAQ,YAAY,EAAE,KAAK;AAC3E;;;ACnEO,IAAM,cAAN,MAAqB;AAAA,EACT,OAAO,oBAAI,IAAoB;AAAA,EAEhD,UAAU,IAAgC;AACxC,SAAK,KAAK,IAAI,EAAE;AAChB,WAAO,MAAM,KAAK,KAAK,OAAO,EAAE;AAAA,EAClC;AAAA,EAEA,KAAK,GAAY;AACf,eAAW,MAAM,KAAK,MAAM;AAC1B,UAAI;AAAE,WAAG,CAAC;AAAA,MAAG,QAAQ;AAAA,MAAgD;AAAA,IACvE;AAAA,EACF;AACF;;;ACbA,SAAS,SAAAE,cAAgC;AACzC,SAAS,QAAAC,aAAY;AAKrB,IAAM,0BAA0B;AAwBhC,eAAsB,eACpB,WACA,MAC+B;AAC/B,QAAM,QAAwB,CAAC;AAC/B,QAAM,SAAmB,CAAC;AAE1B,aAAW,OAAO,WAAW;AAC3B,UAAM,OAAO,cAAc,KAAK,IAAI;AACpC,UAAM,KAAK,EAAE,KAAK,MAAM,KAAK,KAAK,OAAO,KAAK,CAAC;AAE/C,QAAI,CAAC,IAAI,aAAa;AACpB,WAAK,QAAQ,IAAI,MAAM,iCAA4B;AACnD;AAAA,IACF;AAEA,QAAI,IAAI,YAAY,SAAS,SAAS,CAAC,IAAI,MAAM;AAC/C,WAAK,QAAQ,IAAI,MAAM,6DAAmD;AAC1E;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,gBAAgB,2BAA2B;AAClE,UAAM,KAAK,MAAM,YAAY,KAAK,SAAS;AAC3C,QAAI,IAAI;AACN,WAAK,QAAQ,IAAI,MAAM,gBAAW;AAAA,IACpC,OAAO;AACL,WAAK,QAAQ,IAAI,MAAM,wCAAmC,YAAY,GAAI,IAAI;AAC9E,aAAO,KAAK,IAAI,IAAI;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,YAAY,OAAO,WAAW,GAAG,OAAO;AAC1D;AAGA,eAAsB,cACpB,OACA,UACA,OAAqG,CAAC,GACvF;AACf,aAAW,EAAE,KAAK,MAAM,IAAI,KAAK,OAAO;AACtC,QAAI;AACF,UAAI,IAAK,UAAS,SAAS,GAAG;AAC9B,UAAI,IAAI,SAAS;AACf,aAAK,QAAQ,IAAI,MAAM,aAAM,IAAI,OAAO,EAAE;AAC1C,cAAM,IAAI,QAAc,CAAAC,aAAW;AACjC,gBAAM,QAAQ,QAAQ,aAAa;AACnC,gBAAM,QAAQ,QAAQ,YAAY;AAClC,gBAAM,OAAO,QAAQ,OAAO;AAC5B,gBAAM,MAAM,IAAI,MAAMC,MAAK,KAAK,SAAS,IAAI,GAAG,IAAI,KAAK;AACzD,gBAAM,MAAM,EAAE,GAAG,KAAK,KAAK,GAAI,IAAI,YAAY,CAAC,EAAG;AACnD,gBAAM,QAAQC,OAAM,OAAO,CAAC,MAAM,IAAI,OAAQ,GAAG,EAAE,KAAK,KAAK,OAAO,SAAS,CAAC;AAC9E,gBAAM,GAAG,SAAS,MAAMF,SAAQ,CAAC;AACjC,gBAAM,GAAG,SAAS,MAAMA,SAAQ,CAAC;AAEjC,qBAAW,MAAMA,SAAQ,GAAG,GAAM;AAAA,QACpC,CAAC;AAAA,MACH;AAAA,IACF,QAAQ;AAAA,IAAoB;AAC5B,SAAK;AAAA,EACP;AACF;AAEA,SAAS,cAAc,KAAsB,MAAwC;AACnF,QAAM,QAAQ,QAAQ,aAAa;AACnC,QAAM,QAAQ,QAAQ,YAAY;AAClC,QAAM,OAAO,QAAQ,OAAO;AAC5B,QAAM,MAAM,IAAI,MAAMC,MAAK,KAAK,SAAS,IAAI,GAAG,IAAI,KAAK;AACzD,QAAM,MAAM,EAAE,GAAG,KAAK,KAAK,GAAI,IAAI,YAAY,CAAC,EAAG;AAEnD,OAAK,QAAQ,IAAI,MAAM,aAAM,IAAI,GAAG,EAAE;AACtC,QAAM,QAAQC,OAAM,OAAO,CAAC,MAAM,IAAI,GAAG,GAAG;AAAA,IAC1C;AAAA,IAAK;AAAA,IAAK,UAAU;AAAA,IAAM,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,EAC5D,CAAC;AACD,QAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,KAAK,QAAQ,IAAI,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACtF,QAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,KAAK,QAAQ,IAAI,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACtF,QAAM,GAAG,SAAS,SAAO,KAAK,QAAQ,IAAI,MAAM,uBAAkB,IAAI,OAAO,EAAE,CAAC;AAChF,SAAO;AACT;AAEA,eAAe,YAAY,KAAsB,WAAqC;AACpF,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,QAAM,OAAO,IAAI;AACjB,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI,MAAM,YAAY,MAAM,IAAI,WAAW,EAAG,QAAO;AACrD,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;;;ACtHA,OAAOC,UAAS;AAmBT,SAAS,gBAAgB,MAAgC;AAC9D,QAAM,EAAE,YAAY,YAAY,YAAY,eAAe,YAAY,SAAS,MAAM,IAAI;AAC1F,MAAI,YAAkD;AACtD,MAAI,eAAe,KAAK,IAAI;AAC5B,MAAI,WAAW;AACf,MAAI,eAAe;AACnB,MAAI,eAA6B,CAAC;AAClC,QAAM,cAAc,oBAAI,IAAgB;AAExC,WAAS,eAAe;AACtB,mBAAe,KAAK,IAAI;AAAA,EAC1B;AAEA,WAAS,oBAAoB;AAC3B,QAAI,UAAW,cAAa,SAAS;AACrC,QAAI,cAAc,EAAG;AACrB,UAAM,WAAW,aAAa;AAC9B,gBAAY,WAAW,MAAM;AAC3B,YAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,UAAI,YAAY,OAAO,KAAK,UAAU,UAAU;AAE9C,0BAAkB;AAClB;AAAA,MACF;AACA,qBAAe;AACf,cAAQ,kBAAW,UAAU,qBAAgB;AAC7C,iBAAW;AAAA,IACb,GAAG,QAAQ;AAAA,EACb;AAEA,WAAS,aAAa,QAAoB;AACxC,UAAM,SAASC,KAAI,iBAAiB,EAAE,MAAM,YAAY,MAAM,aAAa,eAAe,KAAK,CAAC;AAChG,gBAAY,IAAI,MAAM;AAEtB,UAAM,UAAU,MAAM;AACpB,kBAAY,OAAO,MAAM;AACzB,mBAAa;AAAA,IACf;AAEA,WAAO,GAAG,SAAS,MAAM;AAAE,aAAO,QAAQ;AAAG,cAAQ;AAAA,IAAG,CAAC;AACzD,WAAO,GAAG,SAAS,MAAM;AAAE,aAAO,QAAQ;AAAG,cAAQ;AAAA,IAAG,CAAC;AACzD,WAAO,GAAG,SAAS,OAAO;AAC1B,WAAO,GAAG,SAAS,OAAO;AAE1B,WAAO,GAAG,WAAW,MAAM;AACzB,aAAO,GAAG,QAAQ,CAAC,UAAU;AAAE,qBAAa;AAAG,YAAI,CAAC,OAAO,UAAW,QAAO,MAAM,KAAK;AAAA,MAAG,CAAC;AAC5F,aAAO,GAAG,QAAQ,CAAC,UAAU;AAAE,qBAAa;AAAG,YAAI,CAAC,OAAO,UAAW,QAAO,MAAM,KAAK;AAAA,MAAG,CAAC;AAC5F,aAAO,GAAG,OAAO,MAAM;AAAE,YAAI,CAAC,OAAO,UAAW,QAAO,IAAI;AAAA,MAAG,CAAC;AAC/D,aAAO,GAAG,OAAO,MAAM;AAAE,YAAI,CAAC,OAAO,UAAW,QAAO,IAAI;AAAA,MAAG,CAAC;AAAA,IACjE,CAAC;AAAA,EACH;AAEA,iBAAe,iBAAiB,QAAoB;AAClD,iBAAa;AACb,WAAO,GAAG,SAAS,MAAM;AAAA,IAAC,CAAC;AAE3B,QAAI,gBAAgB,QAAQ,GAAG;AAC7B,mBAAa,MAAM;AACnB;AAAA,IACF;AAEA,iBAAa,KAAK,MAAM;AACxB,WAAO,GAAG,SAAS,MAAM;AAAE,qBAAe,aAAa,OAAO,OAAK,MAAM,MAAM;AAAA,IAAG,CAAC;AAEnF,QAAI,SAAU;AACd,eAAW;AAEX,YAAQ,wBAAmB;AAC3B,QAAI,KAAK;AACT,QAAI;AACF,YAAM,cAAc;AACpB,WAAK,MAAM,YAAY,YAAY,EAAE,SAAS,MAAO,UAAU,IAAI,CAAC;AACpE,UAAI,GAAI,gBAAe;AAAA,UAClB,SAAQ,oCAA+B;AAAA,IAC9C,SAAS,GAAY;AACnB,cAAQ,wBAAoB,EAAY,OAAO,EAAE;AAAA,IACnD;AACA,eAAW;AAEX,UAAM,QAAQ,aAAa,OAAO,CAAC;AACnC,QAAI,CAAC,IAAI;AACP,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,KAAK,UAAW,MAAK,QAAQ;AAAA,MACpC;AACA;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,UAAI,CAAC,KAAK,UAAW,cAAa,IAAI;AAAA,IACxC;AAAA,EACF;AAEA,QAAM,SAASA,KAAI,aAAa,EAAE,eAAe,KAAK,GAAG,YAAU,iBAAiB,MAAM,CAAC;AAC3F,SAAO,OAAO,YAAY,SAAS;AACnC,oBAAkB;AAElB,SAAO;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,SAAS,MAAM;AACb,UAAI,UAAW,cAAa,SAAS;AACrC,mBAAa,QAAQ,OAAK,EAAE,QAAQ,CAAC;AACrC,kBAAY,QAAQ,OAAK,EAAE,QAAQ,CAAC;AACpC,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;;;AC5HA,SAAS,WAAW,mBAA+B;;;ACUnD,IAAM,iBAA0C;AAAA,EAC9C;AAAA,EAAO;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAY;AAAA,EAC7D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAe;AAAA,EAAgB;AAAA,EAAgB;AACzE;AAEA,SAAS,uBAAuB,MAAqB,MAA8B;AACjF,aAAW,KAAK,gBAAgB;AAC9B,QAAI,KAAK,UAAU,KAAK,CAAC,CAAC,MAAM,KAAK,UAAU,KAAK,CAAC,CAAC,EAAG,QAAO;AAAA,EAClE;AACA,SAAO;AACT;AAOO,SAAS,aAAa,MAAuB,MAAoC;AACtF,QAAM,aAAa,IAAI,IAAI,KAAK,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACrD,QAAM,aAAa,IAAI,IAAI,KAAK,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAErD,QAAM,QAAyB,CAAC;AAChC,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAA+D,CAAC;AACtE,QAAM,YAAsB,CAAC;AAE7B,aAAW,CAAC,MAAM,CAAC,KAAK,YAAY;AAClC,QAAI,CAAC,WAAW,IAAI,IAAI,GAAG;AAAE,cAAQ,KAAK,IAAI;AAAG;AAAA,IAAU;AAC3D,UAAM,IAAI,WAAW,IAAI,IAAI;AAC7B,QAAI,uBAAuB,GAAG,CAAC,EAAG,SAAQ,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;AAAA,QAC9D,WAAU,KAAK,IAAI;AAAA,EAC1B;AACA,aAAW,CAAC,MAAM,CAAC,KAAK,YAAY;AAClC,QAAI,CAAC,WAAW,IAAI,IAAI,EAAG,OAAM,KAAK,CAAC;AAAA,EACzC;AACA,SAAO,EAAE,OAAO,SAAS,SAAS,UAAU;AAC9C;AAGO,SAAS,cAAc,GAAwB;AACpD,QAAM,QAAkB,CAAC;AACzB,MAAI,EAAE,MAAM,OAAU,OAAM,KAAK,IAAI,EAAE,MAAM,MAAM,QAAQ;AAC3D,MAAI,EAAE,QAAQ,OAAQ,OAAM,KAAK,IAAI,EAAE,QAAQ,MAAM,UAAU;AAC/D,MAAI,EAAE,QAAQ,OAAQ,OAAM,KAAK,IAAI,EAAE,QAAQ,MAAM,UAAU;AAC/D,MAAI,CAAC,MAAM,OAAW,OAAM,KAAK,YAAY;AAC7C,SAAO,MAAM,KAAK,IAAI;AACxB;;;ADrCA,eAAsB,kBAAkB,MAAsC;AAC5E,QAAM,EAAE,YAAY,SAAS,SAAS,IAAI,IAAI;AAC9C,MAAI;AACF,UAAM,UAAU,MAAM,WAAW,UAAU;AAC3C,UAAM,OAAO,eAAe,SAAS,OAAO;AAC5C,QAAI,KAAK,QAAQ;AACf,UAAI;AAAA,EAA4B,uBAAuB,IAAI,CAAC,EAAE;AAC9D;AAAA,IACF;AACA,UAAM,cAAc,CAAC,GAAG,QAAQ,MAAM,OAAO,CAAC,EAAE,IAAI,OAAK,EAAE,GAAG;AAC9D,UAAM,OAAO,aAAa,aAAa,QAAQ,QAAQ;AACvD,QAAI,CAAC,KAAK,MAAM,UAAU,CAAC,KAAK,QAAQ,UAAU,CAAC,KAAK,QAAQ,OAAQ;AAExE,eAAW,QAAQ,KAAK,SAAS;AAC/B,cAAQ,KAAK,IAAI;AACjB,cAAQ,MAAM,OAAO,IAAI;AAAA,IAC3B;AACA,QAAI,WAAW,YAAY;AAC3B,eAAW,EAAE,KAAK,KAAK,KAAK,SAAS;AACnC,YAAM,OAAO,QAAQ,MAAM,IAAI,KAAK,IAAI;AACxC,YAAM,KAAK,MAAM,YAAY;AAC7B,cAAQ,KAAK,KAAK,IAAI;AAEtB,YAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AACzC,YAAM,QAAQ,QAAQ,MAAM,EAAE;AAC9B,YAAM,QAAQ,MAAM,MAAM,IAAI,IAAI;AAAA,IACpC;AACA,eAAW,QAAQ,KAAK,OAAO;AAC7B,YAAM,KAAK;AACX,YAAM,QAAQ,QAAQ,MAAM,EAAE;AAC9B,YAAM,QAAQ,MAAM,MAAM,EAAE;AAAA,IAC9B;AACA,QAAI,8BAAuB,cAAc,IAAI,CAAC,EAAE;AAAA,EAClD,SAAS,GAAQ;AACf,QAAI,+BAA0B,EAAE,OAAO,EAAE;AAAA,EAC3C;AACF;AAQO,SAAS,YAAY,MAAmC;AAC7D,MAAI,gBAAuC;AAC3C,MAAI,iBAAiB;AACrB,MAAI,cAAc;AAElB,QAAM,UAAU,YAAY;AAC1B,QAAI,gBAAgB;AAAE,oBAAc;AAAM;AAAA,IAAQ;AAClD,qBAAiB;AACjB,QAAI;AACF,YAAM,kBAAkB,IAAI;AAAA,IAC9B,UAAE;AACA,uBAAiB;AACjB,UAAI,aAAa;AAAE,sBAAc;AAAO,aAAK,QAAQ;AAAA,MAAG;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,MAAa,SAAgB;AAE7C,QAAI,KAAK,YAAY,KAAK,WAAW,KAAK,SAAS,KAAK,KAAM;AAC9D,QAAI,cAAe,cAAa,aAAa;AAC7C,oBAAgB,WAAW,MAAM,KAAK,QAAQ,GAAG,GAAG;AAAA,EACtD;AAEA,YAAU,KAAK,YAAY,EAAE,UAAU,IAAI,GAAG,QAAQ;AAEtD,SAAO,MAAM;AACX,QAAI,cAAe,cAAa,aAAa;AAC7C,gBAAY,KAAK,YAAY,QAAQ;AAAA,EACvC;AACF;;;AZnEA,IAAM,OAAO;AACb,IAAMC,YAAW,CAAC,MAAc,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,YAAY,EAAE,KAAK;AAChF,IAAM,WAAW,MAAMC,MAAKC,SAAQ,GAAG,QAAQ;AAExC,SAAS,WAAW,aAA6B;AACtD,SAAOD,MAAK,SAAS,GAAG,GAAGD,UAAS,WAAW,CAAC,MAAM;AACxD;AACO,SAAS,iBAAiB,aAA6B;AAC5D,SAAOC,MAAK,SAAS,GAAG,GAAGD,UAAS,WAAW,CAAC,aAAa;AAC/D;AAEA,SAAS,SAAS,KAAsB;AACtC,MAAI;AAAE,YAAQ,KAAK,KAAK,CAAC;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAO;AACnE;AAIO,SAAS,gBAAgB,aAA6D;AAC3F,QAAM,OAAO,WAAW,WAAW;AACnC,MAAI,CAACG,aAAW,IAAI,EAAG,QAAO,EAAE,KAAK,MAAM,OAAO,MAAM;AACxD,MAAI;AACJ,MAAI;AACF,UAAM,OAAOC,cAAa,MAAM,MAAM,EAAE,KAAK,CAAC;AAC9C,QAAI,CAAC,OAAO,CAAC,OAAO,SAAS,GAAG,EAAG,QAAO,EAAE,KAAK,MAAM,OAAO,KAAK;AAAA,EACrE,QAAQ;AACN,WAAO,EAAE,KAAK,MAAM,OAAO,KAAK;AAAA,EAClC;AACA,SAAO,SAAS,GAAG,IAAI,EAAE,KAAK,OAAO,MAAM,IAAI,EAAE,KAAK,OAAO,KAAK;AACpE;AAkBA,eAAsB,WAAW,MAAiC;AAChE,QAAM,EAAE,QAAQ,UAAU,SAAS,UAAU,KAAK,SAAS,eAAe,UAAU,IAAI;AACxF,QAAM,cAAc,OAAO;AAC3B,QAAM,UAAU,iBAAiB,WAAW;AAC5C,QAAM,UAAU,WAAW,WAAW;AAEtC,EAAAC,WAAU,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACzC,MAAIF,aAAW,OAAO,GAAG;AAAE,QAAI;AAAE,MAAAG,YAAW,OAAO;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EAAE;AAG/E,QAAM,UAAU,IAAI,QAAQ,EAAE,aAAa,SAAS,QAAQ,OAAO,CAAC;AAEpE,QAAM,SAAS,IAAI,YAA2C;AAC9D,QAAM,WAAW,IAAI,YAAmD;AACxE,QAAM,cAAc,oBAAI,IAAuB;AAC/C,QAAM,aAAa,oBAAI,IAA2C;AAClE,MAAI,YAA4B,CAAC;AACjC,MAAI,SAAoC;AACxC,MAAI,cAAqC;AACzC,MAAI,aAAoC;AACxC,MAAI,oBAAyC;AAE7C,QAAM,gBAAgB,CAAC,SAAiB;AACtC,YAAQ,MAAM,SAAS,IAAI;AAC3B,WAAO,KAAK,EAAE,KAAK,SAAS,KAAK,CAAC;AAAA,EACpC;AAEA,QAAM,MAAM,IAAI,eAAe;AAAA,IAC7B;AAAA,IAAS;AAAA,IAAK;AAAA,IACd,QAAQ;AAAA,MACN,OAAO,CAAC,SAAS,SAAS;AACxB,gBAAQ,MAAM,SAAS,IAAI;AAC3B,eAAO,KAAK,EAAE,KAAK,SAAS,KAAK,CAAC;AAAA,MACpC;AAAA,MACA,eAAe,CAAC,MAAM,UAAU,SAAS,KAAK,EAAE,MAAM,MAAM,CAAC;AAAA,IAC/D;AAAA,EACF,CAAC;AAED,QAAM,UAAU,YAA2B;AACzC,QAAI,YAAa,eAAc,WAAW;AAC1C,QAAI,WAAY,eAAc,UAAU;AACxC,QAAI,mBAAmB;AAAE,UAAI;AAAE,0BAAkB;AAAA,MAAG,QAAQ;AAAA,MAAe;AAAA,IAAE;AAC7E,eAAW,KAAK,YAAY,OAAO,EAAG,GAAE,QAAQ;AAChD,QAAI,OAAQ,OAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC/C,UAAM,IAAI,QAAQ,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAClC,QAAI,UAAU,QAAQ;AACpB,YAAM,cAAc,WAAW,UAAU;AAAA,QACvC;AAAA,QAAS;AAAA,QACT,OAAO,CAAC,KAAK,QAAQ,QAAQ,MAAM,OAAO,GAAG,IAAI,GAAG;AAAA,MACtD,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AACA,QAAI,iBAAiB,aAAa,QAAQ,OAAO;AAC/C,UAAI;AAAE,sBAAc,MAAM,SAAS;AAAA,MAAG,QAAQ;AAAA,MAAe;AAAA,IAC/D;AACA,UAAM,QAAQ,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACpC,QAAIH,aAAW,OAAO,GAAG;AAAE,UAAI;AAAE,QAAAG,YAAW,OAAO;AAAA,MAAG,QAAQ;AAAA,MAAe;AAAA,IAAE;AAAA,EACjF;AAEA,MAAI,eAAe;AACnB,QAAM,WAAW,MAAM;AACrB,QAAI,aAAc;AAClB,mBAAe;AACf,YAAQ,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC,GAAG,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,EAC7D;AACA,UAAQ,GAAG,WAAW,QAAQ;AAC9B,UAAQ,GAAG,UAAU,QAAQ;AAE7B,MAAI;AAEF,QAAI,OAAO,UAAU,QAAQ;AAC3B,oBAAc,qBAAgB,OAAO,SAAS,MAAM,GAAG;AACvD,YAAM,SAAS,MAAM,eAAe,OAAO,UAAU;AAAA,QACnD;AAAA,QAAS;AAAA,QAAK;AAAA,QACd,OAAO,CAAC,KAAK,QAAQ;AAAE,kBAAQ,MAAM,OAAO,GAAG,IAAI,GAAG;AAAG,iBAAO,KAAK,EAAE,KAAK,OAAO,GAAG,IAAI,MAAM,IAAI,CAAC;AAAA,QAAG;AAAA,MAC1G,CAAC;AACD,kBAAY,OAAO;AACnB,UAAI,CAAC,OAAO,YAAY;AACtB,cAAM,IAAI,MAAM,qBAAqB,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,MACjE;AAAA,IACF;AAGA,QAAI,QAAQ,QAAQ,OAAO,MAAM;AAC/B,YAAM,SAAS,KAAK,UAAU,OAAO,MAAM,QAAQ,aAAa,WAAW;AAAA,IAC7E,OAAO;AACL,YAAM,WAAW,KAAK,QAAQ;AAAA,IAChC;AAGA,aAAS,MAAM,kBAAkB,aAAa;AAAA,MAC5C,QAAQ,MAAM,IAAI;AAAA,MAClB,SAAS,CAAC,MAAM,IAAI,QAAQ,CAAC;AAAA,MAC7B,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC;AAAA,MACvB,UAAU,OAAO,SAAS,UAAU;AAClC,cAAM,OAAO,QAAQ,QAAQ,OAAO;AACpC,YAAI,CAACH,aAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,eAAO,IAAI,QAAkB,CAACI,UAAS,WAAW;AAChD,gBAAM,MAAgB,CAAC;AACvB,gBAAM,KAAKC,iBAAgB,EAAE,OAAO,iBAAiB,MAAM,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC;AAClF,aAAG,GAAG,QAAQ,OAAK;AAAE,gBAAI,KAAK,CAAC;AAAG,gBAAI,IAAI,SAAS,MAAO,KAAI,MAAM;AAAA,UAAG,CAAC;AACxE,aAAG,GAAG,SAAS,MAAMD,SAAQ,GAAG,CAAC;AACjC,aAAG,GAAG,SAAS,MAAM;AAAA,QACvB,CAAC;AAAA,MACH;AAAA,MACA,WAAW,CAAC,SAAS,WAAW,OAAO,UAAU,CAAC,EAAE,KAAK,KAAK,MAAM;AAClE,YAAI,YAAY,QAAQ,QAAQ,QAAS,QAAO,KAAK,IAAI;AAAA,MAC3D,CAAC;AAAA,MACD,aAAa,CAAC,aAAa,SAAS,UAAU,CAAC,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,KAAK,CAAC;AAAA,MACxF,MAAM,WAAW;AACf,cAAM,OAAiB,CAAC;AACxB,cAAM,YAAY,oBAAI,IAAoB;AAC1C,mBAAW,CAAC,MAAM,EAAE,KAAK,IAAI,OAAO;AAClC,cAAI,GAAG,KAAK;AAAE,iBAAK,KAAK,GAAG,GAAG;AAAG,sBAAU,IAAI,GAAG,KAAK,IAAI;AAAA,UAAG;AAAA,QAChE;AACA,cAAM,MAAM,KAAK,SAAS,MAAM,SAAS,gBAAgB,IAAI,IAAI,oBAAI,IAAI;AACzE,cAAME,YAA2D,CAAC;AAClE,mBAAW,CAAC,IAAI,KAAK,IAAI,OAAO;AAC9B,UAAAA,UAAS,IAAI,IAAI,EAAE,KAAK,GAAG,OAAO,EAAE;AAAA,QACtC;AACA,mBAAW,CAAC,KAAK,IAAI,KAAK,KAAK;AAC7B,gBAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,cAAI,CAAC,KAAM;AACX,gBAAM,OAAO,WAAW,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,EAAE;AAChE,gBAAM,MAAM,eAAe,KAAK,YAAY,KAAK,KAAK,KAAK,IAAI;AAC/D,qBAAW,IAAI,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,KAAK,WAAW,CAAC;AAC/D,UAAAA,UAAS,IAAI,IAAI,EAAE,KAAK,KAAK,MAAM,MAAM,EAAE,IAAI,IAAI,OAAO,KAAK,MAAO,KAAK,MAAM,OAAQ,EAAE,IAAI,GAAG;AAAA,QACpG;AACA,eAAO;AAAA,UACL,UAAAA;AAAA,UACA,QAAQ;AAAA,YACN,YAAY,KAAK,MAAM,SAAS,IAAI,OAAO,IAAI;AAAA,YAC/C,WAAW,KAAK,MAAM,QAAQ,IAAI,OAAO,IAAI;AAAA,YAC7C,UAAU,KAAK,EAAE;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,MACA,eAAe;AACb,YAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,QAAQ,MAAO,QAAO;AAC3D,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,UAAU,cAAc;AAAA,UACxB,QAAQ,UAAU;AAAA,UAClB,KAAK,UAAU;AAAA,UACf,QAAQ,UAAU;AAAA,QACpB;AAAA,MACF;AAAA,IACF,GAAG,EAAE,OAAO,SAAO,cAAc,GAAG,EAAE,CAAC;AAGvC,kBAAc,YAAY,MAAM;AAAE,WAAK,IAAI,eAAe;AAAA,IAAG,GAAG,GAAI;AAGpE,QAAI,iBAAiB,aAAa,QAAQ,OAAO;AAC/C,UAAI,cAA6B;AACjC,YAAM,OAAO,MAAM;AACjB,cAAM,YAAY,oBAAI,IAA0B;AAChD,mBAAW,CAAC,GAAG,EAAE,KAAK,IAAI,OAAO;AAC/B,oBAAU,IAAI,GAAG,EAAE,MAAM,GAAG,IAAI,MAAM,QAAQ,GAAG,QAAQ,UAAW,GAAG,IAA8B,SAAS,CAAC;AAAA,QACjH;AACA,cAAM,UAAU,cAAc,SAAS,WAAW,SAAS;AAC3D,YAAI,YAAY,YAAa;AAC7B,sBAAc;AACd,YAAI;AAAE,wBAAc,MAAM,SAAS,SAAS;AAAA,QAAG,QAAQ;AAAA,QAA6B;AAAA,MACtF;AACA,WAAK;AACL,mBAAa,YAAY,MAAM,GAAI;AAAA,IACrC;AAGA,QAAI,QAAQ,aAAa;AACvB,UAAI;AACF,cAAM,aAAa,eAAe,SAAS,QAAQ,UAAU;AAC7D,sBAAc,sBAAe,UAAU,EAAE;AACzC,4BAAoB,YAAY;AAAA,UAC9B;AAAA,UAAY;AAAA,UAAS,SAAS;AAAA,UAC9B,KAAK,SAAO,cAAc,GAAG;AAAA,QAC/B,CAAC;AAAA,MACH,SAAS,GAAQ;AACf,sBAAc,iCAA4B,EAAE,WAAW,OAAO,CAAC,CAAC,EAAE;AAAA,MACpE;AAAA,IACF;AAGA,IAAAC,eAAc,SAAS,OAAO,QAAQ,GAAG,CAAC;AAC1C,kBAAc,4BAAuB,QAAQ,GAAG,GAAG;AAAA,EAIrD,SAAS,GAAQ;AACf,QAAI;AAAE,MAAAA,eAAc,SAAS,EAAE,WAAW,OAAO,CAAC,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAe;AAC7E,QAAI;AAAE,oBAAc,uBAAkB,EAAE,WAAW,OAAO,CAAC,CAAC,EAAE;AAAA,IAAG,QAAQ;AAAA,IAAe;AACxF,UAAM,QAAQ,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,eAAe,WAAW,KAAqB,UAA0C;AACvF,QAAM,SAAS,aAAa,QAAQ;AACpC,MAAI,WAAW;AACf,aAAW,OAAO,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG;AACvE,eAAW,OAAO,OAAO,GAAG,GAAI;AAC9B,YAAM,KAAK;AACX,YAAM,IAAI,QAAQ,KAAK,EAAE;AACzB,YAAM,IAAI,MAAM,KAAK,EAAE;AAAA,IACzB;AACA,UAAM,OAAO,OAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK;AACtD,QAAI,KAAK,OAAQ,OAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,YAAY,EAAE,MAAM,EAAE,SAAS,KAAM,CAAC,CAAC,CAAC;AACzF,WAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,OAAK;AACtD,YAAM,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI;AAC/B,UAAI,GAAI,IAAG,SAAS;AAAA,IACtB,CAAC;AAAA,EACH;AACF;AAEA,eAAe,SACb,KACA,UACA,SACA,aACA,aACe;AACf,QAAM,EAAE,UAAU,KAAK,IAAI,iBAAiB,UAAU,OAAO;AAC7D,QAAM,SAAS,aAAa,QAAQ;AACpC,MAAI,WAAW;AACf,aAAW,OAAO,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG;AACvE,eAAW,OAAO,OAAO,GAAG,GAAI;AAC9B,YAAM,KAAK;AACX,YAAM,IAAI,QAAQ,KAAK,EAAE;AACzB,YAAM,IAAI,MAAM,KAAK,EAAE;AAAA,IACzB;AACA,UAAM,OAAO,OAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK;AACtD,QAAI,KAAK,OAAQ,OAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,YAAY,EAAE,MAAM,EAAE,SAAS,KAAM,CAAC,CAAC,CAAC;AACzF,WAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,OAAK;AACtD,YAAM,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI;AAC/B,UAAI,GAAI,IAAG,SAAS;AAAA,IACtB,CAAC;AAAA,EACH;AACA,aAAW,OAAO,MAAM;AACtB,UAAM,KAAK;AACX,UAAM,YAAY,mBAAmB,GAAG;AACxC,QAAI,MAAM,IAAI,IAAI,MAAM;AAAA,MACtB,KAAK;AAAA,MAAW,MAAM;AAAA,MAAM,KAAK;AAAA,MACjC,QAAQ;AAAA,MAAQ,QAAQ;AAAA,MACxB,QAAQ;AAAA,MAAG,UAAU;AAAA,MAAG,WAAW;AAAA,MACnC,iBAAiB;AAAA,MAAO,UAAU;AAAA,IACpC,CAAC;AACD,UAAM,QAAQ,gBAAgB;AAAA,MAC5B,YAAY,IAAI;AAAA,MAAM,YAAY,UAAU;AAAA,MAAU,YAAY;AAAA,MAClE,eAAe,YAAY;AACzB,cAAM,IAAI,QAAQ,WAAW,EAAE;AAC/B,cAAM,IAAI,MAAM,WAAW,EAAE;AAC7B,cAAM,KAAK,MAAM,YAAY,UAAU,UAAU,EAAE,SAAS,KAAM,CAAC;AACnE,cAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,YAAI,IAAI;AAAE,aAAG,SAAS,KAAK,YAAY;AAAW,cAAI,GAAI,IAAG,SAAS;AAAA,QAAM;AAAA,MAC9E;AAAA,MACA,YAAY,MAAM;AAChB,YAAI,KAAK,IAAI,IAAI;AACjB,cAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,YAAI,IAAI;AAAE,aAAG,SAAS;AAAQ,aAAG,SAAS;AAAQ,aAAG,MAAM;AAAM,aAAG,OAAO;AAAM,aAAG,YAAY;AAAA,QAAM;AAAA,MACxG;AAAA,MACA,SAAS,MAAM;AACb,cAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,eAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,KAAK,UAAU,GAAG,WAAW;AAAA,MAC/D;AAAA,IACF,CAAC;AACD,gBAAY,IAAI,IAAI,MAAM,KAAK;AAAA,EACjC;AACF;AAWA,eAAsB,YAAY,MAAqC;AACrE,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,OAAO,MAAM,IAAI,IAAI;AACrE,QAAM,cAAc,KAAK,OAAO;AAEhC,MAAI,QAAQ,aAAa,SAAS;AAChC,QAAI,uGAAkG;AACtG,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,gBAAgB,WAAW;AAC5C,MAAI,SAAS,OAAO,CAAC,SAAS,OAAO;AACnC,QAAI,sCAAiC,WAAW,UAAU,SAAS,GAAG,mCAAmC;AACzG,WAAO;AAAA,EACT;AACA,MAAI,SAAS,OAAO;AAClB,QAAI,uCAAkC,WAAW,GAAG;AACpD,QAAI;AAAE,MAAAJ,YAAW,WAAW,WAAW,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EACpE;AAEA,EAAAD,WAAU,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACzC,QAAM,UAAU,iBAAiB,WAAW;AAC5C,QAAM,UAAU,WAAW,WAAW;AACtC,MAAIF,aAAW,OAAO,GAAG;AAAE,QAAI;AAAE,MAAAG,YAAW,OAAO;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EAAE;AAG/E,QAAM,eAAe,QAAQ,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,KAAK,MAAM;AAC5D,QAAI,MAAM,KAAK,QAAQ,KAAM,QAAO;AACpC,QAAI,QAAQ,QAAQ,QAAQ,WAAY,QAAO;AAC/C,WAAO;AAAA,EACT,CAAC;AAED,MAAI,+CAA0C,WAAW,MAAM;AAG/D,QAAM,QAAQK,OAAM,QAAQ,UAAU,CAAC,GAAG,QAAQ,UAAU,QAAQ,KAAK,CAAC,GAAI,GAAG,YAAY,GAAG;AAAA,IAC9F,UAAU;AAAA,IACV,OAAO;AAAA,IACP,KAAK,EAAE,GAAG,QAAQ,KAAK,oBAAoB,IAAI;AAAA,IAC/C,KAAK,KAAK;AAAA,EACZ,CAAC;AACD,QAAM,MAAM;AAGZ,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAIR,aAAW,OAAO,GAAG;AACvB,YAAM,MAAM,OAAOC,cAAa,SAAS,MAAM,EAAE,KAAK,CAAC;AACvD,UAAI,EAAE;AACN,UAAI,iCAA0B,GAAG,GAAG;AACpC,UAAI,+BAA+B;AACnC,UAAI,4CAA4C;AAChD,UAAI,yBAAyB;AAC7B,aAAO;AAAA,IACT;AACA,QAAID,aAAW,OAAO,GAAG;AACvB,YAAM,MAAMC,cAAa,SAAS,MAAM,EAAE,KAAK;AAC/C,UAAI,8BAAyB,GAAG,EAAE;AAClC,UAAI;AAAE,QAAAE,YAAW,OAAO;AAAA,MAAG,QAAQ;AAAA,MAAe;AAClD,aAAO;AAAA,IACT;AACA,UAAM,MAAM,GAAG;AAAA,EACjB;AAEA,MAAI,qEAAgE,MAAM,GAAG,IAAI;AACjF,MAAI,MAAM,KAAK;AAAE,QAAI;AAAE,cAAQ,KAAK,MAAM,KAAK,SAAS;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EAAE;AACpF,SAAO;AACT;AAIA,eAAsB,WACpB,aACA,OAAiE,CAAC,GACjD;AACjB,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,OAAO,MAAM,IAAI,IAAI;AACrE,QAAM,QAAQ,KAAK,iBAAiB;AACpC,QAAM,SAAS,gBAAgB,WAAW;AAE1C,MAAI,CAAC,OAAO,KAAK;AACf,QAAI,iCAA4B,WAAW,IAAI;AAC/C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,OAAO;AAChB,QAAI,8BAAyB,WAAW,UAAU,OAAO,GAAG,wBAAwB;AACpF,QAAI;AAAE,MAAAA,YAAW,WAAW,WAAW,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAe;AAClE,WAAO;AAAA,EACT;AAEA,MAAI,+BAA0B,OAAO,GAAG,MAAM;AAC9C,MAAI;AACF,YAAQ,KAAK,OAAO,KAAK,SAAS;AAAA,EACpC,SAAS,GAAQ;AACf,QAAI,4BAAuB,OAAO,GAAG,KAAK,EAAE,OAAO,EAAE;AACrD,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI,CAAC,SAAS,OAAO,GAAG,GAAG;AACzB,UAAI,8BAAyB,OAAO,GAAG,GAAG;AAC1C,YAAMM,KAAI,WAAW,WAAW;AAChC,UAAIT,aAAWS,EAAC,GAAG;AAAE,YAAI;AAAE,UAAAN,YAAWM,EAAC;AAAA,QAAG,QAAQ;AAAA,QAAe;AAAA,MAAE;AACnE,aAAO;AAAA,IACT;AACA,UAAM,MAAM,GAAG;AAAA,EACjB;AAEA,MAAI,sCAAiC,QAAQ,KAAM,QAAQ,CAAC,CAAC,qBAAqB;AAClF,MAAI;AAAE,YAAQ,KAAK,OAAO,KAAK,SAAS;AAAA,EAAG,QAAQ;AAAA,EAAe;AAClE,QAAM,IAAI,WAAW,WAAW;AAChC,MAAIT,aAAW,CAAC,GAAG;AAAE,QAAI;AAAE,MAAAG,YAAW,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EAAE;AACnE,SAAO;AACT;;;AbhcA,IAAM,QAAQ,oBAAI,IAAI,CAAC,QAAQ,WAAW,UAAU,QAAQ,OAAO,MAAM,MAAM,CAAC;AAGzE,SAAS,iBAAiB,MAA+B;AAC9D,QAAM,QAAQ,KAAK,CAAC;AACpB,SAAO,SAAS,MAAM,IAAI,KAAK,IAAI,QAAQ;AAC7C;AAUA,SAAS,QAAQ,QAAwB,UAA2B;AAClE,QAAM,OAAO,YAAYO,MAAKC,SAAQ,GAAG,UAAU,MAAM;AACzD,SAAOD,MAAK,MAAME,UAAS,OAAO,IAAI,CAAC;AACzC;AAEA,SAASA,UAAS,MAAsB;AACtC,SAAO,KAAK,QAAQ,qBAAqB,GAAG,EAAE,QAAQ,YAAY,EAAE,KAAK;AAC3E;AAIA,eAAsB,QAAQ,MAAgB,MAAgC;AAC5E,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,QAAM,SAAS,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,IAAI;AAC9D,QAAM,SAAS,KAAK,KAAK,OAAK,CAAC,EAAE,WAAW,GAAG,CAAC;AAChD,MAAI,CAAC,QAAQ;AACX,QAAI,wCAAwC;AAC5C,WAAO;AAAA,EACT;AACA,QAAM,YAAY,KAAK,OAAO,SAAS,IAAI,OAAK,EAAE,IAAI;AACtD,MAAI,CAAC,UAAU,SAAS,MAAM,GAAG;AAC/B,QAAI,oBAAoB,MAAM,aAAa,UAAU,KAAK,IAAI,CAAC,EAAE;AACjE,WAAO;AAAA,EACT;AACA,QAAM,OAAOF,MAAK,QAAQ,KAAK,QAAQ,KAAK,MAAM,GAAG,GAAGE,UAAS,MAAM,CAAC,MAAM;AAC9E,MAAI,CAACC,aAAW,IAAI,GAAG;AACrB,QAAI,wBAAwB,MAAM,MAAM,IAAI,GAAG;AAC/C,WAAO,SAAS,MAAM,WAAW,MAAM,GAAG,IAAI;AAAA,EAChD;AACA,QAAM,WAAW,MAAM,GAAG;AAC1B,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,MAAM,WAAW,MAAM,KAAKC,UAAS,IAAI,EAAE,IAAI;AACxD;AAEA,eAAe,WAAW,MAAc,KAAyC;AAC/E,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAM,KAAKC,iBAAgB,EAAE,OAAOC,kBAAiB,MAAM,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC;AAClF,OAAG,GAAG,QAAQ,OAAK,IAAI,CAAC,CAAC;AACzB,OAAG,GAAG,SAAS,MAAMF,SAAQ,CAAC;AAC9B,OAAG,GAAG,SAAS,MAAM;AAAA,EACvB,CAAC;AACH;AAEA,eAAe,WAAW,MAAc,KAA0B,UAAU,GAAoB;AAC9F,MAAI,MAAM;AAEV,SAAO,CAACF,aAAW,IAAI,EAAG,OAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AACnE,SAAO,IAAI,QAAQ,CAAAE,aAAW;AAC5B,UAAM,OAAO,YAAY;AACvB,YAAM,OAAOD,UAAS,IAAI,EAAE;AAC5B,UAAI,OAAO,KAAK;AACd,cAAM,IAAI,QAAc,SAAO;AAC7B,gBAAM,KAAKE,iBAAgB,EAAE,OAAOC,kBAAiB,MAAM,EAAE,UAAU,QAAQ,OAAO,KAAK,KAAK,OAAO,EAAE,CAAC,EAAE,CAAC;AAC7G,aAAG,GAAG,QAAQ,OAAK,IAAI,CAAC,CAAC;AACzB,aAAG,GAAG,SAAS,MAAM;AAAE,kBAAM;AAAM,gBAAI;AAAA,UAAG,CAAC;AAAA,QAC7C,CAAC;AAAA,MACH,WAAW,OAAO,KAAK;AAErB,cAAM;AAAA,MACR;AAAA,IACF;AACA,IAAAC,WAAU,MAAM,EAAE,UAAU,IAAI,GAAG,MAAM;AAAE,WAAK,KAAK;AAAA,IAAG,CAAC;AACzD,YAAQ,KAAK,UAAU,MAAM;AAAE,MAAAC,aAAY,IAAI;AAAG,MAAAJ,SAAQ,CAAC;AAAA,IAAG,CAAC;AAAA,EACjE,CAAC;AACH;AAIA,eAAsB,WAAW,MAA2D;AAC1F,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,QAAQ,KAAK,OAAO,SAAS,IAAI,QAAM,EAAE,MAAM,EAAE,MAAM,KAAKL,MAAK,KAAK,SAAS,EAAE,GAAG,EAAE,EAAE;AAC9F,QAAM,QAAQ,CAAC,GAAG,KAAK;AACvB,QAAM,SAAmB,CAAC;AAC1B,MAAI,WAAW;AAEf,QAAM,IAAI,QAAc,CAAAK,aAAW;AACjC,UAAM,OAAO,MAAM;AACjB,aAAO,WAAW,eAAe,MAAM,QAAQ;AAC7C,cAAM,OAAO,MAAM,MAAM;AACzB;AACA,mBAAW,KAAK,KAAK,KAAK,GAAG,EAAE,KAAK,QAAM;AACxC;AACA,cAAI,GAAI,KAAI,UAAK,KAAK,IAAI,EAAE;AAAA,eACvB;AAAE,mBAAO,KAAK,KAAK,IAAI;AAAG,gBAAI,UAAK,KAAK,IAAI,EAAE;AAAA,UAAG;AACtD,cAAI,MAAM,WAAW,KAAK,aAAa,EAAG,CAAAA,SAAQ;AAAA,cAC7C,MAAK;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AACA,SAAK;AAAA,EACP,CAAC;AAED,MAAI,OAAO,QAAQ;AACjB,QAAI;AAAA,UAAa,OAAO,KAAK,IAAI,CAAC,EAAE;AACpC,WAAO;AAAA,EACT;AACA,MAAI;AAAA,EAAK,MAAM,MAAM,sBAAsB;AAC3C,SAAO;AACT;AAEA,SAAS,WAAW,KAAa,KAA+C;AAC9E,MAAI,CAACF,aAAW,GAAG,EAAG,QAAO,QAAQ,QAAQ,KAAK;AAClD,MAAI,CAAC,aAAa,GAAG,EAAG,QAAO,QAAQ,QAAQ,IAAI;AACnD,SAAO,IAAI,QAAQ,CAAAE,aAAW;AAC5B,UAAM,UAAU,QAAQ,aAAa,UAAU,YAAY;AAC3D,UAAM,OAAOK,OAAM,SAAS,CAAC,SAAS,GAAG,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,UAAU,MAAM,EAAE,CAAC;AAC1F,SAAK,GAAG,SAAS,UAAQ;AACvB,UAAI,SAAS,GAAG;AAAE,0BAAkB,GAAG;AAAG,QAAAL,SAAQ,IAAI;AAAA,MAAG,MAAO,CAAAA,SAAQ,KAAK;AAAA,IAC/E,CAAC;AACD,SAAK,GAAG,SAAS,MAAMA,SAAQ,KAAK,CAAC;AAAA,EACvC,CAAC;AACH;AAIA,eAAsB,UAAU,MAAgC;AAC9D,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,MAAI,GAAG,KAAK,OAAO,QAAQ,WAAI,IAAI,KAAK,OAAO,IAAI,WAAM,KAAK,OAAO,SAAS,MAAM,WAAW;AAC/F,MAAI,EAAE;AAEN,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,OAAO,SAAS,IAAI,OAAK,EAAE,KAAK,MAAM,GAAG,EAAE;AAC3E,MAAI,GAAG,UAAU,OAAO,MAAM,CAAC,KAAK,OAAO,SAAS,CAAC,CAAC,KAAK,OAAO,OAAO,CAAC,CAAC,UAAU;AACrF,MAAI,IAAI,OAAO,SAAS,EAAE,CAAC;AAE3B,aAAW,OAAO,KAAK,OAAO,UAAU;AACtC,UAAM,KAAK,MAAM,YAAY,IAAI,MAAM,IAAI,WAAW;AACtD,UAAM,SAAS,KAAK,cAAS;AAC7B,QAAI,GAAG,IAAI,KAAK,OAAO,MAAM,CAAC,KAAK,OAAO,IAAI,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,KAAK,OAAO,CAAC,CAAC,KAAK,MAAM,EAAE;AAAA,EACrG;AACA,SAAO;AACT;AAgBA,SAAS,UAAU,MAAoB,KAAgC;AACrE,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,OAAK,EAAE,KAAK,MAAM,GAAG,CAAC;AAC1D,aAAW,KAAK,MAAM;AACpB,UAAM,MAAM,EAAE,OAAO,OAAO,OAAO,EAAE,GAAG,KAAK;AAC7C,UAAM,OAAO,EAAE,KAAK,OAAO,MAAM;AACjC,UAAM,OAAO,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC;AACpC,UAAM,SAAS,EAAE,OAAO,OAAO,CAAC;AAChC,UAAM,SAAS,EAAE,OAAO,OAAO,CAAC;AAChC,QAAI,GAAG,IAAI,KAAK,IAAI,KAAK,MAAM,KAAK,MAAM,KAAK,GAAG,YAAY,EAAE,MAAM,cAAc,EAAE,QAAQ,EAAE;AAAA,EAClG;AACF;AAEA,eAAsB,OAAO,MAAgB,MAAgC;AAC3E,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,OAAO,MAAM,IAAI,IAAI;AACrE,QAAM,SAAS,KAAK,CAAC;AACrB,QAAM,SAAS,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,IAAI;AAC9D,QAAM,aAAa,cAAc,KAAK,OAAO,MAAM,KAAK,UAAU;AAElE,MAAI,CAAC,UAAU,WAAW,QAAQ;AAChC,QAAI,6CAA6C;AACjD,QAAI,0DAA0D;AAC9D,QAAI,kEAAkE;AACtE,QAAI,4EAA4E;AAChF,QAAI,kDAAkD;AACtD,QAAI,+CAA+C;AACnD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,uBAAmB,YAAY,KAAK,OAAO,IAAI;AAAA,EACjD,SAAS,GAAQ;AACf,QAAI,EAAE,OAAO;AACb,WAAO;AAAA,EACT;AAEA,MAAI;AACF,QAAI,WAAW,QAAQ;AACrB,YAAM,MAAM,MAAM,QAAQ,YAAY,MAAM;AAC5C,UAAI,YAAY,IAAI,EAAE,EAAE;AACxB,aAAO;AAAA,IACT;AAEA,QAAI,WAAW,YAAY,CAAC,QAAQ;AAClC,YAAM,MAAM,MAAM,QAAQ,YAAY,QAAQ;AAC9C,UAAI,CAAC,IAAI,SAAS,QAAQ;AAAE,YAAI,eAAe;AAAG,eAAO;AAAA,MAAG;AAC5D,gBAAU,IAAI,UAAU,GAAG;AAC3B,aAAO;AAAA,IACT;AAEA,QAAI,WAAW,YAAY,QAAQ;AACjC,aAAO,MAAM,IAAI,QAAgB,CAAAA,aAAW;AAC1C,cAAM,QAAQ,WAAW,YAAY,iBAAiB,CAAC,GAAG,WAAS;AACjE,gBAAM,OAAO,MAAM;AACnB,gBAAM,MAAK,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,IAAI,EAAE;AAChD,qBAAW,KAAK,MAAM;AACpB,gBAAI,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,MAAM,EAAE;AAAA,UAC7D;AAAA,QACF,GAAG,SAAO;AAAE,cAAI,UAAU,IAAI,OAAO,EAAE;AAAG,UAAAA,SAAQ,CAAC;AAAA,QAAG,CAAC;AACvD,gBAAQ,KAAK,UAAU,MAAM;AAAE,gBAAM;AAAG,UAAAA,SAAQ,CAAC;AAAA,QAAG,CAAC;AAAA,MACvD,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,QAAQ;AACrB,YAAM,MAAM,KAAK,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,EAAE,WAAW,GAAG,CAAC;AAC3D,UAAI,CAAC,KAAK;AAAE,YAAI,4CAA4C;AAAG,eAAO;AAAA,MAAG;AAEzE,UAAI,CAAC,QAAQ;AACX,cAAM,MAAM,MAAM,QAAQ,YAAY,aAAa,EAAE,KAAK,OAAO,IAAI,CAAC;AACtE,mBAAW,KAAK,IAAI,MAAO,KAAI,CAAC;AAChC,eAAO;AAAA,MACT;AAEA,aAAO,MAAM,IAAI,QAAgB,CAAAA,aAAW;AAC1C,cAAM,QAAQ,WAAW,YAAY,eAAe,EAAE,KAAK,MAAM,IAAI,GAAG,WAAS;AAC/E,cAAI,MAAM,IAAc;AAAA,QAC1B,GAAG,SAAO;AAAE,cAAI,UAAU,IAAI,OAAO,EAAE;AAAG,UAAAA,SAAQ,CAAC;AAAA,QAAG,CAAC;AACvD,gBAAQ,KAAK,UAAU,MAAM;AAAE,gBAAM;AAAG,UAAAA,SAAQ,CAAC;AAAA,QAAG,CAAC;AAAA,MACvD,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,WAAW;AACxB,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,CAAC,KAAK;AAAE,YAAI,oCAAoC;AAAG,eAAO;AAAA,MAAG;AACjE,YAAM,QAAQ,YAAY,WAAW,EAAE,IAAI,CAAC;AAC5C,UAAI,0BAAqB,GAAG,EAAE;AAC9B,aAAO;AAAA,IACT;AAEA,QAAI,WAAW,QAAQ;AACrB,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,CAAC,KAAK;AAAE,YAAI,iCAAiC;AAAG,eAAO;AAAA,MAAG;AAC9D,YAAM,QAAQ,YAAY,QAAQ,EAAE,IAAI,CAAC;AACzC,UAAI,uBAAkB,GAAG,EAAE;AAC3B,aAAO;AAAA,IACT;AAEA,QAAI,uBAAuB,MAAM,qCAAqC;AACtE,WAAO;AAAA,EACT,SAAS,GAAQ;AACf,QAAI,UAAU,EAAE,OAAO,EAAE;AACzB,WAAO;AAAA,EACT;AACF;AAIA,eAAsB,QAAQ,MAAgC;AAC5D,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,OAAO,MAAM,IAAI,IAAI;AACrE,SAAO,WAAW,KAAK,OAAO,MAAM,EAAE,IAAI,CAAC;AAC7C;AAIO,SAAS,QAAQ,MAAgB,OAAsC,CAAC,GAAW;AACxF,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,QAAQ,QAAQ;AAClB,QAAI,2CAA2C;AAC/C,QAAI,6EAA6E;AACjF,QAAI,kDAAkD;AACtD,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW;AACrB,QAAI,sBAAsB;AAC1B,QAAI,6EAA6E;AACjF,QAAI,kEAAkE;AACtE,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,UAAU;AACpB,QAAI,qBAAqB;AACzB,QAAI,0EAA0E;AAC9E,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,OAAO;AACjB,QAAI,6CAA6C;AACjD,QAAI,0EAA0E;AAC9E,QAAI,EAAE;AACN,QAAI,0DAA0D;AAC9D,QAAI,8EAA8E;AAClF,QAAI,+EAA+E;AACnF,QAAI,0DAA0D;AAC9D,QAAI,uDAAuD;AAC3D,QAAI,EAAE;AACN,QAAI,wDAAwD;AAC5D,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,MAAM;AAChB,QAAI,oBAAoB;AACxB,QAAI,yEAAyE;AAC7E,QAAI,yEAAyE;AAC7E,QAAI,0EAA0E;AAC9E,QAAI,kEAA6D;AACjE,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,QAAQ;AAClB,QAAI,mBAAmB;AACvB,QAAI,oEAAoE;AACxE,QAAI,oEAAoE;AACxE,WAAO;AAAA,EACT;AACA,MAAI,cAAc;AAClB,MAAI,iEAAiE;AACrE,MAAI,4EAA4E;AAChF,MAAI,0EAA0E;AAC9E,MAAI,4EAA4E;AAChF,MAAI,6DAA6D;AACjE,MAAI,qFAAqF;AACzF,MAAI,yEAAyE;AAC7E,MAAI,EAAE;AACN,MAAI,kDAA6C;AACjD,SAAO;AACT;;;A2B9UA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,cAAcM,cAAa;AAIpC,IAAM,YAAY,UAAU,IAAI;AAahC,IAAM,SAAS,QAAQ,aAAa,WAAW,QAAQ,aAAa;AAIpE,eAAsB,eAAe,MAA0C;AAC7E,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI;AAKF,UAAM,EAAE,OAAO,IAAI,MAAM,UAAU,kBAAkB,IAAI,sBAAsB;AAC/E,WAAO,UAAU,MAAM;AAAA,EACzB,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,QAAmC;AAGpD,MAAI,MAAqB;AACzB,MAAI,MAAM;AACV,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,QAAI,CAAC,KAAM;AACX,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,QAAI,QAAQ,KAAK;AAEf,UAAI,OAAO,KAAM,QAAO,EAAE,KAAK,SAAS,OAAO,UAAU;AACzD,YAAM,OAAO,KAAK;AAAA,IACpB,WAAW,QAAQ,KAAK;AACtB,YAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,OAAO,KAAM,QAAO,EAAE,KAAK,SAAS,OAAO,UAAU;AACzD,SAAO;AACT;AAOA,eAAsB,kBAAkB,UAAoD;AAC1F,QAAM,YAA4B,CAAC;AACnC,aAAW,OAAO,UAAU;AAC1B,UAAM,WAAW,MAAM,eAAe,IAAI,IAAI;AAC9C,QAAI,SAAU;AACd,UAAM,SAAS,MAAM,eAAe,IAAI,IAAI;AAC5C,cAAU,KAAK,EAAE,SAAS,IAAI,MAAM,MAAM,IAAI,MAAM,OAAO,CAAC;AAAA,EAC9D;AACA,SAAO;AACT;AAGA,eAAsB,WAAW,KAAa,UAAU,KAAwB;AAC9E,MAAI;AAAE,YAAQ,KAAK,KAAK,SAAS;AAAA,EAAG,QAAQ;AAAE,WAAO;AAAA,EAAO;AAC5D,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI,CAACC,UAAS,GAAG,EAAG,QAAO;AAC3B,UAAMC,OAAM,GAAG;AAAA,EACjB;AACA,MAAI;AAAE,YAAQ,KAAK,KAAK,SAAS;AAAA,EAAG,QAAQ;AAAA,EAAqB;AAEjE,QAAMA,OAAM,GAAG;AACf,SAAO,CAACD,UAAS,GAAG;AACtB;AAEA,SAASA,UAAS,KAAsB;AACtC,MAAI;AAAE,YAAQ,KAAK,KAAK,CAAC;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAO;AACnE;AAeA,eAAsB,qBACpB,WACA,MACkB;AAClB,MAAI,CAAC,UAAU,OAAQ,QAAO;AAE9B,QAAM,EAAE,UAAU,KAAK,QAAQ,gBAAgB,QAAQ,MAAM,SAAS,MAAM,IAAI;AAGhF,MAAI,2DAAsD;AAC1D,MAAI,EAAE;AACN,QAAM,UAAU,KAAK,IAAI,GAAG,UAAU,IAAI,OAAK,EAAE,QAAQ,MAAM,GAAG,CAAC;AACnE,aAAW,KAAK,WAAW;AACzB,UAAM,SAAS,EAAE,SACb,OAAO,EAAE,OAAO,GAAG,aAAa,EAAE,OAAO,OAAO,KAChD,6BAA6B,SAAS,KAAK,+BAA0B;AACzE,QAAI,MAAM,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,QAAQ,OAAO,OAAO,CAAC,KAAK,MAAM,EAAE;AAAA,EAC9E;AACA,MAAI,EAAE;AAEN,MAAI,UAAU;AACZ,WAAO,MAAM,QAAQ,WAAW,GAAG;AAAA,EACrC;AAEA,MAAI,CAAC,iBAAiB,CAAC,QAAQ;AAC7B,QAAI,6EAA6E;AACjF,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM,OAAO;AAC/B,MAAI,CAAC,WAAW;AACd,QAAI,qCAAgC;AACpC,WAAO;AAAA,EACT;AACA,SAAO,MAAM,QAAQ,WAAW,GAAG;AACrC;AAEA,eAAe,QAAQ,WAA2B,KAA4C;AAC5F,MAAI,QAAQ;AACZ,aAAW,KAAK,WAAW;AACzB,QAAI,CAAC,EAAE,QAAQ;AACb,UAAI,WAAM,EAAE,IAAI,IAAI,EAAE,OAAO,8CAAyC;AACtE,cAAQ;AACR;AAAA,IACF;AACA,UAAM,KAAK,MAAM,WAAW,EAAE,OAAO,GAAG;AACxC,QAAI,IAAI;AACN,UAAI,WAAM,EAAE,IAAI,IAAI,EAAE,OAAO,gBAAgB,EAAE,OAAO,GAAG,EAAE;AAAA,IAC7D,OAAO;AACL,UAAI,WAAM,EAAE,IAAI,IAAI,EAAE,OAAO,SAAS,EAAE,OAAO,GAAG,mBAAmB;AACrE,cAAQ;AAAA,IACV;AAAA,EACF;AACA,SAAO;AACT;;;AC3KA,eAAsB,iBAAoC;AACxD,UAAQ,QAAQ,UAAU;AAAA,IACxB,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,aAAO,IAAI,cAAc;AAAA,IAC3B;AAAA,IACA,KAAK,UAAU;AACb,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,sBAAa;AACrD,aAAO,IAAI,eAAe;AAAA,IAC5B;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,aAAO,IAAI,cAAc;AAAA,IAC3B;AAAA,IACA;AACE,YAAM,IAAI,MAAM,yBAAyB,QAAQ,QAAQ,EAAE;AAAA,EAC/D;AACF;;;ACnBA,SAAS,cAAAE,cAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,WAAAC,gBAAe;AAGxB,IAAM,eAAe;AAEd,IAAM,kBAAN,MAAqD;AAAA,EACjD,OAAO;AAAA,EAEhB,SAAS,UAAqC,MAAyB;AACrE,UAAM,UAAoB,CAAC;AAC3B,UAAM,OAAiB,CAAC;AAExB,eAAW,CAAC,MAAM,EAAE,KAAK,UAAU;AACjC,UAAI,GAAG,WAAW,KAAM;AACxB,YAAM,MAAM,KAAK,OAAO,IAAI;AAC5B,UAAI,QAAQ,OAAW;AAEvB,YAAM,OAAO,MAAM,UAAU,GAAG,IAAI,KAAK,MAAM,QAAQ,UAAU,KAAK,MAAM;AAC5E,YAAM,OAAO,KAAK,QAAQ,eAAe,GAAG;AAC5C,YAAM,OAAO,GAAG,YAAY,GAAG;AAE/B,UAAI,SAAS,OAAO,IAAI;AAAA,eAAmB,IAAI;AAAA,iBAAqB,IAAI;AAAA;AAAA,YAAmC,KAAK,UAAU;AAC1H,UAAI,KAAK,IAAK,WAAU;AAAA;AAAA;AACxB,cAAQ,KAAK,MAAM;AAEnB,WAAK,KAAK,OAAO,IAAI;AAAA;AAAA;AAAA,2BAAsE,KAAK,IAAI,IAAI,IAAI,GAAG;AAAA,IACjH;AAEA,QAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,WAAO;AAAA;AAAA,EAAsB,QAAQ,KAAK,IAAI,CAAC;AAAA;AAAA,EAAkB,KAAK,KAAK,IAAI,CAAC;AAAA;AAAA,EAClF;AAAA,EAEA,MAAM,SAAiB,MAAuB;AAC5C,UAAM,MAAMA,SAAQ,KAAK,QAAQ;AACjC,QAAI,CAACH,aAAW,GAAG,EAAG,CAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,IAAAC,eAAc,KAAK,UAAU,OAAO;AAAA,EACtC;AAAA,EAEA,MAAM,MAAuB;AAC3B,SAAK,MAAM,cAAc,IAAI;AAAA,EAC/B;AACF;;;AC1CA,SAAS,cAAAE,cAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,WAAAC,gBAAe;AAGxB,IAAMC,gBAAe;AAId,IAAM,gBAAN,MAAmD;AAAA,EAC/C,OAAO;AAAA,EAEhB,SAAS,UAAqC,MAAyB;AACrE,UAAM,SAAmB,CAAC;AAE1B,eAAW,CAAC,MAAM,EAAE,KAAK,UAAU;AACjC,UAAI,GAAG,WAAW,KAAM;AACxB,YAAM,MAAM,KAAK,OAAO,IAAI;AAC5B,UAAI,QAAQ,OAAW;AAEvB,YAAM,aAAa,MAAM,GAAG,GAAG,IAAI,KAAK,MAAM,KAAK,KAAK;AACxD,YAAM,OAAO,GAAG,YAAY,GAAG;AAC/B,YAAM,SAAS,KAAK,MAAM,YAAY;AAEtC,YAAM,WAAW,KAAK,MAClB,4CAA4C,UAAU;AAAA,2CACV,UAAU;AAAA,IACtD;AAEJ,aAAO;AAAA,QACL;AAAA,aACc,MAAM;AAAA,kBACD,UAAU;AAAA,IAC7B,WACA;AAAA,4BAC6B,KAAK,IAAI,IAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUhD;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,OAAQ,QAAOA;AAC3B,WAAO,OAAO,KAAK,MAAM,IAAI;AAAA,EAC/B;AAAA,EAEA,MAAM,SAAiB,MAAuB;AAC5C,UAAM,MAAMD,SAAQ,KAAK,QAAQ;AACjC,QAAI,CAACH,aAAW,GAAG,EAAG,CAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,IAAAC,eAAc,KAAK,UAAU,OAAO;AAAA,EACtC;AAAA,EAEA,MAAM,MAAuB;AAC3B,SAAK,MAAME,eAAc,IAAI;AAAA,EAC/B;AACF;;;AC5DA,SAAS,cAAAC,cAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,WAAAC,gBAAe;AAGxB,IAAMC,gBAAe;AAId,IAAM,gBAAN,MAAmD;AAAA,EAC/C,OAAO;AAAA,EAEhB,SAAS,UAAqC,MAAyB;AACrE,UAAM,SAAmB,CAAC;AAE1B,eAAW,CAAC,MAAM,EAAE,KAAK,UAAU;AACjC,UAAI,GAAG,WAAW,KAAM;AACxB,YAAM,MAAM,KAAK,OAAO,IAAI;AAC5B,UAAI,QAAQ,OAAW;AAEvB,YAAM,OAAO,MAAM,GAAG,GAAG,IAAI,KAAK,MAAM,KAAK,KAAK;AAClD,YAAM,OAAO,GAAG,YAAY,GAAG;AAC/B,YAAM,WAAW,KAAK,MAAM,OAAO,UAAU,IAAI;AAEjD,aAAO;AAAA,QACL,GAAG,QAAQ;AAAA,oBACU,KAAK,IAAI,IAAI,IAAI;AAAA;AAAA,MAExC;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,OAAQ,QAAOA;AAC3B,WAAO,OAAO,KAAK,MAAM,IAAI;AAAA,EAC/B;AAAA,EAEA,MAAM,SAAiB,MAAuB;AAC5C,UAAM,MAAMD,SAAQ,KAAK,QAAQ;AACjC,QAAI,CAACH,aAAW,GAAG,EAAG,CAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,IAAAC,eAAc,KAAK,UAAU,OAAO;AAAA,EACtC;AAAA,EAEA,MAAM,MAAuB;AAC3B,SAAK,MAAME,eAAc,IAAI;AAAA,EAC/B;AACF;;;ACtCA,IAAM,YAAuD;AAAA,EAC3D,SAAS,MAAM,IAAI,gBAAgB;AAAA,EACnC,OAAO,MAAM,IAAI,cAAc;AAAA,EAC/B,OAAO,MAAM,IAAI,cAAc;AACjC;AAEO,SAAS,oBAAoB,MAAmC;AACrE,QAAM,UAAU,UAAU,IAAI;AAC9B,MAAI,CAAC,SAAS;AACZ,UAAM,YAAY,OAAO,KAAK,SAAS,EAAE,KAAK,IAAI;AAClD,UAAM,IAAI,MAAM,4BAA4B,IAAI,iBAAiB,SAAS,EAAE;AAAA,EAC9E;AACA,SAAO,QAAQ;AACjB;;;AClBA,SAAgB,eAAAC,cAAa,UAAAC,eAAc;AAC3C,SAAS,OAAAC,MAAK,QAAAC,aAAY;;;ACD1B,SAAS,UAAU,WAAW,QAAQ,mBAAmB;AAsBlD,SAAS,kBACd,UACA,SACA,KACA,UAA0B,MAC1B;AACA,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAoC,oBAAI,IAAI,CAAC;AACzE,QAAM,CAAC,MAAM,OAAO,IAAI,SAAqB,CAAC,CAAC;AAC/C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoC,oBAAI,IAAI,CAAC;AACvE,QAAM,SAAS,OAA8B,IAAI;AACjD,QAAM,UAAU,OAAmD,oBAAI,IAAI,CAAC;AAC5E,QAAM,YAAY,OAAO,KAAK;AAC9B,QAAM,iBAAiB,OAAmB,CAAC,CAAC;AAC5C,QAAM,UAAU,OAAuB,OAAO;AAC9C,UAAQ,UAAU;AAGlB,QAAM,SAAS,OAAO,IAAI,YAA2C,CAAC;AACtE,QAAM,WAAW,OAAO,IAAI,YAAmD,CAAC;AAEhF,YAAU,MAAM;AACd,UAAMC,OAAM,IAAI,eAAe;AAAA,MAC7B;AAAA,MAAS;AAAA,MAAK;AAAA,MACd,QAAQ;AAAA,QACN,OAAO,CAAC,SAAS,MAAM,aAAa;AAClC,kBAAQ,SAAS,MAAM,SAAS,IAAI;AACpC,iBAAO,QAAQ,KAAK,EAAE,KAAK,SAAS,KAAK,CAAC;AAC1C,gBAAM,QAAkB,EAAE,SAAS,MAAM,UAAU,IAAI,KAAK,IAAI,GAAG,OAAO,eAAe,IAAI,EAAE;AAC/F,cAAI,UAAU,SAAS;AACrB,2BAAe,QAAQ,KAAK,KAAK;AACjC,gBAAI,eAAe,QAAQ,SAAS,KAAM;AACxC,6BAAe,UAAU,eAAe,QAAQ,MAAM,IAAK;AAAA,YAC7D;AACA;AAAA,UACF;AACA,kBAAQ,UAAQ;AACd,kBAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,mBAAO,KAAK,SAAS,MAAO,KAAK,MAAM,IAAK,IAAI;AAAA,UAClD,CAAC;AAAA,QACH;AAAA,QACA,eAAe,CAAC,MAAM,UAAU;AAC9B,mBAAS,QAAQ,KAAK,EAAE,MAAM,MAAM,CAAC;AACrC,oBAAU,IAAI,IAAIA,KAAI,KAAK,CAAC;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,CAAC;AACD,WAAO,UAAUA;AACjB,WAAO,MAAM;AAAE,MAAAA,KAAI,QAAQ;AAAA,IAAG;AAAA,EAChC,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC;AAG3B,YAAU,MAAM;AACd,UAAM,KAAK,YAAY,YAAY;AACjC,YAAMA,OAAM,OAAO;AACnB,UAAI,CAACA,KAAK;AACV,YAAMA,KAAI,eAAe;AACzB,gBAAU,IAAI,IAAIA,KAAI,KAAK,CAAC;AAE5B,YAAM,OAAiB,CAAC;AACxB,YAAM,SAAS,oBAAI,IAAoB;AACvC,iBAAW,CAAC,MAAM,EAAE,KAAKA,KAAI,OAAO;AAClC,YAAI,GAAG,KAAK;AAAE,eAAK,KAAK,GAAG,GAAG;AAAG,iBAAO,IAAI,GAAG,KAAK,IAAI;AAAA,QAAG;AAAA,MAC7D;AACA,UAAI,KAAK,QAAQ;AACf,cAAM,MAAM,MAAM,SAAS,gBAAgB,IAAI;AAC/C,cAAM,OAAO,oBAAI,IAA0B;AAC3C,mBAAW,CAAC,KAAK,IAAI,KAAK,KAAK;AAC7B,gBAAM,OAAO,OAAO,IAAI,GAAG;AAC3B,cAAI,CAAC,KAAM;AACX,gBAAM,OAAO,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,EAAE;AACrE,gBAAM,SAAS,eAAe,KAAK,YAAY,KAAK,KAAK,KAAK,IAAI;AAClE,kBAAQ,QAAQ,IAAI,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,KAAK,WAAW,CAAC;AACpE,eAAK,IAAI,MAAM,EAAE,KAAK,OAAO,QAAQ,CAAC,IAAI,KAAK,MAAM,KAAK,MAAM,MAAM,QAAQ,CAAC,IAAI,MAAM,CAAC;AAAA,QAC5F;AACA,iBAAS,IAAI;AAAA,MACf;AAAA,IACF,GAAG,GAAI;AACP,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,MAAM,OAAO;AAEnB,QAAM,YAAY,YAAY,MAAM;AAAE,mBAAe,UAAU,CAAC;AAAG,YAAQ,CAAC,CAAC;AAAA,EAAG,GAAG,CAAC,CAAC;AAGrF,QAAM,UAAU,YAAY,CAAC,SAAiB,MAAc,WAAW,MAAM;AAC3E,YAAQ,SAAS,MAAM,SAAS,IAAI;AACpC,WAAO,QAAQ,KAAK,EAAE,KAAK,SAAS,KAAK,CAAC;AAC1C,UAAM,QAAkB,EAAE,SAAS,MAAM,UAAU,IAAI,KAAK,IAAI,GAAG,OAAO,eAAe,IAAI,EAAE;AAC/F,QAAI,UAAU,SAAS;AACrB,qBAAe,QAAQ,KAAK,KAAK;AACjC,UAAI,eAAe,QAAQ,SAAS,KAAM;AACxC,uBAAe,UAAU,eAAe,QAAQ,MAAM,IAAK;AAAA,MAC7D;AACA;AAAA,IACF;AACA,YAAQ,UAAQ;AACd,YAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,aAAO,KAAK,SAAS,MAAO,KAAK,MAAM,IAAK,IAAI;AAAA,IAClD,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,YAAY,YAAY,CAAC,WAAoB;AACjD,cAAU,UAAU;AACpB,QAAI,CAAC,UAAU,eAAe,QAAQ,QAAQ;AAC5C,YAAM,QAAQ,eAAe;AAC7B,qBAAe,UAAU,CAAC;AAC1B,cAAQ,UAAQ;AACd,cAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,eAAO,KAAK,SAAS,MAAO,KAAK,MAAM,IAAK,IAAI;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IAAQ;AAAA,IAAM;AAAA,IACd,OAAO,YAAY,CAAC,KAAoB,aAAqB,KAAK,MAAM,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC;AAAA,IAC7F,MAAM,YAAY,CAAC,SAAiB,KAAK,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AAAA,IAC1D,SAAS,YAAY,CAAC,SAAiB,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC;AAAA,IAChE,SAAS,YAAY,CAAC,KAAoB,aAAqB,KAAK,QAAQ,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC;AAAA,IACjG,SAAS,YAAY,MAAM,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,QAAQ,OAAO;AAAA,IACf,UAAU,SAAS;AAAA,EACrB;AACF;;;ACtJA,SAAS,gBAAgB;AACzB,SAAgB,YAAAC,WAAU,eAAAC,oBAAmB;AAsB7C,IAAM,aAAa,CAAC,QAAQ,OAAO,QAAQ;AAI3C,SAAS,SAAS,UAA0D,OAAe;AACzF,WAAS,OAAK;AACZ,QAAI,EAAE,UAAU,QAAQ;AAEtB,YAAMC,QAAO,EAAE,mBAAmB;AAClC,aAAO,EAAE,GAAG,GAAG,kBAAkB,KAAK,IAAI,GAAGA,KAAI,EAAE;AAAA,IACrD;AACA,UAAM,OAAO,EAAE,oBAAoB;AACnC,WAAO,EAAE,GAAG,GAAG,mBAAmB,KAAK,IAAI,GAAG,IAAI,EAAE;AAAA,EACtD,CAAC;AACH;AAEA,SAAS,SAAS,UAA0D,QAA0B;AACpG,WAAS,OAAK;AACZ,QAAI,EAAE,UAAU,QAAQ;AAEtB,aAAO,EAAE,GAAG,GAAG,kBAAkB,WAAW,QAAQ,OAAO,mBAAmB,EAAE;AAAA,IAClF;AACA,WAAO,EAAE,GAAG,GAAG,mBAAmB,WAAW,QAAQ,IAAI,OAAO,iBAAiB;AAAA,EACnF,CAAC;AACH;AAEO,SAAS,eAAe,MAI5B;AACD,QAAM,CAAC,OAAO,QAAQ,IAAIF,UAAmB;AAAA,IAC3C,OAAO;AAAA,IAAQ,OAAO;AAAA,IAAQ,WAAW;AAAA,IAAM,YAAY;AAAA,IAC3D,YAAY;AAAA,IAAO,gBAAgB;AAAA,IAAO,SAAS;AAAA,IAAG,cAAc;AAAA,IACpE,kBAAkB;AAAA,IAAG,mBAAmB;AAAA,IAAG,aAAa;AAAA,IAAO,cAAc;AAAA,EAC/E,CAAC;AAED,QAAM,cAA6B,CAAC,OAAO,SAAS,MAAM;AAE1D,QAAM,WAAWC,aAAY,CAAC,UAAiB,SAAS,QAAM,EAAE,GAAG,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;AACnF,QAAM,YAAYA,aAAY,CAAC,MAAqB,SAAS,QAAM,EAAE,GAAG,GAAG,WAAW,GAAG,OAAO,OAAO,EAAE,GAAG,CAAC,CAAC;AAC9G,QAAM,YAAYA,aAAY,CAAC,MAAqB,SAAS,QAAM,EAAE,GAAG,GAAG,YAAY,GAAG,OAAO,OAAO,EAAE,GAAG,CAAC,CAAC;AAE/G,QAAM,WAAW,QAAQ,MAAM,SAAS;AAExC,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,MAAM,UAAU,OAAQ;AAE5B,QAAI,UAAU,OAAQ,IAAI,QAAQ,UAAU,IAAM,MAAK,OAAO;AAAA,aAErD,IAAI,QAAQ,UAAU,IAAK,UAAS,UAAU,KAAK;AAAA,aACnD,IAAI,QAAQ,UAAU,IAAK,UAAS,UAAU,QAAQ;AAAA,aACtD,IAAI,QAAQ,UAAU,IAAK,UAAS,UAAU,GAAG;AAAA,aACjD,IAAI,QAAQ,UAAU,IAAK,UAAS,UAAU,EAAG;AAAA,aACjD,IAAI,QAAuB,UAAS,UAAU,EAAE;AAAA,aAChD,IAAI,UAAuB,UAAS,UAAU,CAAE;AAAA,aAChD,UAAU,IAAiB,UAAS,UAAU,GAAG;AAAA,aACjD,UAAU,IAAiB,UAAS,UAAU,EAAG;AAAA,aAEjD,UAAU,IAAK,MAAK,YAAY;AAAA,aAChC,IAAI,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,OAAO,EAAE,UAAU,SAAS,UAAU,OAAO,EAAE;AAAA,aAC/E,UAAU,IAAK,UAAS,QAAQ;AAAA,aAChC,UAAU,IAAK,UAAS,SAAS;AAAA,aACjC,UAAU,IAAK,UAAS,MAAM;AAAA,aAC9B,UAAU,IAAK,UAAS,QAAQ;AAAA,aAChC,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,WAAW,MAAM,YAAY,MAAM,aAAa,MAAM,EAAE;AAAA,aAC9F,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,YAAY,CAAC,EAAE,WAAW,EAAE;AAAA,aAClE,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,gBAAgB,CAAC,EAAE,eAAe,EAAE;AAAA,aAC1E,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,UAAU,EAAE,UAAU,KAAK,WAAW,OAAO,EAAE;AAAA,aACrF,UAAU,KAAK;AAAE,WAAK,cAAc;AAAG,eAAS,QAAM,EAAE,GAAG,GAAG,cAAc,CAAC,EAAE,aAAa,EAAE;AAAA,IAAG,WACjG,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,aAAa,aAAa,YAAY,QAAQ,EAAE,WAAW,IAAI,KAAK,YAAY,MAAM,EAAG,EAAE;AAAA,aACjI,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,cAAc,CAAC,EAAE,aAAa,EAAE;AAAA,EACjF,GAAG,EAAE,SAAS,CAAC;AAEf,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,WAAW,MAAM,OAAO;AAAA;AAAA,IAElC,iBAAiBA,aAAY,MAAM,SAAS,QAAM,EAAE,GAAG,GAAG,kBAAkB,EAAE,EAAE,GAAG,CAAC,CAAC;AAAA,IACrF,kBAAkBA,aAAY,MAAM,SAAS,QAAM,EAAE,GAAG,GAAG,mBAAmB,EAAE,EAAE,GAAG,CAAC,CAAC;AAAA,EACzF;AACF;;;AC3GA,SAAS,aAAAE,YAAW,UAAAC,eAAc;AAI3B,SAAS,aACd,UACA,MACA,QACA,SACA;AACA,QAAM,YAAYA,QAAO,MAAM;AAC/B,QAAM,iBAAiBA,QAAsB,IAAI;AACjD,YAAU,UAAU;AAEpB,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAS;AAEpC,UAAM,OAAO,MAAM;AACjB,YAAM,YAAY,oBAAI,IAA0B;AAChD,iBAAW,CAAC,MAAM,EAAE,KAAK,UAAU,SAAS;AAC1C,kBAAU,IAAI,MAAM,EAAE,MAAM,GAAG,IAAI,MAAM,QAAQ,GAAG,QAAQ,UAAW,GAAG,IAAY,SAAS,CAAC;AAAA,MAClG;AACA,YAAM,UAAU,SAAS,SAAS,WAAW,IAAI;AACjD,UAAI,YAAY,eAAe,QAAS;AACxC,qBAAe,UAAU;AACzB,eAAS,MAAM,SAAS,IAAI;AAAA,IAC9B;AAEA,SAAK;AACL,UAAM,KAAK,YAAY,MAAM,GAAI;AACjC,WAAO,MAAM;AACX,oBAAc,EAAE;AAChB,qBAAe,UAAU;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,UAAU,MAAM,OAAO,CAAC;AAC9B;;;ACnCA,SAAS,aAAAE,YAAW,YAAAC,iBAAgB;AACpC,SAAS,iBAAiB;AAInB,SAAS,kBAA0B;AACxC,QAAM,EAAE,OAAO,IAAI,UAAU;AAC7B,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,QAAQ,QAAQ,EAAE;AACnD,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,WAAW,MAAM,QAAQ,OAAO,QAAQ,EAAE;AAChD,WAAO,GAAG,UAAU,QAAQ;AAC5B,WAAO,MAAM;AAAE,aAAO,IAAI,UAAU,QAAQ;AAAA,IAAG;AAAA,EACjD,GAAG,CAAC,MAAM,CAAC;AACX,SAAO;AACT;;;ACfA,SAAS,aAAAE,kBAAiB;AAInB,SAAS,aACd,WACA,YACA,kBACM;AACN,EAAAA,WAAU,MAAM;AACd,cAAU,cAAc,mBAAmB,CAAC;AAAA,EAC9C,GAAG,CAAC,YAAY,kBAAkB,SAAS,CAAC;AAC9C;;;ACZA,SAAS,aAAAC,YAAW,UAAAC,eAAc;AAClC,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,oBAAAC,mBAAkB,cAAAC,oBAAkB;AAC7C,SAAS,YAAAC,WAAU,WAAAC,UAAS,QAAAC,aAAY;AAejC,SAAS,gBACd,SACA,aACA,SACA,SACA,QACA,UACA,UACA,OAC4C;AAC5C,QAAM,YAAYC,QAAkC,IAAI;AACxD,QAAM,aAAaA,QAAO,oBAAI,IAA2C,CAAC;AAE1E,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,QAAS;AACd,QAAI,SAAoC;AACxC,KAAC,YAAY;AACX,UAAI;AACF,iBAAS,MAAM,kBAAkB,aAAa;AAAA,UAC5C,QAAQ,MAAM,QAAQ;AAAA,UACtB,SAAS,CAAC,SAAS,QAAQ,QAAQ,IAAI;AAAA,UACvC,MAAM,CAAC,SAAS,QAAQ,KAAK,IAAI;AAAA,UACjC,UAAU,OAAO,SAAS,UAAU;AAClC,gBAAI,CAAC,QAAS,QAAO,CAAC;AACtB,kBAAM,OAAO,QAAQ,QAAQ,OAAO;AACpC,gBAAI,CAACC,aAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,mBAAO,IAAI,QAAkB,CAACC,UAAS,WAAW;AAChD,oBAAM,MAAgB,CAAC;AACvB,oBAAM,KAAKC,iBAAgB,EAAE,OAAOC,kBAAiB,MAAM,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC;AAClF,iBAAG,GAAG,QAAQ,OAAK;AAAE,oBAAI,KAAK,CAAC;AAAG,oBAAI,IAAI,SAAS,MAAO,KAAI,MAAM;AAAA,cAAG,CAAC;AACxE,iBAAG,GAAG,SAAS,MAAMF,SAAQ,GAAG,CAAC;AACjC,iBAAG,GAAG,SAAS,MAAM;AAAA,YACvB,CAAC;AAAA,UACH;AAAA,UACA,WAAW,CAAC,SAAS,WAAW;AAC9B,mBAAO,OAAO,UAAU,CAAC,EAAE,KAAK,KAAK,MAAM;AACzC,kBAAI,YAAY,QAAQ,QAAQ,QAAS,QAAO,KAAK,IAAI;AAAA,YAC3D,CAAC;AAAA,UACH;AAAA,UACA,aAAa,CAAC,aAAa;AACzB,mBAAO,SAAS,UAAU,CAAC,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,KAAK,CAAC;AAAA,UACtE;AAAA,UACA,MAAM,WAAW;AACf,kBAAM,OAAiB,CAAC;AACxB,kBAAM,YAAY,oBAAI,IAAoB;AAC1C,uBAAW,CAAC,MAAM,EAAE,KAAK,QAAQ,OAAO;AACtC,kBAAI,GAAG,KAAK;AAAE,qBAAK,KAAK,GAAG,GAAG;AAAG,0BAAU,IAAI,GAAG,KAAK,IAAI;AAAA,cAAG;AAAA,YAChE;AACA,kBAAM,MAAM,KAAK,SAAS,MAAM,SAAS,gBAAgB,IAAI,IAAI,oBAAI,IAAI;AACzE,kBAAM,WAA2D,CAAC;AAClE,uBAAW,CAAC,IAAI,KAAK,QAAQ,OAAO;AAClC,uBAAS,IAAI,IAAI,EAAE,KAAK,GAAG,OAAO,EAAE;AAAA,YACtC;AACA,uBAAW,CAAC,KAAK,IAAI,KAAK,KAAK;AAC7B,oBAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,kBAAI,CAAC,KAAM;AACX,oBAAM,OAAO,WAAW,QAAQ,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,EAAE;AACxE,oBAAM,MAAM,eAAe,KAAK,YAAY,KAAK,KAAK,KAAK,IAAI;AAC/D,yBAAW,QAAQ,IAAI,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,KAAK,WAAW,CAAC;AACvE,uBAAS,IAAI,IAAI,EAAE,KAAK,KAAK,MAAM,MAAM,EAAE,IAAI,IAAI,OAAO,KAAK,MAAO,KAAK,MAAM,OAAQ,EAAE,IAAI,GAAG;AAAA,YACpG;AACA,mBAAO;AAAA,cACL;AAAA,cACA,QAAQ;AAAA,gBACN,YAAY,KAAK,MAAMG,UAAS,IAAI,OAAO,IAAI;AAAA,gBAC/C,WAAW,KAAK,MAAMC,SAAQ,IAAI,OAAO,IAAI;AAAA,gBAC7C,UAAUC,MAAK,EAAE;AAAA,cACnB;AAAA,YACF;AAAA,UACF;AAAA,UACA,eAAe;AACb,gBAAI,CAAC,MAAO,QAAO;AACnB,mBAAO;AAAA,cACL,QAAQ;AAAA,cACR,UAAU,MAAM,SAAS;AAAA,cACzB,QAAQ,MAAM,KAAK;AAAA,cACnB,KAAK,MAAM,KAAK;AAAA,cAChB,QAAQ,MAAM,KAAK;AAAA,YACrB;AAAA,UACF;AAAA,QACF,GAAG,EAAE,OAAO,SAAO,QAAQ,SAAS,KAAK,EAAE,EAAE,CAAC;AAC9C,kBAAU,UAAU;AAAA,MACtB,SAAS,GAAQ;AACf,gBAAQ,SAAS,kCAA6B,EAAE,OAAO,IAAI,CAAC;AAAA,MAC9D;AAAA,IACF,GAAG;AACH,WAAO,MAAM;AAAE,WAAK,QAAQ,MAAM;AAAG,gBAAU,UAAU;AAAA,IAAM;AAAA,EACjE,GAAG,CAAC,SAAS,aAAa,SAAS,SAAS,QAAQ,UAAU,UAAU,KAAK,CAAC;AAC9E,SAAO;AACT;;;AC3GA,SAAS,aAAAC,kBAAiB;AAQnB,SAAS,aACd,SACA,SACA,SACA,SACM;AACN,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,QAAQ,eAAe,CAAC,QAAS;AACtC,QAAI;AACJ,QAAI;AACF,mBAAa,eAAe,SAAS,QAAQ,UAAU;AAAA,IACzD,SAAS,GAAQ;AACf,cAAQ,SAAS,iCAA4B,EAAE,OAAO,IAAI,CAAC;AAC3D;AAAA,IACF;AACA,YAAQ,SAAS,sBAAe,UAAU,IAAI,EAAE;AAChD,WAAO,YAAY;AAAA,MACjB;AAAA,MAAY;AAAA,MAAS;AAAA,MACrB,KAAK,SAAO,QAAQ,SAAS,KAAK,IAAI,WAAW,QAAG,IAAI,IAAI,EAAE;AAAA,IAChE,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,aAAa,QAAQ,YAAY,SAAS,SAAS,OAAO,CAAC;AACzE;;;AC7BA,SAAS,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;;;ACkBrC,SAAS,QAAQ,OAA6B;AAEnD,MAAI,MAAM,mBAAmB,KAAK,CAAC,MAAM,MAAM,IAAI,SAAS,GAAG;AAC7D,WAAO,EAAE,IAAI,WAAW,SAAS,mEAAmE;AAAA,EACtG;AACA,MAAI,MAAM,YAAY,OAAQ,CAAC,MAAM,aAAa,CAAC,MAAM,MAAM,IAAI,QAAQ,GAAG;AAC5E,WAAO,EAAE,IAAI,UAAU,SAAS,iCAAiC;AAAA,EACnE;AACA,MAAI,MAAM,YAAY,OAAO,CAAC,MAAM,aAAa,CAAC,MAAM,MAAM,IAAI,QAAQ,GAAG;AAC3E,WAAO,EAAE,IAAI,UAAU,SAAS,yCAAyC;AAAA,EAC3E;AACA,SAAO;AACT;;;AC9BA,SAAgB,aAAAC,YAAW,YAAAC,iBAAgB;AAC3C,SAAS,KAAK,YAAY;AAI1B,OAAO,QAAQ;AA6BT,cASA,YATA;AAfN,IAAM,IAAkD;AAAA,EACtD,IAAI,EAAE,GAAG,UAAK,OAAO,QAAQ;AAAA,EAAG,MAAM,EAAE,GAAG,UAAK,OAAO,SAAS;AAAA,EAChE,MAAM,EAAE,GAAG,UAAK,OAAO,MAAM;AAAA,EAAG,MAAM,EAAE,GAAG,UAAK,OAAO,OAAO;AAChE;AAGO,IAAMC,gBAAe;AAErB,SAAS,cAAc,IAA2B;AACvD,SAAO,GAAG,WAAW,aAAa,GAAG,YAAYA;AACnD;AAEA,SAAS,IAAI,EAAE,MAAM,IAAI,MAAM,IAAI,QAAQ,GAA2F;AACpI,QAAM,SAAS,cAAc,EAAE;AAC/B,QAAM,YAAY,SACd,oBAAC,QAAK,OAAM,OAAM,MAAI,MAAC,oBAAC,IACxB,oBAAC,QAAK,QAAQ,EAAE,GAAG,MAAM,KAAK,EAAE,MAAM,GAAI,OAAS,aAAE,GAAG,MAAM,KAAK,EAAE,MAAM,GAAI,GAAE;AACrF,QAAM,QAAQ,UAAU,GAAG,WAAW,UAAU,MAAM;AACtD,QAAM,KAAK,SAAS,QAAQ,GAAG,WAAW,YAAY,UAAU,GAAG,WAAW,aAAa,WAAW,GAAG,WAAW,SAAS,SAAS;AACtI,QAAM,cAAc,SAAS,YAAY,GAAG;AAC5C,QAAM,KAAK,GAAG,YAAY,UAAU,KAAK,IAAI,IAAI,GAAG,SAAS,IAAI;AAEjE,MAAI,CAAC,SAAS;AACZ,WACE,qBAAC,QACE;AAAA;AAAA,MAAU;AAAA,MAAC,oBAAC,QAAK,OAAe,eAAK,OAAO,EAAE,GAAE;AAAA,MAAO;AAAA,MAAE,OAAO,GAAG,IAAI,IAAI,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAC,oBAAC,QAAK,OAAO,IAAI,MAAM,QAAS,sBAAY,OAAO,CAAC,GAAE;AAAA,MAAO;AAAA,OAAG,MAAM,OAAO,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,OAAG,MAAM,OAAO,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,OAAO,GAAG,MAAM,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,OAAO,GAAG,QAAQ,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,GAAG,SAAS,CAAC;AAAA,OAC7S;AAAA,EAEJ;AAGA,QAAM,eAAe,iBAAiB,GAAG,GAAG,EAAE,KAAK,GAAG;AACtD,QAAM,MAAM,cAAc,GAAG,IAAI,QAAQ;AACzC,QAAM,SAAS,OAAO,QAAQ,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG;AACxE,SACE,qBAAC,OAAI,eAAc,UACjB;AAAA,yBAAC,QACE;AAAA;AAAA,MAAU;AAAA,MAAC,oBAAC,QAAK,OAAe,eAAK,OAAO,EAAE,GAAE;AAAA,MAAO;AAAA,MAAE,OAAO,GAAG,IAAI,IAAI,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAC,oBAAC,QAAK,OAAO,IAAI,MAAM,QAAS,sBAAY,OAAO,CAAC,GAAE;AAAA,MAAO;AAAA,OAAG,MAAM,OAAO,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,OAAG,MAAM,OAAO,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,OAAO,GAAG,MAAM,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,OAAO,GAAG,QAAQ,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,GAAG,SAAS,CAAC;AAAA,OAC7S;AAAA,IACA,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,MAAS,GAAG,IAAI;AAAA,MAAI;AAAA,MAAE;AAAA,OAAa;AAAA,IACjD,UAAU,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,MAAS;AAAA,OAAO;AAAA,KAC5C;AAEJ;AAEA,SAAS,UAAU,EAAE,GAAG,GAAmB;AACzC,SAAO,qBAAC,QAAK,MAAI,MAAC;AAAA;AAAA,IAAG,UAAU,OAAO,EAAE;AAAA,IAAE;AAAA,IAAE,OAAO,SAAS,CAAC;AAAA,IAAE;AAAA,IAAE,SAAS,OAAO,CAAC;AAAA,IAAE;AAAA,IAAE,MAAM,SAAS,CAAC;AAAA,IAAE;AAAA,IAAE,MAAM,SAAS,CAAC;AAAA,IAAE;AAAA,IAAU,KAAK,SAAS,CAAC;AAAA,KAAE;AACzJ;AAEO,SAAS,WAAW,EAAE,QAAQ,OAAO,UAAU,YAAY,QAAQ,SAAS,cAAc,aAAa,UAAU,MAAM,GAAU;AACtI,QAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,CAAC;AAC/B,QAAM,QAAQ,OAAO,YAAY,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AACvF,QAAM,WAAW,OAAO,YAAY,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAEtE,QAAM,OAAO,iBAAiB,MAAM,OAAO,OAAK,OAAO,IAAI,CAAC,EAAG,IAAI,SAAS,KAAK,GAAG,UAAU,UAAU,KAAK;AAC7G,QAAM,OAAO,iBAAiB,MAAM,OAAO,OAAK,OAAO,IAAI,CAAC,EAAG,IAAI,SAAS,KAAK,GAAG,UAAU,UAAU,KAAK;AAG7G,QAAMC,QAAO,GAAG,KAAK,EAAE;AACvB,QAAM,WAAW,GAAG,SAAS,IAAI,OAAO,OAAO,MAAM,QAAQ,CAAC;AAC9D,QAAM,UAAU,WAAW,OAAO,IAAI,GAAG,QAAQ,IAAI,OAAO,OAAO,MAAM,QAAQ,CAAC;AAClF,QAAM,OAAO,GAAG,QAAQ,EAAE,CAAC,EAAG,QAAQ,CAAC;AAGvC,MAAI,WAAW,GAAG,aAAa,GAAG,cAAc,GAAG,gBAAgB;AACnE,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,MAAM,IAAI,IAAI;AACxB,QAAI,GAAG;AACL,YAAM,IAAI,WAAW,EAAE,GAAG;AAAG,UAAI,CAAC,MAAM,CAAC,EAAG,aAAY;AACxD,YAAM,IAAI,WAAW,EAAE,GAAG;AAAG,UAAI,CAAC,MAAM,CAAC,EAAG,eAAc;AAAA,IAC5D;AACA,mBAAe,OAAO,IAAI,IAAI,GAAG,UAAU;AAC3C,qBAAiB,OAAO,IAAI,IAAI,GAAG,YAAY;AAAA,EACjD;AACA,QAAM,WAAW,cAAc,QAAQ,aAAa,MAAM,QAAQ,CAAC,IAAI,QAAQ,WAAW,QAAQ,CAAC,IAAI;AAEvG,QAAM,KAAK;AACX,QAAM,gBAAgB,KAAK,IAAI,GAAG,SAAS,CAAC;AAC5C,QAAM,aAAa,KAAK,IAAI,GAAG,gBAAgB,CAAC;AAGhD,QAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,KAAK,MAAM,IAAI,UAAU;AAC3E,QAAM,kBAAkB,iBAAiB,OAAO,mBAC5C,UACA,KAAK,IAAI,cAAc,OAAO;AAClC,QAAM,gBAAgB,KAAK,IAAI,iBAAiB,KAAK,IAAI,GAAG,KAAK,SAAS,UAAU,CAAC;AACrF,QAAM,gBAAgB,KAAK,IAAI,iBAAiB,KAAK,IAAI,GAAG,KAAK,SAAS,UAAU,CAAC;AAErF,QAAM,cAAc,KAAK,MAAM,eAAe,gBAAgB,UAAU;AACxE,QAAM,cAAc,KAAK,MAAM,eAAe,gBAAgB,UAAU;AAGxE,EAAAC,WAAU,MAAM;AACd,gBAAY;AAAA,EACd,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,QAAM,gBAAgB,KAAK,IAAI,KAAK,QAAQ,KAAK,MAAM;AACvD,QAAM,eAAe,WAAW,gBAAgB,IAC5C,IAAI,kBAAkB,CAAC,IAAI,KAAK,IAAI,kBAAkB,YAAY,aAAa,CAAC,IAAI,aAAa,MACjG;AACJ,QAAM,WAAW,kBAAkB;AACnC,QAAM,cAAc,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,OAAO,aAAa,EAAE;AAG/D,QAAM,SAAU,WAAW,MAAM,IAAI,WAAW,OAAO,IAAK;AAC5D,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAS,KAAK;AAChD,EAAAD,WAAU,MAAM;AACd,iBAAa,UAAQ,wBAAwB,QAAQ,IAAI,CAAC;AAAA,EAC5D,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,eAAe,YACjB,CAAC,GAAG,MAAM,QAAQ,CAAC,EAChB,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,EACzD,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE,EAC1B,MAAM,GAAG,CAAC,IACb,CAAC;AAEL,SACE,qBAAC,OAAI,eAAc,UAAS,aAAY,SAAQ,aAAa,UAAU,UAAU,QAAQ,QACvF;AAAA,yBAAC,OACC;AAAA,2BAAC,QAAK,MAAI,MAAC,OAAM,SAAQ;AAAA;AAAA,QAAQ;AAAA,SAAa;AAAA,MAC7C,YAAY,oBAAC,QAAK,OAAM,UAAS,uBAAS;AAAA,MAC1C,cAAc,KAAK,qBAAC,QAAK,OAAM,OAAM,MAAI,MAAC;AAAA;AAAA,QAAI;AAAA,QAAY;AAAA,SAAe;AAAA,MAC1E,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAUD;AAAA,QAAK;AAAA,QAAQ;AAAA,QAAK;AAAA,QAAM;AAAA,QAAO;AAAA,QAAE;AAAA,QAAQ;AAAA,SAAE;AAAA,MACpE,oBAAC,QAAK,UAAQ,MAAC,sBAAG;AAAA,MAClB,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAY,SAAS,QAAQ,CAAC;AAAA,QAAE;AAAA,QAAO;AAAA,QAAS;AAAA,QAAM;AAAA,QAAY;AAAA,QAAM;AAAA,QAAc;AAAA,QAAO,MAAM;AAAA,SAAO;AAAA,MACxH,aAAa,UAAU,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAU;AAAA,SAAS;AAAA,OAC5D;AAAA,IACC,aACC,qBAAC,OACC;AAAA,2BAAC,QAAK,OAAM,UAAS,MAAI,MAAC;AAAA;AAAA,QAAQ,OAAO,QAAQ,CAAC;AAAA,QAAE;AAAA,SAAS;AAAA,MAC7D,oBAAC,QAAK,OAAM,UAAU,uBAAa,IAAI,OAAK,GAAG,EAAE,IAAI,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,GAAE;AAAA,OAC3F;AAAA,IAEF,qBAAC,OAAI,UAAU,GAEb;AAAA,2BAAC,OAAI,eAAc,UAAS,UAAU,GAAG,WAAW,GAClD;AAAA,6BAAC,QAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,UAAQ,KAAK;AAAA,UAAO;AAAA,WAAC;AAAA,QAC7C,oBAAC,aAAU,IAAQ;AAAA,QAClB,YAAY,IAAI,OACf,oBAAC,OAAY,MAAM,GAAG,IAAI,OAAO,IAAI,CAAC,GAAI,MAAM,MAAM,IAAI,CAAC,GAAG,IAAQ,WAA5D,CAA8E,CACzF;AAAA,SACH;AAAA,MAEA,oBAAC,OAAI,eAAc,UAAS,OAAO,GAChC,gBAAM,KAAK,EAAE,QAAQ,cAAc,GAAG,CAAC,GAAG,MAAM,oBAAC,QAAa,UAAQ,MAAC,sBAAZ,CAAa,CAAO,GAClF;AAAA,MAEA,qBAAC,OAAI,eAAc,UAAS,UAAU,GAAG,WAAW,GAClD;AAAA,6BAAC,QAAK,MAAI,MAAC,OAAM,WAAU;AAAA;AAAA,UAAQ,KAAK;AAAA,UAAO;AAAA,WAAC;AAAA,QAChD,oBAAC,aAAU,IAAQ;AAAA,QAClB,YAAY,IAAI,OACf,oBAAC,OAAY,MAAM,GAAG,IAAI,OAAO,IAAI,CAAC,GAAI,MAAM,MAAM,IAAI,CAAC,GAAG,IAAQ,WAA5D,CAA8E,CACzF;AAAA,SACH;AAAA,OACF;AAAA,KACF;AAEJ;;;AF1KO,SAAS,kBACd,WACA,WACA,WACA,QACe;AACf,QAAM,YAAYG,QAAoB,oBAAI,IAAI,CAAC;AAC/C,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAwB,IAAI;AAE9D,EAAAC,WAAU,MAAM;AACd,UAAM,MAAM,QAAQ;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,OAAO,aAAa,EAAE;AAAA,MAC7D,OAAO,UAAU;AAAA,IACnB,CAAC;AACD,QAAI,OAAO,IAAI,YAAY,WAAW;AACpC,gBAAU,QAAQ,IAAI,IAAI,EAAE;AAC5B,mBAAa,IAAI,OAAO;AACxB,YAAM,QAAQ,WAAW,MAAM,aAAa,IAAI,GAAG,IAAM;AACzD,aAAO,MAAM,aAAa,KAAK;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,WAAW,QAAQ,WAAW,WAAW,SAAS,CAAC;AAEvD,SAAO;AACT;;;AGlCA,SAAS,aAAAC,YAAW,YAAAC,iBAAgB;AAwB7B,SAAS,gBACd,SACA,QACA,UACA,SACA,UACA,KACA,SACA,MACA,SACM;AACN,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAE1C,EAAAC,WAAU,MAAM;AACd,QAAI,UAAU,CAAC,QAAS;AACxB,cAAU,IAAI;AACd,UAAM,MAAM;AAEZ,KAAC,YAAY;AACX,YAAM,WAAW,QAAQ;AACzB,YAAM,cAAc,QAAQ;AAG5B,UAAI,OAAO,UAAU,QAAQ;AAC3B,cAAM,SAAS,MAAM,eAAe,OAAO,UAAU;AAAA,UACnD;AAAA,UAAS;AAAA,UAAK;AAAA,UACd,OAAO,CAAC,KAAK,QAAQ,QAAQ,OAAO,GAAG,IAAI,KAAK,EAAE;AAAA,QACpD,CAAC;AACD,aAAK,UAAU,UAAU,OAAO;AAChC,YAAI,CAAC,OAAO,YAAY;AACtB,kBAAQ,SAAS,8BAAyB,OAAO,OAAO,KAAK,IAAI,CAAC,oBAAoB,CAAC;AACvF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,YAAY,OAAO,MAAM;AAE3B,cAAM,EAAE,UAAU,KAAK,IAAI,iBAAiB,UAAU,OAAO,IAAI;AAGjE,cAAM,WAAW,aAAa,QAAQ;AACtC,YAAI,WAAW;AACf,mBAAW,OAAO,OAAO,KAAK,QAAQ,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG;AACzE,gBAAM,OAAO,SAAS,GAAG;AACzB,qBAAW,OAAO,MAAM;AACtB,kBAAM,KAAK;AACX,kBAAM,IAAI,QAAQ,KAAK,EAAE;AACzB,kBAAM,IAAI,MAAM,KAAK,EAAE;AAAA,UACzB;AACA,gBAAM,OAAO,KAAK,OAAO,OAAK,EAAE,SAAS,KAAK;AAC9C,cAAI,KAAK,OAAQ,OAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,YAAY,EAAE,MAAM,EAAE,SAAS,KAAM,CAAC,CAAC,CAAC;AACzF,eAAK,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,OAAK;AAC9C,kBAAM,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI;AAC/B,gBAAI,GAAI,IAAG,SAAS;AAAA,UACtB,CAAC;AAAA,QACH;AAGA,mBAAW,OAAO,MAAM;AACtB,gBAAM,KAAK;AACX,gBAAM,YAAY,mBAAmB,GAAG;AAGxC,gBAAM,YAA0B;AAAA,YAC9B,KAAK;AAAA,YAAW,MAAM;AAAA,YAAM,KAAK;AAAA,YACjC,QAAQ;AAAA,YAAQ,QAAQ;AAAA,YACxB,QAAQ;AAAA,YAAG,UAAU;AAAA,YAAG,WAAW;AAAA,YACnC,iBAAiB;AAAA,YAAO,UAAU;AAAA,UACpC;AACA,cAAI,MAAM,IAAI,IAAI,MAAM,SAAS;AAEjC,gBAAM,QAAQ,gBAAgB;AAAA,YAC5B,YAAY,IAAI;AAAA,YAChB,YAAY,UAAU;AAAA,YACtB,YAAY;AAAA,YACZ,eAAe,YAAY;AACzB,oBAAM,IAAI,QAAQ,WAAW,EAAE;AAC/B,oBAAM,IAAI,MAAM,WAAW,EAAE;AAC7B,oBAAM,KAAK,MAAM,YAAY,UAAU,UAAU,EAAE,SAAS,KAAM,CAAC;AACnE,oBAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,kBAAI,IAAI;AACN,mBAAG,SAAS,KAAK,YAAY;AAC7B,oBAAI,GAAI,IAAG,SAAS;AAAA,cACtB;AAAA,YACF;AAAA,YACA,YAAY,MAAM;AAChB,kBAAI,KAAK,IAAI,IAAI;AACjB,oBAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,kBAAI,IAAI;AAAE,mBAAG,SAAS;AAAQ,mBAAG,SAAS;AAAQ,mBAAG,MAAM;AAAM,mBAAG,OAAO;AAAM,mBAAG,YAAY;AAAA,cAAM;AAAA,YACxG;AAAA,YACA,SAAS,MAAM;AACb,oBAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,qBAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,KAAK,UAAU,GAAG,WAAW;AAAA,YAC/D;AAAA,UACF,CAAC;AAED,eAAK,YAAY,QAAS,IAAI,IAAI,MAAM,KAAK;AAAA,QAC/C;AAAA,MACF,OAAO;AAEL,cAAM,SAAS,aAAa,QAAQ;AACpC,YAAI,WAAW;AACf,mBAAW,OAAO,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG;AACvE,gBAAM,OAAO,OAAO,GAAG;AACvB,qBAAW,OAAO,MAAM;AACtB,kBAAM,KAAK;AACX,kBAAM,IAAI,QAAQ,KAAK,EAAE;AACzB,kBAAM,IAAI,MAAM,KAAK,EAAE;AAAA,UACzB;AACA,gBAAM,OAAO,KAAK,OAAO,OAAK,EAAE,SAAS,KAAK;AAC9C,cAAI,KAAK,OAAQ,OAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,YAAY,EAAE,MAAM,EAAE,SAAS,KAAM,CAAC,CAAC,CAAC;AACzF,eAAK,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,OAAK;AAC9C,kBAAM,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI;AAC/B,gBAAI,GAAI,IAAG,SAAS;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,GAAG;AAAA,EACL,GAAG,CAAC,QAAQ,SAAS,UAAU,SAAS,OAAO,MAAM,OAAO,UAAU,SAAS,KAAK,UAAU,MAAM,OAAO,CAAC;AAC9G;;;AC/IA,SAAgB,aAAAC,aAAW,eAAe;AAC1C,SAAS,OAAAC,MAAK,QAAAC,aAAY;AA0EpB,gBAAAC,MAAK,QAAAC,aAAL;AAlEC,SAAS,cAAc,SAAkB,QAAuB,kBAAyC;AAC9G,MAAI,QAAS,QAAO;AACpB,MAAI,UAAU,qBAAqB,QAAQ,oBAAoB,GAAG;AAChE,WAAO,UAAU,mBAAmB,UAAU,MAAM;AAAA,EACtD;AACA,SAAO;AACT;AAmBO,SAAS,UAAU,EAAE,MAAM,QAAQ,YAAY,QAAQ,gBAAgB,YAAY,QAAQ,SAAS,cAAc,aAAa,cAAc,OAAO,mBAAmB,KAAK,GAAU;AAC3L,QAAM,YAAY,SAAS,KAAK,OAAO,OAAK,EAAE,YAAY,MAAM,IAAI;AACpE,QAAM,WAAW,gBAAgB,QAC7B,YACA,gBAAgB,UACd,UAAU,OAAO,OAAK,EAAE,UAAU,OAAO,IACzC,UAAU,OAAO,OAAK,EAAE,UAAU,WAAW,EAAE,UAAU,MAAM;AACrE,QAAM,gBAAgB,KAAK,IAAI,GAAG,SAAS,CAAC;AAC5C,QAAM,aAAa,SAAS;AAG5B,QAAM,YAAY,KAAK,IAAI,GAAG,aAAa,aAAa;AACxD,QAAM,kBAAkB,iBAAiB,OAAO,mBAC5C,YACA,KAAK,IAAI,cAAc,SAAS;AACpC,QAAM,aAAa,KAAK,IAAI,GAAG,aAAa,gBAAgB,eAAe;AAC3E,QAAM,WAAW,KAAK,IAAI,aAAa,eAAe,UAAU;AAChE,QAAM,UAAU,SAAS,MAAM,YAAY,QAAQ;AAGnD,EAAAC,YAAU,MAAM;AACd,gBAAY;AAAA,EACd,GAAG,CAAC,QAAQ,YAAY,WAAW,CAAC;AAEpC,QAAM,UAAU,QAAQ,MAAM,qBAAqB,UAAU,GAAG,CAAC,UAAU,CAAC;AAE5E,QAAM,WAAW,kBAAkB;AACnC,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,SAAS,IAAI,MAAM,MAAM;AAAA,IACzB,aAAa,IAAI,UAAU,KAAK;AAAA,IAChC,SAAS,UAAU,oBAAoB;AAAA,IACvC,gBAAgB,QAAQ,WAAW,WAAW,GAAG,gBAAgB,SAAS,WAAW,EAAE,MAAM;AAAA,IAC7F,SAAS,aAAa;AAAA,IACtB,WAAW,aAAa;AAAA,IACxB,GAAG,SAAS,MAAM;AAAA,IAClB,WAAW,aAAa,IAAI,IAAI,aAAa,CAAC,IAAI,QAAQ,IAAI,UAAU,MAAM;AAAA,EAChF,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAE1B,SACE,gBAAAD,MAACE,MAAA,EAAI,eAAc,UAAS,aAAY,SAAQ,aAAa,cAAc,SAAS,QAAQ,gBAAgB,GAAG,QAC7G;AAAA,oBAAAH,KAACG,MAAA,EAAI,0BAAAF,MAACG,OAAA,EAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,MAAE;AAAA,MAAM;AAAA,OAAC,GAAO;AAAA,IAC5C,QAAQ,IAAI,CAAC,OAAO,MAAM;AACzB,YAAM,QAAQ,UAAU,MAAM,WAAW,UAAU,MAAM;AACzD,YAAM,KAAK,iBAAiB,IAAI,KAAK,MAAM,EAAE,EAAE,mBAAmB,OAAO,IAAI,MAAM;AACnF,YAAM,OAAO,MAAM;AACnB,YAAM,UAAU,UAAU,QAAQ,KAAK,IAAI,IAAI;AAC/C,aACE,gBAAAH,MAACE,MAAA,EACE;AAAA,0BAAkB,gBAAAH,KAACI,OAAA,EAAK,UAAQ,MAAE,cAAG;AAAA,QACtC,gBAAAH,MAACG,OAAA,EAAK,OAAc;AAAA;AAAA,UAAE,MAAM,QAAQ,OAAO,UAAU;AAAA,UAAE;AAAA,WAAC;AAAA,QACxD,gBAAAJ,KAACI,OAAA,EAAK,eAAC;AAAA,QACN,UAAU,gBAAAJ,KAACI,OAAA,EAAK,iBAAgB,UAAS,OAAM,SAAS,gBAAK,IAAU,gBAAAJ,KAACI,OAAA,EAAM,gBAAK;AAAA,WAJ5E,CAKV;AAAA,IAEJ,CAAC;AAAA,KACH;AAEJ;;;AC3FA,SAAS,OAAAC,MAAK,QAAAC,aAAY;AAKpB,SACE,OAAAC,MADF,QAAAC,aAAA;AAHC,SAAS,YAAY;AAC1B,SACE,gBAAAD,KAACF,MAAA,EACC,0BAAAG,MAACF,OAAA,EACC;AAAA,oBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,iBAAG;AAAA,IAAO;AAAA,IAAS,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,0BAAE;AAAA,IAAO;AAAA,IAAS,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,uBAAS;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,sBAAQ;AAAA,IAAO;AAAA,IAAW,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAQ,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAS,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAQ,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAM,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAU,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAS,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAQ,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAU,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,KAC3d,GACF;AAEJ;;;ACXA,SAAgB,YAAAG,WAAU,WAAAC,gBAAe;AACzC,SAAS,OAAAC,MAAK,QAAAC,OAAM,YAAAC,iBAAgB;AAiDa,SAEzC,OAAAC,MAFyC,QAAAC,aAAA;AAtC1C,SAAS,YAAY,EAAE,OAAO,UAAU,UAAU,SAAS,WAAW,GAAU;AACrF,QAAM,WAAWL;AAAA,IACf,MAAM,CAAC,GAAG,SAAS,KAAK,CAAC,EAAE,OAAO,OAAK,CAAC,cAAc,SAAS,IAAI,CAAC,EAAG,IAAI,SAAS,UAAU;AAAA,IAC9F,CAAC,UAAU,UAAU;AAAA,EACvB;AACA,QAAM,CAAC,KAAK,MAAM,IAAID,UAAS,CAAC;AAChC,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,EAAE;AAErC,QAAM,QAAQC,SAAQ,MAAM;AAC1B,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,IAAI,MAAM,YAAY;AAC5B,WAAO,SAAS,OAAO,OAAK,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AAAA,EACzD,GAAG,CAAC,UAAU,KAAK,CAAC;AAGpB,QAAM,UAAU,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,MAAM,SAAS,CAAC,CAAC;AAE3D,EAAAG,UAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,UAAI,MAAO,UAAS,EAAE;AAAA,UACjB,SAAQ;AACb;AAAA,IACF;AACA,QAAI,IAAI,QAAQ;AACd,UAAI,MAAM,OAAO,EAAG,UAAS,MAAM,OAAO,CAAE;AAC5C;AAAA,IACF;AACA,QAAI,IAAI,SAAS;AAAE,aAAO,OAAK,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AAAG;AAAA,IAAQ;AAC5D,QAAI,IAAI,WAAW;AAAE,aAAO,OAAK,KAAK,IAAI,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC;AAAG;AAAA,IAAQ;AAC7E,QAAI,IAAI,aAAa,IAAI,QAAQ;AAAE,eAAS,OAAK,EAAE,MAAM,GAAG,EAAE,CAAC;AAAG,aAAO,CAAC;AAAG;AAAA,IAAQ;AACrF,QAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,QAAQ,MAAM,WAAW,GAAG;AACzD,eAAS,OAAK,IAAI,KAAK;AACvB,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,EAAE,UAAU,QAAQ,MAAM,SAAS,MAAM,CAAC;AAE7C,SACE,gBAAAE,MAACJ,MAAA,EAAI,eAAc,UAAS,aAAY,SAAQ,aAAY,QAAO,UAAU,GAC3E;AAAA,oBAAAI,MAACH,OAAA,EAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,MAAE;AAAA,MAAM;AAAA,MAAE,SAAS,gBAAAG,MAACH,OAAA,EAAK,OAAM,UAAS;AAAA;AAAA,QAAE;AAAA,QAAM;AAAA,SAAC;AAAA,OAAQ;AAAA,IAChF,MAAM,WAAW,IAChB,gBAAAE,KAACF,OAAA,EAAK,UAAQ,MAAC,4BAAc,IAE7B,MAAM,IAAI,CAAC,MAAM,MACf,gBAAAE,KAACH,MAAA,EACC,0BAAAI,MAACH,OAAA,EAAK,OAAO,MAAM,UAAU,SAAS,QAAW,SAAS,MAAM,SAAS;AAAA;AAAA,MAAE;AAAA,MAAK;AAAA,MAAG,SAAS,IAAI,IAAI,EAAG,IAAI;AAAA,MAAK;AAAA,OAAC,KADzG,IAEV,CACD;AAAA,IAEH,gBAAAE,KAACF,OAAA,EAAK,UAAQ,MAAC,kFAA0D;AAAA,KAC3E;AAEJ;;;AC/DA,SAAgB,YAAAI,iBAAgB;AAChC,SAAS,OAAAC,MAAK,QAAAC,OAAM,YAAAC,iBAAgB;AAkBhC,SACE,OAAAC,MADF,QAAAC,aAAA;AAXG,SAAS,YAAY,EAAE,UAAU,QAAQ,GAAU;AACxD,QAAM,CAAC,OAAO,QAAQ,IAAIL,UAAS,EAAE;AAErC,EAAAG,UAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,OAAQ,SAAQ;AAAA,aACf,IAAI,OAAQ,UAAS,MAAM,KAAK,KAAK,IAAI;AAAA,aACzC,IAAI,aAAa,IAAI,OAAQ,UAAS,OAAK,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,aACzD,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAM,UAAS,OAAK,IAAI,KAAK;AAAA,EACnE,GAAG,EAAE,UAAU,QAAQ,MAAM,SAAS,MAAM,CAAC;AAE7C,SACE,gBAAAE,MAACJ,MAAA,EAAI,aAAY,SAAQ,aAAY,UAAS,UAAU,GACtD;AAAA,oBAAAG,KAACF,OAAA,EAAK,MAAI,MAAC,OAAM,UAAS,sBAAQ;AAAA,IAClC,gBAAAE,KAACF,OAAA,EAAM,iBAAM;AAAA,IACb,gBAAAE,KAACF,OAAA,EAAK,UAAQ,MAAC,oBAAC;AAAA,KAClB;AAEJ;;;AfyFQ,SAIF,OAAAI,MAJE,QAAAC,aAAA;AAvFD,SAAS,gBACd,MACA,MACA,aACA,WACQ;AACR,MAAI,eAAe,WAAW;AAC5B,UAAM,MAAM,UAAU,OAAO,IAAI;AACjC,QAAI,QAAQ,QAAW;AACrB,YAAM,OAAO,MAAM,GAAG,GAAG,IAAI,UAAU,MAAM,KAAK,UAAU;AAC5D,YAAM,SAAS,UAAU,MAAM,UAAU;AACzC,aAAO,GAAG,MAAM,MAAM,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,SAAO,oBAAoB,IAAI;AACjC;AAcO,SAAS,IAAI,EAAE,QAAQ,UAAU,SAAS,UAAU,KAAK,SAAS,eAAe,WAAW,QAAQ,GAAU;AACnH,QAAM,OAAO,gBAAgB;AAC7B,QAAM,aAAa,KAAK,MAAM,OAAO,IAAI;AACzC,QAAM,cAAc,OAAO,aAAa;AACxC,QAAM,aAAa,KAAK,IAAI,GAAG,SAAS,IAAI,OAAK,EAAE,KAAK,MAAM,GAAG,EAAE;AAEnE,QAAM,KAAK,kBAAkB,UAAU,SAAS,KAAK,OAAO;AAC5D,QAAM,cAAcC,QAA+B,oBAAI,IAAI,CAAC;AAC5D,QAAM,YAAYA,QAAuB,CAAC,CAAC;AAE3C,QAAM,KAAK,eAAe;AAAA,IACxB,QAAQ,MAAM;AAAE,WAAK,SAAS;AAAA,IAAG;AAAA,IACjC,aAAa,GAAG;AAAA,IAChB,eAAe,MAAM;AAAA,IAAC;AAAA,EACxB,CAAC;AAED,QAAM,WAAW,iBAAiB,YAAY,EAAE,UAAU,eAAe,MAAM,UAAU,IAAI;AAC7F,QAAM,eAAe,gBAAgB,GAAG,SAAS,OAAO,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,UAAU,QAAQ;AAE7H,QAAM,WAAWC,aAAY,YAAY;AACvC,gBAAY,QAAQ,QAAQ,OAAK,EAAE,QAAQ,CAAC;AAC5C,UAAM,aAAa,SAAS,MAAM;AAClC,UAAM,GAAG,QAAQ;AACjB,QAAI,UAAU,QAAQ,QAAQ;AAC5B,YAAM,cAAc,UAAU,SAAS,UAAU;AAAA,QAC/C;AAAA,QAAS;AAAA,QACT,OAAO,CAAC,KAAK,QAAQ,GAAG,QAAQ,OAAO,GAAG,IAAI,KAAK,EAAE;AAAA,MACvD,CAAC;AACD,gBAAU,UAAU,CAAC;AAAA,IACvB;AACA,UAAM,SAAS,MAAM;AACrB,YAAQ,KAAK,CAAC;AAAA,EAChB,GAAG,CAAC,IAAI,SAAS,UAAU,SAAS,KAAK,YAAY,CAAC;AAEtD,eAAa,GAAG,SAAS,SAAS,SAAS,GAAG,OAAO;AACrD,eAAa,GAAG,WAAW,GAAG,YAAY,GAAG,gBAAgB;AAC7D,QAAM,YAAY,kBAAkB,GAAG,KAAK,QAAQ,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,GAAG,WAAW,GAAG,MAAM;AAC9F,eAAa,eAAe,WAAW,GAAG,QAAQ,GAAG,YAAY;AACjE;AAAA,IAAgB,GAAG;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAU;AAAA,IAAS;AAAA,IAAU;AAAA,IAAK;AAAA,IACpE,EAAE,aAAa,UAAU;AAAA,IAAG,GAAG;AAAA,EAAO;AAExC,QAAM,qBAAqBA,aAAY,CAAC,SAAiB,GAAG,UAAU,IAAI,GAAG,CAAC,EAAE,CAAC;AACjF,QAAM,sBAAsBA,aAAY,CAAC,SAAiB;AAAE,OAAG,QAAQ,IAAI;AAAG,OAAG,SAAS,MAAM;AAAA,EAAG,GAAG,CAAC,IAAI,EAAE,CAAC;AAC9G,QAAM,mBAAmBA,aAAY,CAAC,SAAiB;AACrD,UAAM,KAAK,GAAG,OAAO,IAAI,IAAI;AAC7B,QAAI,IAAI;AACN,YAAM,MAAM,gBAAgB,MAAM,GAAG,IAAI,MAAM,QAAQ,OAAO,SAAS;AACvE,eAAS,YAAY,GAAG;AAAA,IAC1B;AACA,OAAG,SAAS,MAAM;AAAA,EACpB,GAAG,CAAC,IAAI,UAAU,IAAI,QAAQ,OAAO,SAAS,CAAC;AAE/C,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,YAAY,QAAQ,QAAQ,OAAO,OAAO,SAAS;AAEzD,SACE,gBAAAF,MAACG,MAAA,EAAI,eAAc,UAAS,QAAQ,MAClC;AAAA,oBAAAH,MAACG,MAAA,EACC;AAAA,sBAAAH,MAACI,OAAA,EAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,QAAE;AAAA,QAAK;AAAA,QAAE,OAAO;AAAA,QAAK;AAAA,QAAY,SAAS;AAAA,QAAO;AAAA,QAAY;AAAA,QAAU;AAAA,SAAE;AAAA,MAChG,aAAa,gBAAAJ,MAACI,OAAA,EAAK,UAAQ,MAAC;AAAA;AAAA,QAAI;AAAA,SAAU;AAAA,OAC7C;AAAA,IAEA,gBAAAL;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,GAAG;AAAA,QAAM,QAAQ,GAAG;AAAA,QAAW,YAAY,GAAG;AAAA,QACpD,QAAQ,GAAG;AAAA,QAAY,gBAAgB,GAAG;AAAA,QAC1C;AAAA,QAAwB,QAAQ;AAAA,QAAY,SAAS,GAAG,UAAU;AAAA,QAClE,cAAc,GAAG;AAAA,QAAkB,aAAa,GAAG;AAAA,QACnD,aAAa,GAAG;AAAA,QAChB,kBAAkB,GAAG,YAAa,GAAG,OAAO,IAAI,GAAG,SAAS,GAAG,YAAY,OAAQ;AAAA;AAAA,IACrF;AAAA,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ,GAAG;AAAA,QAAQ,OAAO,GAAG;AAAA,QAAO,UAAU,GAAG;AAAA,QACjD;AAAA,QAAwB,QAAQ;AAAA,QAAa,SAAS,GAAG,UAAU;AAAA,QACnE,cAAc,GAAG;AAAA,QAAmB,aAAa,GAAG;AAAA,QACpD,SAAS,GAAG;AAAA;AAAA,IACd;AAAA,IAEC,GAAG,UAAU,YACZ,gBAAAA,KAAC,eAAY,OAAM,qBAAoB,UAAU,GAAG,QAAQ,UAAU,oBAAoB,SAAS,MAAM,GAAG,SAAS,MAAM,GAAG;AAAA,IAE/H,GAAG,UAAU,aACZ,gBAAAA,KAAC,eAAY,OAAM,mBAAkB,UAAU,GAAG,QAAQ,UAAU,qBAAqB,SAAS,MAAM,GAAG,SAAS,MAAM,GAAG;AAAA,IAE9H,GAAG,UAAU,UACZ,gBAAAA,KAAC,eAAY,OAAM,mBAAkB,UAAU,GAAG,QAAQ,UAAU,kBAAkB,SAAS,MAAM,GAAG,SAAS,MAAM,GAAG,YAAW,OAAM;AAAA,IAE5I,GAAG,UAAU,YACZ,gBAAAA,KAAC,eAAY,UAAU,GAAG,WAAW,SAAS,MAAM,GAAG,SAAS,MAAM,GAAG;AAAA,IAG3E,gBAAAA,KAAC,aAAU;AAAA,KACb;AAEJ;;;AgBrIO,SAAS,aAAa,MAA0B;AACrD,QAAM,EAAE,QAAQ,UAAU,SAAS,KAAK,eAAe,UAAU,IAAI;AACrE,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,aAAa,OAAO,QAAQ,WAAI,IAAI,OAAO,IAAI,EAAE;AAC5D,QAAM,KAAK,aAAa,QAAQ,QAAQ,OAAO,OAAO,SAAS,QAAQ,EAAE;AACzE,MAAI,QAAQ,QAAS,OAAM,KAAK,aAAa,QAAQ,OAAO,EAAE;AAC9D,QAAM,KAAK,aAAa,SAAS,MAAM,EAAE;AACzC,QAAM,KAAK,EAAE;AAEb,MAAI,OAAO,UAAU,QAAQ;AAC3B,UAAM,KAAK,cAAc,OAAO,SAAS,MAAM,IAAI;AACnD,eAAW,OAAO,OAAO,UAAU;AACjC,YAAM,KAAK,IAAI;AACf,YAAM,QAAQ,KACV,WAAW,GAAG,IAAI,GAAG,GAAG,SAAS,SAAS,OAAO,GAAG,QAAQ,OAAO,EAAE,KAAK,IAAI,QAAQ,GAAG,KACzF;AACJ,YAAM,KAAK,OAAO,IAAI,KAAK,OAAO,EAAE,CAAC,IAAI,IAAI,GAAG,GAAG,KAAK,EAAE;AAAA,IAC5D;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,WAAW,QAAQ,QAAQ,CAAC,CAAC,OAAO;AAC1C,MAAI,WAA4B;AAChC,MAAI,OAAwB,CAAC;AAC7B,MAAI,UAAU;AACZ,UAAM,IAAI,iBAAiB,UAAU,OAAO,IAAK;AACjD,eAAW,EAAE;AACb,WAAO,EAAE;AAAA,EACX;AAEA,QAAM,SAAS,aAAa,QAAQ;AACpC,QAAM,YAAY,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACtE,aAAW,OAAO,WAAW;AAC3B,UAAM,KAAK,SAAS,GAAG,GAAG;AAC1B,eAAW,OAAO,OAAO,GAAG,GAAI;AAC9B,YAAM,KAAK,cAAc,KAAK,KAAK,KAAK,CAAC;AAAA,IAC3C;AAAA,EACF;AAEA,MAAI,KAAK,QAAQ;AACf,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,mBAAmB;AAC9B,eAAW,OAAO,MAAM;AACtB,YAAM,YAAY,mBAAmB,GAAG;AACxC,YAAM,KAAK,cAAc,WAAW,KAAK,IAAI,CAAC;AAC9C,YAAM,KAAK,gBAAgB,IAAI,IAAI,YAAO,gBAAgB,IAAI,IAAI,CAAC,kBAAkB,QAAQ,WAAW,IAAI;AAAA,IAC9G;AAAA,EACF;AAEA,MAAI,iBAAiB,WAAW;AAC9B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,aAAa,cAAc,IAAI,WAAM,UAAU,QAAQ,EAAE;AAEpE,UAAM,YAAY,oBAAI,IAA0B;AAChD,eAAW,OAAO,UAAU;AAC1B,YAAM,OAAO,YAAY,CAAC,SAAS,SAAS,GAAG,IAAI,gBAAgB,IAAI,IAAI,IAAI;AAC/E,gBAAU,IAAI,IAAI,MAAM,EAAE,MAAM,IAAI,MAAM,QAAQ,MAAM,UAAU,KAAK,CAAC;AAAA,IAC1E;AACA,UAAM,UAAU,cAAc,SAAS,WAAW,SAAS;AAC3D,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,0BAA0B;AACrC,UAAM,KAAK,OAAO;AAAA,EACpB;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,cAAc,KAAoB,KAA6B,QAAyB;AAC/F,QAAM,OAAO,iBAAiB,GAAG;AACjC,QAAM,UAAU,CAAC,IAAI,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;AAC3C,QAAM,QAAQ,gBAAgB,KAAK,GAAG;AACtC,QAAM,WAAW,OAAO,KAAK,IAAI,YAAY,CAAC,CAAC,EAAE,SAC7C,WAAW,OAAO,QAAQ,IAAI,QAAS,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,IAC9E;AACJ,QAAM,SAAS,IAAI,SAAS,QAAQ,IAAI,MAAM,OAAO;AACrD,QAAM,KAAK,IAAI;AACf,QAAM,QAAQ,IAAI,SAAS,SAAS,gBAAgB,GAAG,QAAQ,GAAG,KAAK;AACvE,QAAM,UAAU,SAAS,YAAY;AACrC,OAAK;AACL,SAAO,OAAO,IAAI,KAAK,OAAO,EAAE,CAAC,KAAK,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ;AAChH;AAEO,SAAS,UAAU,MAAwB;AAEhD,UAAQ,IAAI,aAAa,IAAI,CAAC;AAChC;;;AChFA,eAAsB,QAAQ,MAAiC;AAC7D,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,QAAM,EAAE,QAAQ,UAAU,SAAS,UAAU,KAAK,SAAS,QAAQ,IAAI;AAEvE,QAAM,MAAM,IAAI,eAAe;AAAA,IAC7B;AAAA,IAAS;AAAA,IAAK;AAAA,IACd,QAAQ;AAAA,MACN,OAAO,CAAC,KAAK,SAAS;AAAE,iBAAS,MAAM,KAAK,IAAI;AAAG,YAAI,IAAI,GAAG,KAAK,IAAI,EAAE;AAAA,MAAG;AAAA,MAC5E,eAAe,MAAM;AAAA,MAAC;AAAA,IACxB;AAAA,EACF,CAAC;AAGD,MAAI,YAA4B,CAAC;AACjC,MAAI,OAAO,UAAU,QAAQ;AAC3B,QAAI,qBAAgB,OAAO,SAAS,MAAM,GAAG;AAC7C,UAAM,SAAS,MAAM,eAAe,OAAO,UAAU;AAAA,MACnD;AAAA,MAAS;AAAA,MAAK;AAAA,MACd,OAAO,CAAC,KAAK,QAAQ;AAAE,iBAAS,MAAM,OAAO,GAAG,IAAI,GAAG;AAAG,YAAI,QAAQ,GAAG,KAAK,GAAG,EAAE;AAAA,MAAG;AAAA,IACxF,CAAC;AACD,gBAAY,OAAO;AACnB,QAAI,CAAC,OAAO,YAAY;AACtB,UAAI,4BAAuB,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AACrD,YAAM,cAAc,WAAW,UAAU,EAAE,SAAS,IAAI,CAAC;AACzD,YAAM,IAAI,QAAQ;AAClB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,SAAS,aAAa,QAAQ;AACpC,QAAM,YAAY,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACtE,QAAM,WAAW,SAAS,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,IAAI,OAAK,EAAE,IAAI;AACvE,QAAM,WAAW,KAAK,IAAI,IAAI,QAAQ,cAAc;AACpD,MAAI,WAAW;AAEf,aAAW,OAAO,WAAW;AAC3B,QAAI,gBAAW,GAAG,EAAE;AACpB,eAAW,OAAO,OAAO,GAAG,GAAI;AAC9B,YAAM,KAAK;AACX,YAAM,YAAY,MAAM,IAAI,QAAQ,KAAK,EAAE;AAC3C,UAAI,CAAC,WAAW;AACd,YAAI,6BAAwB,IAAI,IAAI,EAAE;AACtC,cAAM,IAAI,QAAQ;AAClB,cAAM,cAAc,WAAW,UAAU,EAAE,SAAS,IAAI,CAAC;AACzD,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,KAAK,EAAE;AAAA,IACzB;AAGA,UAAM,OAAO,OAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK;AACtD,eAAW,OAAO,MAAM;AACtB,YAAM,KAAK,MAAMM,aAAY,KAAK,QAAQ;AAC1C,UAAI,CAAC,IAAI;AACP,YAAI,UAAK,IAAI,IAAI,kCAAkC,QAAQ,WAAW,GAAG;AACzE,cAAM,IAAI,QAAQ;AAClB,cAAM,cAAc,WAAW,UAAU,EAAE,SAAS,IAAI,CAAC;AACzD,eAAO;AAAA,MACT;AACA,UAAI,UAAK,IAAI,IAAI,QAAQ;AACzB,YAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,UAAI,IAAI;AAAE,WAAG,SAAS;AAAW,WAAG,SAAS;AAAA,MAAM;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,UAAU,UAAU,SAAS,MAAM,cAAc,QAAQ,cAAc,OAAQ,WAAW,KAAK,IAAI,MAAM,KAAM,QAAQ,CAAC,CAAC;AAC/H,MAAI,OAAO;AACX,QAAM,IAAI,QAAQ;AAClB,QAAM,cAAc,WAAW,UAAU,EAAE,SAAS,IAAI,CAAC;AACzD,SAAO;AACT;AAEA,eAAeA,aAAY,KAAoB,UAAoC;AACjF,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,KAAK,MAAM,YAAY,IAAI,MAAM,IAAI,WAAW;AACtD,QAAI,GAAI,QAAO;AACf,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;;;ACbO,SAAS,aAAa,QAAwC;AACnE,SAAO;AACT;;;AxD/DA,SAAS,cAAsB;AAC7B,MAAI;AACF,UAAM,OAAOC,SAAQC,eAAc,YAAY,GAAG,CAAC;AACnD,UAAM,UAAUC,OAAK,MAAM,MAAM,cAAc;AAC/C,WAAO,KAAK,MAAMC,cAAa,SAAS,MAAM,CAAC,EAAE,WAAW;AAAA,EAC9D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,OAAO;AACpB,QAAM,MAAM,QAAQ,KAAK,MAAM,CAAC;AAEhC,MAAI,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,WAAW,GAAG;AACnD,YAAQ,IAAI,YAAY,CAAC;AACzB;AAAA,EACF;AACA,MAAI,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,QAAQ,GAAG;AAChD,YAAQ,IAAI,KAAK;AACjB;AAAA,EACF;AAIA,QAAM,SAAS,iBAAiB,GAAG;AACnC,MAAI,WAAW,QAAQ;AACrB,YAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC;AAAA,EACpC;AAEA,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,UAAU,aAAa,GAAG;AAEhC,MAAI,QAAQ;AACV,UAAM,UAAU,IAAI,MAAM,CAAC;AAE3B,QAAI;AACJ,QAAI;AAAE,gBAAU,eAAe,KAAK,QAAQ,UAAU;AAAA,IAAG,SAClD,GAAQ;AAAE,cAAQ,MAAM,UAAK,EAAE,OAAO,EAAE;AAAG,cAAQ,KAAK,CAAC;AAAA,IAAG;AACnE,UAAM,MAAM,MAAM,WAAW,OAAO;AACpC,UAAM,UAAU,EAAE,QAAQ,KAAK,SAAS,KAAK,KAAK,QAAQ,KAA+B,QAAQ,QAAQ,OAAO;AAChH,QAAI,WAAW,OAAW,SAAQ,KAAK,MAAM,QAAQ,SAAS,OAAO,CAAC;AACtE,QAAI,WAAW,UAAW,SAAQ,KAAK,MAAM,WAAW,OAAO,CAAC;AAChE,QAAI,WAAW,SAAW,SAAQ,KAAK,MAAM,UAAU,OAAO,CAAC;AAC/D,QAAI,WAAW,MAAW,SAAQ,KAAK,MAAM,OAAO,SAAS,OAAO,CAAC;AACrE,QAAI,WAAW,OAAW,SAAQ,KAAK,MAAM,QAAQ,OAAO,CAAC;AAAA,EAE/D;AAGA,MAAI;AACJ,MAAI;AACF,iBAAa,eAAe,KAAK,QAAQ,UAAU;AAAA,EACrD,SAAS,GAAQ;AACf,YAAQ,MAAM,UAAK,EAAE,OAAO,EAAE;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,MAAM,WAAW,UAAU;AAG1C,QAAM,SAAS,eAAe,QAAQ,GAAG;AACzC,MAAI,OAAO,QAAQ;AACjB,YAAQ,MAAM;AAAA,EAAgC,uBAAuB,MAAM,CAAC,EAAE;AAC9E,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,WAAW,gBAAgB,MAAM;AACvC,MAAI,SAAS,QAAQ;AACnB,YAAQ,KAAK;AAAA,EAAuB,yBAAyB,QAAQ,CAAC,EAAE;AAAA,EAC1E;AAGA,MAAI;AACJ,MAAI;AACF,eAAW,eAAe,OAAO,UAAU,SAAS,MAAM;AAAA,EAC5D,SAAS,GAAQ;AACf,YAAQ,MAAM,UAAK,EAAE,OAAO,EAAE;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,CAAC,SAAS,QAAQ;AACpB,YAAQ,MAAM,2CAAsC;AACpD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,WAAW,MAAM,eAAe;AAGtC,QAAM,UAAU,OAAO,UAAUD,OAAK,KAAK,OAAO,OAAO,IAAIA,OAAK,KAAK,MAAM;AAC7E,QAAM,MAAM,aAAa,SAAS,QAAQ,GAA6B;AACvE,MAAI,OAAO,KAAK;AACd,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG,GAAG;AAC/C,UAAI,CAAC,IAAI,CAAC,EAAG,KAAI,CAAC,IAAI;AAAA,IACxB;AAAA,EACF;AAGA,MAAI,gBAA4C;AAChD,MAAI,YAA8B;AAClC,MAAI,QAAQ,SAAS,OAAO,OAAO;AACjC,oBAAgB,oBAAoB,OAAO,MAAM,QAAQ;AACzD,gBAAY;AAAA,MACV,MAAM,QAAQ,aAAa,OAAO,MAAM,QAAQ,SAAS;AAAA,MACzD,QAAQ,IAAI,iBAAiB,KAAK,IAAI,QAAQ,KAAK;AAAA,MACnD,QAAQ,OAAO,MAAM;AAAA,MACrB,KAAK,QAAQ,YAAY,OAAO,MAAM,OAAO;AAAA,MAC7C,YAAY,QAAQ,mBAAmB,OAAO,MAAM,cAAc;AAAA,MAClE,UAAU,QAAQ,aAAa,OAAO,MAAM,YAAYA,OAAKE,SAAQ,GAAG,YAAY,mBAAmB;AAAA,IACzG;AAAA,EACF;AAGA,MAAI,QAAQ,QAAQ;AAClB,cAAU,EAAE,QAAQ,UAAU,SAAS,KAAK,SAAS,KAAK,eAAe,UAAU,CAAC;AACpF;AAAA,EACF;AAGA,MAAI,UAA0B;AAC9B,MAAI,QAAQ,SAAS;AACnB,cAAU,IAAI,QAAQ,EAAE,aAAa,OAAO,MAAM,SAAS,QAAQ,OAAO,CAAC;AAAA,EAC7E;AAOA,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,UAAM,eAAe,gBAAgB,OAAO,IAAI;AAChD,QAAI,aAAa,OAAO,CAAC,aAAa,OAAO;AAC3C,cAAQ,MAAM,iDAA4C,OAAO,IAAI,UAAU,aAAa,GAAG,IAAI;AACnG,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,qEAAqE;AACnF,cAAQ,MAAM,oBAAoB;AAClC,cAAQ,MAAM,iCAAiC;AAC/C,cAAQ,MAAM,2BAA2B;AACzC,YAAM,SAAS,MAAM;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAKA,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,UAAM,YAAY,MAAM,kBAAkB,QAAQ;AAClD,QAAI,UAAU,QAAQ;AACpB,YAAM,WAAW,MAAM,qBAAqB,WAAW;AAAA,QACrD,UAAU,QAAQ;AAAA,QAClB,KAAK,SAAO,QAAQ,OAAO,MAAM,MAAM,IAAI;AAAA,QAC3C,QAAQ,MAAM,SAAS,4CAA4C;AAAA,MACrE,CAAC;AACD,UAAI,CAAC,UAAU;AACb,cAAM,SAAS,MAAM;AACrB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,QAAQ,MAAM;AAChB,UAAM,OAAO,MAAM,QAAQ;AAAA,MACzB;AAAA,MAAQ;AAAA,MAAU;AAAA,MAAS;AAAA,MAAU;AAAA,MAAK,SAAS;AAAA,MAAK;AAAA,IAC1D,CAAC;AACD,UAAM,SAAS,MAAM;AACrB,YAAQ,KAAK,IAAI;AAAA,EACnB;AAIA,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,UAAM,WAAW,EAAE,QAAQ,UAAU,SAAS,UAAU,KAAK,SAAS,KAAK,eAAe,UAAU,CAAC;AACrG;AAAA,EACF;AAGA,MAAI,WAAW,MAAM;AACnB,QAAI,CAAC,IAAI,SAAS,IAAI,KAAK,CAAC,IAAI,SAAS,UAAU,GAAG;AACpD,cAAQ,MAAM,qDAAqD;AACnE,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,YAAQ,KAAK,MAAM,YAAY;AAAA,MAC7B;AAAA,MAAQ;AAAA,MAAU;AAAA,MAAS;AAAA,MAAU;AAAA,MAAK,SAAS;AAAA,MAAK;AAAA,MAAe;AAAA,IACzE,CAAC,CAAC;AAAA,EACJ;AAGA,QAAM,gBAAgB,QAAQ,MAAM,SAAS;AAC7C,QAAM,EAAE,cAAc,IAAI;AAAA,IACxBC,OAAM,cAAc,KAAK;AAAA,MACvB;AAAA,MAAQ;AAAA,MAAU;AAAA,MAAS;AAAA,MAAU;AAAA,MAAK,SAAS;AAAA,MACnD;AAAA,MAAe;AAAA,MAAW;AAAA,IAC5B,CAAC;AAAA,IACD,EAAE,aAAa,OAAO,cAAc,eAAe,aAAa,cAAc;AAAA,EAChF;AAEA,QAAM,cAAc;AACtB;AAWA,SAAS,SAAS,UAAoC;AACpD,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAC5B,UAAM,QAAQ,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,SAAS,QAAQ,OAAO,KAAK;AACzF,QAAI,CAAC,OAAO;AAAE,MAAAA,SAAQ,KAAK;AAAG;AAAA,IAAQ;AAEtC,YAAQ,OAAO,MAAM,QAAQ;AAC7B,YAAQ,MAAM,OAAO;AACrB,YAAQ,MAAM,YAAY,MAAM;AAEhC,UAAM,UAAU,MAAM;AACpB,cAAQ,MAAM,eAAe,QAAQ,MAAM;AAC3C,cAAQ,MAAM,eAAe,OAAO,KAAK;AACzC,cAAQ,MAAM,MAAM;AAAA,IACtB;AACA,UAAM,SAAS,CAAC,SAA0B;AACxC,cAAQ;AACR,MAAAA,SAAQ,YAAY,KAAK,OAAO,IAAI,EAAE,KAAK,CAAC,CAAC;AAAA,IAC/C;AACA,UAAM,QAAQ,MAAM;AAAE,cAAQ;AAAG,MAAAA,SAAQ,KAAK;AAAA,IAAG;AAEjD,YAAQ,MAAM,KAAK,QAAQ,MAAM;AACjC,YAAQ,MAAM,KAAK,OAAO,KAAK;AAAA,EACjC,CAAC;AACH;AAgBA,SAAS,oBAA6B;AACpC,QAAM,WAAW,QAAQ,KAAK,CAAC;AAC/B,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,aAAaL,eAAc,YAAY,GAAG;AAChD,MAAI;AACF,WAAO,aAAa,QAAQ,MAAM;AAAA,EACpC,QAAQ;AACN,WAAO,aAAa;AAAA,EACtB;AACF;AAEA,IAAI,kBAAkB,GAAG;AACvB,OAAK,EAAE,MAAM,OAAK;AAChB,YAAQ,MAAM,CAAC;AACf,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":["React","readFileSync","dirname","join","fileURLToPath","homedir","existsSync","resolve","existsSync","resolve","spawn","createReadStream","watchFile","unwatchFile","existsSync","statSync","readFile","join","dirname","homedir","createInterface","resolve","existsSync","lower","existsSync","readFileSync","join","createInterface","existsSync","existsSync","join","resolve","existsSync","resolve","createInterface","spawn","writeFileSync","readFileSync","existsSync","unlinkSync","mkdirSync","join","homedir","createInterface","join","existsSync","existsSync","resolve","spawn","existsSync","join","resolve","join","existsSync","resolve","spawn","resolve","join","existsSync","mkdirSync","join","dirname","homedir","spawn","join","resolve","join","spawn","net","net","sanitize","join","homedir","existsSync","readFileSync","mkdirSync","unlinkSync","resolve","createInterface","services","writeFileSync","spawn","p","join","homedir","sanitize","existsSync","statSync","resolve","createInterface","createReadStream","watchFile","unwatchFile","spawn","sleep","pidAlive","sleep","existsSync","mkdirSync","writeFileSync","dirname","existsSync","mkdirSync","writeFileSync","dirname","EMPTY_CONFIG","existsSync","mkdirSync","writeFileSync","dirname","EMPTY_CONFIG","useCallback","useRef","Box","Text","mgr","useState","useCallback","next","useEffect","useRef","useEffect","useState","useEffect","useEffect","useRef","createInterface","createReadStream","existsSync","totalmem","freemem","cpus","useRef","useEffect","existsSync","resolve","createInterface","createReadStream","totalmem","freemem","cpus","useEffect","useEffect","useEffect","useRef","useState","useEffect","useState","MAX_RESTARTS","cpus","useEffect","useState","useRef","useState","useEffect","useEffect","useState","useState","useEffect","useEffect","Box","Text","jsx","jsxs","useEffect","Box","Text","Box","Text","jsx","jsxs","useState","useMemo","Box","Text","useInput","jsx","jsxs","useState","Box","Text","useInput","jsx","jsxs","jsx","jsxs","useRef","useCallback","Box","Text","waitHealthy","dirname","fileURLToPath","join","readFileSync","homedir","React","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config/loader.ts","../src/config/validator.ts","../src/lazy/classifier.ts","../src/config/cli.ts","../src/orchestrator/subcommands.ts","../src/process/health.ts","../src/utils/env.ts","../src/utils/format.ts","../src/utils/search.ts","../src/utils/redact.ts","../src/utils/install-stamp.ts","../src/utils/process-args.ts","../src/utils/stats.ts","../src/utils/phases.ts","../src/utils/colors.ts","../src/control-plane/client.ts","../src/control-plane/socket-server.ts","../src/orchestrator/daemon.ts","../src/process/manager.ts","../src/process/installer.ts","../src/process/spawner.ts","../src/process/internals.ts","../src/process/restarter.ts","../src/process/health-poller.ts","../src/process/lifecycle.ts","../src/process/log-sink.ts","../src/utils/broadcaster.ts","../src/process/external.ts","../src/lazy/proxy.ts","../src/orchestrator/config-watcher.ts","../src/config/diff.ts","../src/process/port-conflicts.ts","../src/platform/detect.ts","../src/proxy-config/traefik.ts","../src/proxy-config/nginx.ts","../src/proxy-config/caddy.ts","../src/proxy-config/detect.ts","../src/tui/App.tsx","../src/tui/hooks/useProcessManager.ts","../src/tui/hooks/useKeyBindings.ts","../src/tui/hooks/useProxySync.ts","../src/tui/hooks/useTerminalSize.ts","../src/tui/hooks/useLogsPause.ts","../src/tui/hooks/useControlPlane.ts","../src/tui/hooks/useHotReload.ts","../src/tui/hooks/useContextualTips.ts","../src/tui/tips.ts","../src/tui/StatsPanel.tsx","../src/tui/hooks/useBootSequence.ts","../src/tui/LogsPanel.tsx","../src/tui/StatusBar.tsx","../src/tui/ServiceList.tsx","../src/tui/SearchInput.tsx","../src/orchestrator/dry-run.ts","../src/orchestrator/once.ts","../src/config/types.ts"],"sourcesContent":["import React from 'react';\nimport { render } from 'ink';\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { homedir } from 'node:os';\n\nimport { findConfigFile, loadConfig } from './config/loader.js';\nimport { validateConfig, formatValidationErrors, collectWarnings, formatValidationWarnings } from './config/validator.js';\nimport { parseCliArgs, filterServices, USAGE } from './config/cli.js';\nimport { detectSubcommand, runLogs, runInstall, runStatus, runHelp, runCtl, runDown } from './orchestrator/subcommands.js';\nimport { runDetached, daemonBody, isDaemonRunning } from './orchestrator/daemon.js';\nimport { scanPortConflicts, resolvePortConflicts } from './process/port-conflicts.js';\nimport { detectPlatform } from './platform/detect.js';\nimport { detectProxyProvider } from './proxy-config/detect.js';\nimport { parseEnvFile } from './utils.js';\nimport { App } from './tui/App.js';\nimport { LogSink } from './process/log-sink.js';\nimport { runDryRun } from './orchestrator/dry-run.js';\nimport { runOnce } from './orchestrator/once.js';\nimport type { ProxyConfigProvider, ProxyOpts } from './proxy-config/types.js';\n\n// Re-export for config files\nexport { defineConfig } from './config/types.js';\nexport type { DevStackConfig, ServiceConfig, LazyConfig, ProxyConfig } from './config/types.js';\nexport type { Platform, ProcessStats } from './platform/types.js';\nexport type { ProxyConfigProvider, ProxyOpts } from './proxy-config/types.js';\n\nfunction readVersion(): string {\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(here, '..', 'package.json');\n return JSON.parse(readFileSync(pkgPath, 'utf8')).version ?? 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\nasync function main() {\n const raw = process.argv.slice(2);\n // --version / --help short-circuit before any config loading\n if (raw.includes('-v') || raw.includes('--version')) {\n console.log(readVersion());\n return;\n }\n if (raw.includes('-h') || raw.includes('--help')) {\n console.log(USAGE);\n return;\n }\n\n // Subcommand dispatch (devup logs / install / status / help). All require the config\n // file to be present so we can know which services exist and where logs live.\n const subcmd = detectSubcommand(raw);\n if (subcmd === 'help') {\n process.exit(runHelp(raw.slice(1)));\n }\n\n const cwd = process.cwd();\n const cliArgs = parseCliArgs(raw);\n\n if (subcmd) {\n const subArgs = raw.slice(1);\n // Load config (no validation needed for read-only ops, but resolve path errors clearly)\n let cfgPath: string;\n try { cfgPath = findConfigFile(cwd, cliArgs.configPath); }\n catch (e: any) { console.error(`❌ ${e.message}`); process.exit(1); }\n const cfg = await loadConfig(cfgPath);\n const subOpts = { config: cfg, baseCwd: cwd, env: process.env as Record<string, string>, logDir: cliArgs.logDir };\n if (subcmd === 'logs') process.exit(await runLogs(subArgs, subOpts));\n if (subcmd === 'install') process.exit(await runInstall(subOpts));\n if (subcmd === 'status') process.exit(await runStatus(subOpts));\n if (subcmd === 'ctl') process.exit(await runCtl(subArgs, subOpts));\n if (subcmd === 'down') process.exit(await runDown(subOpts));\n // `up` falls through to the full setup pipeline so it can boot the stack like the TUI does.\n }\n\n // Load config\n let configPath: string;\n try {\n configPath = findConfigFile(cwd, cliArgs.configPath);\n } catch (e: any) {\n console.error(`❌ ${e.message}`);\n process.exit(1);\n }\n\n const config = await loadConfig(configPath);\n\n // Validate\n const errors = validateConfig(config, cwd);\n if (errors.length) {\n console.error(`❌ Config validation failed:\\n${formatValidationErrors(errors)}`);\n process.exit(1);\n }\n const warnings = collectWarnings(config);\n if (warnings.length) {\n console.warn(`⚠ Config warnings:\\n${formatValidationWarnings(warnings)}`);\n }\n\n // Filter services\n let services: ReturnType<typeof filterServices>;\n try {\n services = filterServices(config.services, cliArgs, config);\n } catch (e: any) {\n console.error(`❌ ${e.message}`);\n process.exit(1);\n }\n if (!services.length) {\n console.error('❌ No services to run after filtering');\n process.exit(1);\n }\n\n // Platform\n const platform = await detectPlatform();\n\n // Env\n const envFile = config.envFile ? join(cwd, config.envFile) : join(cwd, '.env');\n const env = parseEnvFile(envFile, process.env as Record<string, string>);\n if (config.env) {\n for (const [k, v] of Object.entries(config.env)) {\n if (!env[k]) env[k] = v;\n }\n }\n\n // Proxy provider\n let proxyProvider: ProxyConfigProvider | null = null;\n let proxyOpts: ProxyOpts | null = null;\n if (cliArgs.proxy && config.proxy) {\n proxyProvider = detectProxyProvider(config.proxy.provider);\n proxyOpts = {\n host: cliArgs.proxyHost ?? config.proxy.host ?? platform.defaultTraefikHost,\n domain: env['GUESTHUB_DOMAIN'] ?? env['DOMAIN'] ?? 'localhost',\n routes: config.proxy.routes,\n tls: cliArgs.proxyTls ?? config.proxy.tls ?? true,\n entrypoint: cliArgs.proxyEntrypoint ?? config.proxy.entrypoint ?? 'websecure',\n confPath: cliArgs.proxyConf ?? config.proxy.confPath ?? join(homedir(), '.traefik', 'traefik_conf.yaml'),\n };\n }\n\n // --dry-run: imprime plan y sale\n if (cliArgs.dryRun) {\n runDryRun({ config, services, cliArgs, env, baseCwd: cwd, proxyProvider, proxyOpts });\n return;\n }\n\n // Log sink (a disco). Desactivable con --no-log-file.\n let logSink: LogSink | null = null;\n if (cliArgs.logFile) {\n logSink = new LogSink({ projectName: config.name, rootDir: cliArgs.logDir });\n }\n\n // Daemon-already-running guard. Applies to all \"boot the stack\" flows\n // (TUI, --once, devup up -d). If a healthy daemon is up for this project,\n // the ports we'd scan belong to its services — killing them only triggers\n // the daemon's auto-restarter and produces churn. Skip only for the daemon\n // child itself (which IS the running daemon).\n if (process.env.DEVUP_DAEMON_CHILD !== '1') {\n const daemonStatus = isDaemonRunning(config.name);\n if (daemonStatus.pid && !daemonStatus.stale) {\n console.error(`❌ A devup daemon is already running for \"${config.name}\" (pid=${daemonStatus.pid}).`);\n console.error('');\n console.error('Stop it first with `devup down`, or interact via the control plane:');\n console.error(' devup ctl status');\n console.error(' devup ctl logs <svc> --follow');\n console.error(' devup ctl restart <svc>');\n await logSink?.close();\n process.exit(1);\n }\n }\n\n // Pre-boot port conflict resolution. Skip in the daemon child (the parent\n // already cleared conflicts before spawning us). All other flows benefit:\n // TUI, `devup up -d`, `--once`.\n if (process.env.DEVUP_DAEMON_CHILD !== '1') {\n const conflicts = await scanPortConflicts(services);\n if (conflicts.length) {\n const resolved = await resolvePortConflicts(conflicts, {\n autoKill: cliArgs.killPortConflicts,\n out: msg => process.stderr.write(msg + '\\n'),\n prompt: () => askYesNo('Kill these processes and continue? [y/N]: '),\n });\n if (!resolved) {\n await logSink?.close();\n process.exit(1);\n }\n }\n }\n\n // --once: arranca, espera ready, sale 0/1 (sin TUI)\n if (cliArgs.once) {\n const code = await runOnce({\n config, services, cliArgs, platform, env, baseCwd: cwd, logSink,\n });\n await logSink?.close();\n process.exit(code);\n }\n\n // Daemon child: spawned by `devup up -d`. Skip Ink/TUI; run the daemon body\n // which stays alive until SIGTERM. The parent process polls for the PID file.\n if (process.env.DEVUP_DAEMON_CHILD === '1') {\n await daemonBody({ config, services, cliArgs, platform, env, baseCwd: cwd, proxyProvider, proxyOpts });\n return; // daemonBody installs its own signal handlers and only exits via process.exit\n }\n\n // `devup up -d`: spawn the daemon child detached, wait for it to signal ready, exit.\n if (subcmd === 'up') {\n if (!raw.includes('-d') && !raw.includes('--detach')) {\n console.error('usage: devup up -d (use plain `devup` for the TUI)');\n process.exit(1);\n }\n process.exit(await runDetached({\n config, services, cliArgs, platform, env, baseCwd: cwd, proxyProvider, proxyOpts,\n }));\n }\n\n // Render TUI\n const isInteractive = process.stdin.isTTY ?? false;\n const { waitUntilExit } = render(\n React.createElement(App, {\n config, services, cliArgs, platform, env, baseCwd: cwd,\n proxyProvider, proxyOpts, logSink,\n }),\n { exitOnCtrlC: false, patchConsole: isInteractive, interactive: isInteractive },\n );\n\n await waitUntilExit();\n}\n\n/** Single-line y/N prompt. Reads stdin directly rather than going through\n * readline — `readline.createInterface` can no-op silently when the input\n * stream has been touched elsewhere (e.g. terminal multiplexers, IDE\n * integrated terminals, complex shells), which left users with the\n * question printed but the process moving on without waiting.\n *\n * TTY is detected via any of stdin / stderr / stdout being a TTY; some\n * environments misreport one but not the others. Resolves false on EOF\n * or non-TTY so a caller can fall back to \"non-interactive\" handling. */\nfunction askYesNo(question: string): Promise<boolean> {\n return new Promise(resolve => {\n const isTTY = Boolean(process.stdin.isTTY || process.stderr.isTTY || process.stdout.isTTY);\n if (!isTTY) { resolve(false); return; }\n\n process.stderr.write(question);\n process.stdin.resume();\n process.stdin.setEncoding('utf8');\n\n const cleanup = () => {\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n process.stdin.pause();\n };\n const onData = (data: string | Buffer) => {\n cleanup();\n resolve(/^y(es)?$/i.test(String(data).trim()));\n };\n const onEnd = () => { cleanup(); resolve(false); };\n\n process.stdin.once('data', onData);\n process.stdin.once('end', onEnd);\n });\n}\n\n/** Only run main() when this script is invoked directly (i.e. as the `devup`\n * binary). When the bundle is *imported* — which happens whenever a user's\n * `devup.config.ts` does `import { defineConfig } from '@gachlab/devup'` —\n * we just want our exports (`defineConfig`, types) to be available, NOT to\n * start a second concurrent main() that races for the same ports and\n * duplicates every line of output.\n *\n * Compare `import.meta.url` (this module's file URL) against the realpath\n * of `process.argv[1]` (the entry script). When invoked as `devup`, npm\n * installs `bin/devup` as a symlink to `dist/index.js`, so the realpath\n * resolves to our module and the comparison matches. When imported from a\n * config file, `process.argv[1]` points at the outer entry — which lives\n * at a different node_modules path even when the same version — and the\n * comparison fails, so `main()` does not fire. */\nfunction isInvokedDirectly(): boolean {\n const argvPath = process.argv[1];\n if (!argvPath) return false;\n const moduleFile = fileURLToPath(import.meta.url);\n try {\n return realpathSync(argvPath) === moduleFile;\n } catch {\n return argvPath === moduleFile;\n }\n}\n\nif (isInvokedDirectly()) {\n main().catch(e => {\n console.error(e);\n process.exit(1);\n });\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { resolve, join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { DevStackConfig } from './types.js';\n\nconst CONFIG_NAMES = [\n 'devup.config.ts',\n 'devup.config.js',\n 'devup.config.json',\n];\n\nexport function findConfigFile(cwd: string, explicit?: string): string {\n if (explicit) {\n const full = resolve(cwd, explicit);\n if (!existsSync(full)) throw new Error(`Config not found: ${full}`);\n return full;\n }\n for (const name of CONFIG_NAMES) {\n const full = join(cwd, name);\n if (existsSync(full)) return full;\n }\n throw new Error(\n `No config found. Create one of: ${CONFIG_NAMES.join(', ')}\\n` +\n `Or use --config <path>`,\n );\n}\n\nexport async function loadConfig(configPath: string): Promise<DevStackConfig> {\n if (configPath.endsWith('.json')) {\n const raw = await readFile(configPath, 'utf8');\n return JSON.parse(raw) as DevStackConfig;\n }\n\n // .ts and .js — dynamic import (tsx loader handles .ts at runtime)\n const url = pathToFileURL(configPath).href;\n const mod = await import(url);\n const config = mod.default ?? mod;\n\n if (!config || typeof config !== 'object' || !Array.isArray(config.services)) {\n throw new Error(`Invalid config: must export a DevStackConfig (use defineConfig() from @gachlab/devup)`);\n }\n\n return config as DevStackConfig;\n}\n","import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { DevStackConfig } from './types.js';\nimport { LAZY_PORT_OFFSET } from '../lazy/classifier.js';\n\nexport interface ValidationError {\n field: string;\n message: string;\n}\n\nexport interface ValidationWarning {\n field: string;\n message: string;\n}\n\n/** Collects non-blocking warnings: things that look suspicious but don't justify\n * refusing to start the stack. Run alongside `validateConfig` from the CLI entry\n * point; print them and continue. */\nexport function collectWarnings(config: DevStackConfig): ValidationWarning[] {\n const warnings: ValidationWarning[] = [];\n if (!config.services?.length) return warnings;\n\n for (const svc of config.services) {\n // extraEnv.PORT vs svc.port: catches the common \"I set PORT in extraEnv to\n // something other than port and now nothing connects\" footgun.\n const ep = svc.extraEnv?.['PORT'];\n if (ep !== undefined) {\n const expected = String(svc.port);\n if (ep !== expected) {\n warnings.push({\n field: `services[${svc.name}].extraEnv.PORT`,\n message: `extraEnv.PORT=\"${ep}\" does not match port=${svc.port}. devup will health-check :${svc.port} but the service will probably bind to :${ep}.`,\n });\n }\n }\n }\n return warnings;\n}\n\nexport function formatValidationWarnings(warnings: ValidationWarning[]): string {\n return warnings.map(w => ` ⚠ ${w.field}: ${w.message}`).join('\\n');\n}\n\nexport function validateConfig(config: DevStackConfig, cwd: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (!config.name?.trim()) {\n errors.push({ field: 'name', message: 'Project name is required' });\n }\n\n if (!config.services?.length) {\n errors.push({ field: 'services', message: 'At least one service is required' });\n return errors;\n }\n\n // Unique names\n const names = new Set<string>();\n for (const svc of config.services) {\n if (names.has(svc.name)) {\n errors.push({ field: `services[${svc.name}].name`, message: `Duplicate service name: ${svc.name}` });\n }\n names.add(svc.name);\n }\n\n // Unique ports\n const ports = new Map<number, string>();\n for (const svc of config.services) {\n const existing = ports.get(svc.port);\n if (existing) {\n errors.push({ field: `services[${svc.name}].port`, message: `Port ${svc.port} already used by ${existing}` });\n }\n ports.set(svc.port, svc.name);\n }\n\n // Valid fields per service\n for (const svc of config.services) {\n if (!svc.name?.trim()) errors.push({ field: 'services[].name', message: 'Service name is required' });\n if (!svc.cwd?.trim()) errors.push({ field: `services[${svc.name}].cwd`, message: 'cwd is required' });\n if (!svc.cmd?.trim()) errors.push({ field: `services[${svc.name}].cmd`, message: 'cmd is required' });\n if (!svc.type || !['api', 'web'].includes(svc.type)) {\n errors.push({ field: `services[${svc.name}].type`, message: `Invalid type: ${svc.type} (must be \"api\" or \"web\")` });\n }\n if (typeof svc.port !== 'number' || svc.port <= 0) {\n errors.push({ field: `services[${svc.name}].port`, message: `Invalid port: ${svc.port}` });\n }\n if (typeof svc.phase !== 'number' || svc.phase < 0) {\n errors.push({ field: `services[${svc.name}].phase`, message: `Invalid phase: ${svc.phase}` });\n }\n\n // cwd exists\n if (svc.cwd && !existsSync(resolve(cwd, svc.cwd))) {\n errors.push({ field: `services[${svc.name}].cwd`, message: `Directory not found: ${svc.cwd}` });\n }\n\n // errorPattern (same regex grammar as readyPattern)\n if (svc.errorPattern !== undefined) {\n if (typeof svc.errorPattern !== 'string' || !svc.errorPattern.length) {\n errors.push({ field: `services[${svc.name}].errorPattern`, message: `errorPattern must be a non-empty string` });\n } else {\n const slashed = /^\\/(.+)\\/([gimsuy]*)$/.exec(svc.errorPattern);\n try {\n if (slashed) new RegExp(slashed[1]!, slashed[2] || 'i');\n else new RegExp(svc.errorPattern, 'i');\n } catch (e: any) {\n errors.push({ field: `services[${svc.name}].errorPattern`, message: `Invalid regex: ${e.message}` });\n }\n }\n }\n\n // readyPattern\n if (svc.readyPattern !== undefined) {\n if (typeof svc.readyPattern !== 'string' || !svc.readyPattern.length) {\n errors.push({ field: `services[${svc.name}].readyPattern`, message: `readyPattern must be a non-empty string` });\n } else {\n const slashed = /^\\/(.+)\\/([gimsuy]*)$/.exec(svc.readyPattern);\n try {\n if (slashed) new RegExp(slashed[1]!, slashed[2] || 'i');\n else new RegExp(svc.readyPattern, 'i');\n } catch (e: any) {\n errors.push({ field: `services[${svc.name}].readyPattern`, message: `Invalid regex: ${e.message}` });\n }\n }\n }\n\n // preBuild / watchBuild\n if (svc.preBuild !== undefined && (typeof svc.preBuild !== 'string' || !svc.preBuild.trim())) {\n errors.push({ field: `services[${svc.name}].preBuild`, message: `preBuild must be a non-empty string` });\n }\n if (svc.watchBuild !== undefined && (typeof svc.watchBuild !== 'string' || !svc.watchBuild.trim())) {\n errors.push({ field: `services[${svc.name}].watchBuild`, message: `watchBuild must be a non-empty string` });\n }\n\n // healthCheck\n if (svc.healthCheck) {\n const hc = svc.healthCheck;\n if (hc.type !== 'tcp' && hc.type !== 'http') {\n errors.push({ field: `services[${svc.name}].healthCheck.type`, message: `Invalid healthCheck.type: ${hc.type} (must be \"tcp\" or \"http\")` });\n }\n if (hc.startPeriod !== undefined && (typeof hc.startPeriod !== 'number' || hc.startPeriod < 0)) {\n errors.push({ field: `services[${svc.name}].healthCheck.startPeriod`, message: `startPeriod must be a non-negative number (seconds), got ${hc.startPeriod}` });\n }\n if (hc.type === 'http' && hc.path && !hc.path.startsWith('/')) {\n errors.push({ field: `services[${svc.name}].healthCheck.path`, message: `healthCheck.path must start with \"/\": got \"${hc.path}\"` });\n }\n }\n }\n\n // Lazy refs\n if (config.lazy?.alwaysOn) {\n for (const ref of config.lazy.alwaysOn) {\n if (!names.has(ref)) {\n errors.push({ field: `lazy.alwaysOn`, message: `Unknown service: ${ref}` });\n }\n }\n }\n\n // Lazy port collisions: in lazy mode each non-always-on service also listens on port + LAZY_PORT_OFFSET\n if (config.lazy) {\n const alwaysOn = new Set(config.lazy.alwaysOn ?? []);\n const portToSvc = new Map<number, string>();\n for (const svc of config.services) portToSvc.set(svc.port, svc.name);\n for (const svc of config.services) {\n if (alwaysOn.has(svc.name)) continue;\n const realPort = svc.port + LAZY_PORT_OFFSET;\n const conflict = portToSvc.get(realPort);\n if (conflict && conflict !== svc.name) {\n errors.push({\n field: `services[${svc.name}].port`,\n message: `Lazy real port ${realPort} (= ${svc.port}+${LAZY_PORT_OFFSET}) collides with service ${conflict}`,\n });\n }\n }\n }\n\n // External services\n if (config.external) {\n const extNames = new Set<string>();\n for (const ext of config.external) {\n if (!ext.name?.trim()) {\n errors.push({ field: 'external[].name', message: 'External service name is required' });\n continue;\n }\n if (extNames.has(ext.name)) {\n errors.push({ field: `external[${ext.name}].name`, message: `Duplicate external name: ${ext.name}` });\n }\n extNames.add(ext.name);\n if (!ext.cmd?.trim()) {\n errors.push({ field: `external[${ext.name}].cmd`, message: 'cmd is required' });\n }\n if (ext.healthCheck) {\n const hc = ext.healthCheck;\n if (hc.type !== 'tcp' && hc.type !== 'http') {\n errors.push({ field: `external[${ext.name}].healthCheck.type`, message: `Invalid healthCheck.type: ${hc.type}` });\n }\n if ((hc.type === 'tcp' || hc.type === 'http') && (typeof ext.port !== 'number' || ext.port <= 0)) {\n errors.push({ field: `external[${ext.name}].port`, message: `port is required when healthCheck is set (got ${ext.port})` });\n }\n if (hc.type === 'http' && hc.path && !hc.path.startsWith('/')) {\n errors.push({ field: `external[${ext.name}].healthCheck.path`, message: `must start with \"/\"` });\n }\n }\n }\n }\n\n // Proxy route refs\n if (config.proxy?.routes) {\n for (const ref of Object.keys(config.proxy.routes)) {\n if (!names.has(ref)) {\n errors.push({ field: `proxy.routes`, message: `Unknown service: ${ref}` });\n }\n }\n }\n\n // Profiles\n if (config.profiles) {\n for (const [profile, svcNames] of Object.entries(config.profiles)) {\n if (!Array.isArray(svcNames) || !svcNames.length) {\n errors.push({ field: `profiles.${profile}`, message: `Profile \"${profile}\" must be a non-empty array of service names` });\n continue;\n }\n for (const ref of svcNames) {\n if (!names.has(ref)) {\n errors.push({ field: `profiles.${profile}`, message: `Unknown service: ${ref}` });\n }\n }\n }\n }\n\n return errors;\n}\n\nexport function formatValidationErrors(errors: ValidationError[]): string {\n return errors.map(e => ` ✗ ${e.field}: ${e.message}`).join('\\n');\n}\n","import type { ServiceConfig, LazyConfig } from '../config/types.js';\n\nexport const LAZY_PORT_OFFSET = 10000;\nexport const DEFAULT_LAZY_TIMEOUT = 10;\n\nexport interface ClassifiedServices {\n alwaysOn: ServiceConfig[];\n lazy: ServiceConfig[];\n}\n\nexport function classifyServices(services: ServiceConfig[], config?: LazyConfig): ClassifiedServices {\n const alwaysOnSet = new Set(config?.alwaysOn ?? []);\n const alwaysOn: ServiceConfig[] = [];\n const lazy: ServiceConfig[] = [];\n\n for (const svc of services) {\n if (alwaysOnSet.has(svc.name)) alwaysOn.push(svc);\n else lazy.push(svc);\n }\n return { alwaysOn, lazy };\n}\n\nexport function getLazyRealPort(originalPort: number): number {\n return originalPort + LAZY_PORT_OFFSET;\n}\n\nexport function rewriteServicePort(svc: ServiceConfig): ServiceConfig & { realPort: number; originalPort: number } {\n const realPort = getLazyRealPort(svc.port);\n const args = svc.args.map(a => a === String(svc.port) ? String(realPort) : a);\n const extraEnv = { ...svc.extraEnv, PORT_OVERRIDE: String(realPort) };\n return { ...svc, port: realPort, args, extraEnv, realPort, originalPort: svc.port };\n}\n","import type { DevStackConfig, ServiceConfig } from './types.js';\n\nexport interface CliArgs {\n configPath?: string;\n only?: string;\n skip: string[];\n services?: string[];\n profile?: string;\n lazy: boolean;\n lazyTimeout: number;\n proxy: boolean;\n proxyHost?: string;\n proxyConf?: string;\n proxyTls: boolean;\n proxyEntrypoint: string;\n dryRun: boolean;\n once: boolean;\n onceTimeout: number;\n logFile: boolean;\n logDir?: string;\n watchConfig: boolean;\n killPortConflicts: boolean;\n}\n\nconst DEFAULT_LAZY_TIMEOUT = 10;\nconst DEFAULT_ONCE_TIMEOUT = 90;\n\nexport const USAGE = `devup — terminal UI dev stack runner\n\nUsage: devup [options]\n\nService selection:\n --only apis | webs Start only APIs or only webs\n --services a,b,c Start only the named services\n --profile <name> Start the services in a named profile (see ROADMAP)\n --skip a,b,c Start everything except these\n --config <path> Use a custom config file\n\nLazy mode:\n --lazy Enable lazy mode (default)\n --no-lazy Start every service immediately\n --timeout <minutes> Idle timeout for lazy services. Default: 10\n\nReverse proxy:\n --proxy Enable proxy config generation\n --proxy-host <host> Override the target host (Docker/local)\n --proxy-conf <path> Override the generated config file path\n --proxy-tls Enable TLS in the generated config (default)\n --no-proxy-tls Disable TLS\n --proxy-entrypoint <n> Override entrypoint name (Traefik only)\n\nCI / scripting:\n --dry-run Print the resolved boot plan and exit\n --once Boot, wait for readiness, exit 0/1 (no TUI)\n --once-timeout <s> Max seconds to wait in --once mode. Default: 90\n\nLog files:\n --no-log-file Disable persistent log files\n --log-dir <path> Override log root (default: ~/.devup/logs)\n\nHot reload:\n --watch-config Watch devup.config.* and apply add/remove/restart\n service changes without exiting the TUI\n\nPort conflicts:\n --kill-port-conflicts Kill any processes already holding a configured\n port before boot. Interactive prompt without it;\n required for non-TTY (daemon, --once, CI)\n\nOther:\n -h, --help Show this help and exit\n -v, --version Show version and exit\n\nSee https://github.com/gachlab/devup for the full documentation.`;\n\nexport function parseCliArgs(argv: string[]): CliArgs {\n const args: CliArgs = {\n skip: [],\n lazy: true,\n lazyTimeout: DEFAULT_LAZY_TIMEOUT,\n proxy: false,\n proxyTls: true,\n proxyEntrypoint: 'websecure',\n dryRun: false,\n once: false,\n onceTimeout: DEFAULT_ONCE_TIMEOUT,\n logFile: true,\n watchConfig: false,\n killPortConflicts: false,\n };\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n const next = argv[i + 1];\n\n switch (arg) {\n case '--config': args.configPath = next; i++; break;\n case '--only': args.only = next; i++; break;\n case '--skip': args.skip = next?.split(',') ?? []; i++; break;\n case '--services': args.services = next?.split(','); i++; break;\n case '--profile': args.profile = next; i++; break;\n case '--lazy': args.lazy = true; break;\n case '--no-lazy': args.lazy = false; break;\n case '--timeout': args.lazyTimeout = parseInt(next ?? '', 10) || DEFAULT_LAZY_TIMEOUT; i++; break;\n case '--proxy': args.proxy = true; break;\n case '--proxy-host': args.proxyHost = next; i++; break;\n case '--proxy-conf': args.proxyConf = next; i++; break;\n case '--proxy-tls': args.proxyTls = true; break;\n case '--no-proxy-tls': args.proxyTls = false; break;\n case '--proxy-entrypoint': args.proxyEntrypoint = next ?? 'websecure'; i++; break;\n case '--dry-run': args.dryRun = true; break;\n case '--once': args.once = true; break;\n case '--once-timeout': args.onceTimeout = parseInt(next ?? '', 10) || DEFAULT_ONCE_TIMEOUT; i++; break;\n case '--no-log-file': args.logFile = false; break;\n case '--log-dir': args.logDir = next; i++; break;\n case '--watch-config': args.watchConfig = true; break;\n case '--kill-port-conflicts': args.killPortConflicts = true; break;\n }\n }\n\n return args;\n}\n\nexport function filterServices(\n services: ServiceConfig[],\n args: CliArgs,\n config?: Pick<DevStackConfig, 'profiles'>,\n): ServiceConfig[] {\n let result = services;\n\n if (args.profile) {\n const profileNames = config?.profiles?.[args.profile];\n if (!profileNames) {\n const available = Object.keys(config?.profiles ?? {});\n const hint = available.length ? `Available: ${available.join(', ')}` : 'No profiles defined in config.';\n throw new Error(`Unknown profile: \"${args.profile}\". ${hint}`);\n }\n const set = new Set(profileNames);\n result = result.filter(s => set.has(s.name));\n } else if (args.services) {\n const explicit = new Set(args.services);\n result = result.filter(s => explicit.has(s.name));\n } else if (args.only) {\n switch (args.only) {\n case 'apis': result = result.filter(s => s.type === 'api'); break;\n case 'webs': result = result.filter(s => s.type === 'web'); break;\n default: result = result.filter(s => s.name.startsWith(args.only!)); break;\n }\n }\n\n if (args.skip.length) {\n const skipSet = new Set(args.skip);\n result = result.filter(s => !skipSet.has(s.name));\n }\n\n return result;\n}\n","import { spawn } from 'node:child_process';\nimport { createReadStream, watchFile, unwatchFile, existsSync, statSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { homedir } from 'node:os';\nimport { createInterface } from 'node:readline';\nimport { checkHealth } from '../process/health.js';\nimport { needsInstall, writeInstallStamp } from '../utils.js';\nimport { sendRpc, openStream, resolveSocket, assertSocketExists } from '../control-plane/client.js';\nimport { stopDaemon } from './daemon.js';\nimport type { DevStackConfig } from '../config/types.js';\n\nconst KNOWN = new Set(['logs', 'install', 'status', 'help', 'ctl', 'up', 'down']);\n\n/** Returns the subcommand name if the first arg is one we recognise, else null. */\nexport function detectSubcommand(argv: string[]): string | null {\n const first = argv[0];\n return first && KNOWN.has(first) ? first : null;\n}\n\ninterface SubOpts {\n config: DevStackConfig;\n baseCwd: string;\n env: Record<string, string>;\n logDir?: string;\n out?: (line: string) => void;\n}\n\nfunction logRoot(config: DevStackConfig, override?: string): string {\n const root = override ?? join(homedir(), '.devup', 'logs');\n return join(root, sanitize(config.name));\n}\n\nfunction sanitize(name: string): string {\n return name.replace(/[^a-zA-Z0-9._-]+/g, '_').replace(/^_+|_+$/g, '') || 'devup';\n}\n\n// ── devup logs <svc> [--follow] ──\n\nexport async function runLogs(argv: string[], opts: SubOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => console.log(l));\n const follow = argv.includes('--follow') || argv.includes('-f');\n const svcArg = argv.find(a => !a.startsWith('-'));\n if (!svcArg) {\n out('usage: devup logs <service> [--follow]');\n return 1;\n }\n const knownSvcs = opts.config.services.map(s => s.name);\n if (!knownSvcs.includes(svcArg)) {\n out(`Unknown service \"${svcArg}\". Known: ${knownSvcs.join(', ')}`);\n return 1;\n }\n const file = join(logRoot(opts.config, opts.logDir), `${sanitize(svcArg)}.log`);\n if (!existsSync(file)) {\n out(`No log file yet for \"${svcArg}\" (${file})`);\n return follow ? await followFile(file, out) : 1;\n }\n await streamFile(file, out);\n if (!follow) return 0;\n return await followFile(file, out, statSync(file).size);\n}\n\nasync function streamFile(file: string, out: (l: string) => void): Promise<void> {\n return new Promise((resolve, reject) => {\n const rl = createInterface({ input: createReadStream(file, { encoding: 'utf8' }) });\n rl.on('line', l => out(l));\n rl.on('close', () => resolve());\n rl.on('error', reject);\n });\n}\n\nasync function followFile(file: string, out: (l: string) => void, startAt = 0): Promise<number> {\n let pos = startAt;\n // Wait for the file to appear if it doesn't yet\n while (!existsSync(file)) await new Promise(r => setTimeout(r, 500));\n return new Promise(resolve => {\n const tick = async () => {\n const size = statSync(file).size;\n if (size > pos) {\n await new Promise<void>(res => {\n const rl = createInterface({ input: createReadStream(file, { encoding: 'utf8', start: pos, end: size - 1 }) });\n rl.on('line', l => out(l));\n rl.on('close', () => { pos = size; res(); });\n });\n } else if (size < pos) {\n // File was truncated / rotated — restart from beginning\n pos = 0;\n }\n };\n watchFile(file, { interval: 500 }, () => { void tick(); });\n process.once('SIGINT', () => { unwatchFile(file); resolve(0); });\n });\n}\n\n// ── devup install ──\n\nexport async function runInstall(opts: SubOpts & { concurrency?: number }): Promise<number> {\n const out = opts.out ?? ((l: string) => console.log(l));\n const concurrency = opts.concurrency ?? 4;\n const items = opts.config.services.map(s => ({ name: s.name, cwd: join(opts.baseCwd, s.cwd) }));\n const queue = [...items];\n const failed: string[] = [];\n let inFlight = 0;\n\n await new Promise<void>(resolve => {\n const pump = () => {\n while (inFlight < concurrency && queue.length) {\n const item = queue.shift()!;\n inFlight++;\n installOne(item.cwd, opts.env).then(ok => {\n inFlight--;\n if (ok) out(`✓ ${item.name}`);\n else { failed.push(item.name); out(`✗ ${item.name}`); }\n if (queue.length === 0 && inFlight === 0) resolve();\n else pump();\n });\n }\n };\n pump();\n });\n\n if (failed.length) {\n out(`\\nfailed: ${failed.join(', ')}`);\n return 1;\n }\n out(`\\n${items.length} services up to date`);\n return 0;\n}\n\nfunction installOne(cwd: string, env: Record<string, string>): Promise<boolean> {\n if (!existsSync(cwd)) return Promise.resolve(false);\n if (!needsInstall(cwd)) return Promise.resolve(true);\n return new Promise(resolve => {\n const command = process.platform === 'win32' ? 'npm.cmd' : 'npm';\n const proc = spawn(command, ['install'], { cwd, env, stdio: ['ignore', 'ignore', 'pipe'] });\n proc.on('close', code => {\n if (code === 0) { writeInstallStamp(cwd); resolve(true); } else resolve(false);\n });\n proc.on('error', () => resolve(false));\n });\n}\n\n// ── devup status ──\n\nexport async function runStatus(opts: SubOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => console.log(l));\n out(`${opts.config.icon ?? '📦'} ${opts.config.name} — ${opts.config.services.length} services`);\n out('');\n\n const maxLen = Math.max(...opts.config.services.map(s => s.name.length), 12);\n out(`${'Service'.padEnd(maxLen)} ${'Port'.padStart(5)} ${'Type'.padEnd(4)} Health`);\n out('-'.repeat(maxLen + 24));\n\n for (const svc of opts.config.services) {\n const up = await checkHealth(svc.port, svc.healthCheck);\n const health = up ? '✓ up' : '✗ down';\n out(`${svc.name.padEnd(maxLen)} ${String(svc.port).padStart(5)} ${svc.type.padEnd(4)} ${health}`);\n }\n return 0;\n}\n\n// ── devup ctl <method> [args] ──\n\ninterface CtlOpts {\n config: DevStackConfig;\n out?: (line: string) => void;\n socketPath?: string;\n}\n\ntype ServiceRow = {\n name: string; status: string; health: string;\n port: number; type: string; pid: number | null;\n errors: number; restarts: number;\n};\n\nfunction fmtStatus(rows: ServiceRow[], out: (l: string) => void): void {\n const maxLen = Math.max(...rows.map(r => r.name.length), 8);\n for (const r of rows) {\n const pid = r.pid != null ? `pid=${r.pid}` : ' ';\n const name = r.name.padEnd(maxLen);\n const port = `:${r.port}`.padStart(6);\n const status = r.status.padEnd(8);\n const health = r.health.padEnd(4);\n out(`${name} ${port} ${status} ${health} ${pid} errors=${r.errors} restarts=${r.restarts}`);\n }\n}\n\nexport async function runCtl(argv: string[], opts: CtlOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => process.stdout.write(l + '\\n'));\n const method = argv[0];\n const follow = argv.includes('--follow') || argv.includes('-f');\n const socketPath = resolveSocket(opts.config.name, opts.socketPath);\n\n if (!method || method === 'help') {\n out('Usage: devup ctl <method> [args] [--follow]');\n out(' ping Check if devup is running');\n out(' status [--follow] Service snapshot, or live updates');\n out(' logs <svc> [--follow] Tail logs (last 100), or follow live stream');\n out(' restart <svc> Restart a service');\n out(' stop <svc> Stop a service');\n return 0;\n }\n\n try {\n assertSocketExists(socketPath, opts.config.name);\n } catch (e: any) {\n out(e.message);\n return 1;\n }\n\n try {\n if (method === 'ping') {\n const res = await sendRpc(socketPath, 'ping') as { ok: boolean; ts: number };\n out(`pong ts=${res.ts}`);\n return 0;\n }\n\n if (method === 'status' && !follow) {\n const res = await sendRpc(socketPath, 'status') as { services: ServiceRow[] };\n if (!res.services.length) { out('(no services)'); return 0; }\n fmtStatus(res.services, out);\n return 0;\n }\n\n if (method === 'status' && follow) {\n return await new Promise<number>(resolve => {\n const abort = openStream(socketPath, 'status.follow', {}, frame => {\n const rows = frame.data as ServiceRow[];\n const ts = new Date().toISOString().slice(11, 23);\n for (const r of rows) {\n out(`[${ts}] ${r.name.padEnd(24)} ${r.status}/${r.health}`);\n }\n }, err => { out(`error: ${err.message}`); resolve(1); });\n process.once('SIGINT', () => { abort(); resolve(0); });\n });\n }\n\n if (method === 'logs') {\n const svc = argv.find((a, i) => i > 0 && !a.startsWith('-'));\n if (!svc) { out('usage: devup ctl logs <service> [--follow]'); return 1; }\n\n if (!follow) {\n const res = await sendRpc(socketPath, 'logs.tail', { svc, lines: 100 }) as { lines: string[] };\n for (const l of res.lines) out(l);\n return 0;\n }\n\n return await new Promise<number>(resolve => {\n const abort = openStream(socketPath, 'logs.follow', { svc, tail: 100 }, frame => {\n out(frame.data as string);\n }, err => { out(`error: ${err.message}`); resolve(1); });\n process.once('SIGINT', () => { abort(); resolve(0); });\n });\n }\n\n if (method === 'restart') {\n const svc = argv[1];\n if (!svc) { out('usage: devup ctl restart <service>'); return 1; }\n await sendRpc(socketPath, 'restart', { svc });\n out(`✓ restart sent to ${svc}`);\n return 0;\n }\n\n if (method === 'stop') {\n const svc = argv[1];\n if (!svc) { out('usage: devup ctl stop <service>'); return 1; }\n await sendRpc(socketPath, 'stop', { svc });\n out(`✓ stop sent to ${svc}`);\n return 0;\n }\n\n out(`unknown ctl method: ${method}. Run \\`devup ctl help\\` for usage.`);\n return 1;\n } catch (e: any) {\n out(`error: ${e.message}`);\n return 1;\n }\n}\n\n// ── devup down ──\n\nexport async function runDown(opts: SubOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => process.stdout.write(l + '\\n'));\n return stopDaemon(opts.config.name, { out });\n}\n\n// ── devup help <subcommand> ──\n\nexport function runHelp(argv: string[], opts: { out?: (l: string) => void } = {}): number {\n const out = opts.out ?? ((l: string) => console.log(l));\n const sub = argv[0];\n if (sub === 'logs') {\n out('Usage: devup logs <service> [--follow|-f]');\n out(' Print the persisted log file for a service (works without devup running).');\n out(' --follow tails new lines as they are appended.');\n return 0;\n }\n if (sub === 'install') {\n out('Usage: devup install');\n out(' Run `npm install` across every service.cwd in parallel (max 4 at a time).');\n out(' Skips services whose .install-stamp matches package.json hash.');\n return 0;\n }\n if (sub === 'status') {\n out('Usage: devup status');\n out(' For each service, probes its health-check endpoint and prints up/down.');\n return 0;\n }\n if (sub === 'ctl') {\n out('Usage: devup ctl <method> [args] [--follow]');\n out(' Send commands to a running devup process via the control plane socket.');\n out('');\n out(' ping Check if devup is running');\n out(' status [--follow] Service snapshot, or live state-change stream');\n out(' logs <svc> [--follow] Tail last 100 lines, or follow the live stream');\n out(' restart <svc> Restart the named service');\n out(' stop <svc> Stop the named service');\n out('');\n out(' devup must be running in the same project directory.');\n return 0;\n }\n if (sub === 'up') {\n out('Usage: devup up -d');\n out(' Boot the stack in detached/daemon mode (like `docker compose up -d`).');\n out(' Returns immediately once the stack is healthy; services keep running.');\n out(' Use `devup ctl status`, `devup ctl logs`, or `devup down` to interact.');\n out(' Not supported on Windows yet — use `devup` (TUI) instead.');\n return 0;\n }\n if (sub === 'down') {\n out('Usage: devup down');\n out(' Stop the daemon for the current project. SIGTERM with 10s grace,');\n out(' then SIGKILL. Removes the PID file and the control-plane socket.');\n return 0;\n }\n out('Subcommands:');\n out(' devup logs <service> [--follow] Read the persisted log file');\n out(' devup install Concurrent npm install across services');\n out(' devup status Health check every service in config');\n out(' devup up -d Boot the stack in detached/daemon mode');\n out(' devup down Stop the running daemon');\n out(' devup ctl <method> [args] Control a running devup (restart/stop/logs/...)');\n out(' devup help [<subcommand>] Show detailed help for a subcommand');\n out('');\n out('No subcommand → launch the interactive TUI.');\n return 0;\n}\n\nvoid readFile;\nvoid dirname;\nvoid fileURLToPath;\n","import net from 'node:net';\nimport http from 'node:http';\nimport type { HealthStatus } from './types.js';\nimport type { HealthCheckConfig } from '../config/types.js';\n\n/** \"Is something accepting connections at port?\" — connect-based test.\n * Use this for health checks and waitForPort, where \"occupied\" means\n * \"the service is up\". Do NOT use this to decide whether to spawn — use\n * `isPortBindable` instead (a bound but pre-accept server would slip\n * through this check). */\nexport function checkPort(port: number, host = '127.0.0.1', timeoutMs = 2000): Promise<boolean> {\n return new Promise(resolve => {\n const socket = new net.Socket();\n socket.setTimeout(timeoutMs);\n socket.once('connect', () => { socket.destroy(); resolve(true); });\n socket.once('error', () => { socket.destroy(); resolve(false); });\n socket.once('timeout', () => { socket.destroy(); resolve(false); });\n socket.connect(port, host);\n });\n}\n\n/** \"Can I bind to this port right now?\" — bind-based test. Returns true\n * if a server could listen on the port on every wildcard address. Used as\n * the pre-flight before spawning a service: catches every case that would\n * cause the spawned process to die with EADDRINUSE, including bound-but-\n * not-yet-accepting states that `checkPort` misses.\n *\n * Implementation detail: tests both IPv4 (`0.0.0.0`) and IPv6 (`::`)\n * wildcards. On Linux these usually share an address space (IPV6_V6ONLY=0),\n * so a single test suffices; on Windows the defaults isolate the stacks,\n * so a one-stack test can miss a conflicting bind on the other. We require\n * both stacks to be free to call the port bindable. */\nexport async function isPortBindable(port: number): Promise<boolean> {\n // Sequential, not parallel — on Linux the IPv4/IPv6 wildcards share an\n // address space, so two simultaneous test-binds race each other and the\n // second loses with EADDRINUSE even when the port is genuinely free.\n for (const host of ['0.0.0.0', '::']) {\n if (!(await tryBind(port, host))) return false;\n }\n return true;\n}\n\nfunction tryBind(port: number, host: string): Promise<boolean> {\n return new Promise(resolve => {\n const server = net.createServer();\n server.once('error', (err: NodeJS.ErrnoException) => {\n // EADDRINUSE / EACCES → conflict. Other errors (e.g. EAFNOSUPPORT on an\n // IPv6-disabled box) we treat as \"stack unavailable, not a conflict\".\n if (err.code === 'EADDRINUSE' || err.code === 'EACCES') resolve(false);\n else resolve(true);\n });\n server.once('listening', () => server.close(() => resolve(true)));\n server.listen(port, host);\n });\n}\n\nexport function checkHttp(\n port: number,\n opts: { path?: string; expect?: number | number[]; host?: string; timeoutMs?: number } = {},\n): Promise<boolean> {\n const path = opts.path ?? '/';\n const host = opts.host ?? '127.0.0.1';\n const timeoutMs = opts.timeoutMs ?? 2000;\n const accept = (code: number) => {\n if (opts.expect === undefined) return code >= 200 && code < 300;\n if (Array.isArray(opts.expect)) return opts.expect.includes(code);\n return code === opts.expect;\n };\n return new Promise(resolve => {\n const req = http.get({ host, port, path, timeout: timeoutMs }, res => {\n const ok = typeof res.statusCode === 'number' && accept(res.statusCode);\n res.resume();\n resolve(ok);\n });\n req.on('error', () => resolve(false));\n req.on('timeout', () => { req.destroy(); resolve(false); });\n });\n}\n\n/** Run the right check for a service, given its optional healthCheck config. */\nexport function checkHealth(port: number, hc?: HealthCheckConfig): Promise<boolean> {\n if (hc?.type === 'http') {\n return checkHttp(port, {\n path: hc.path, expect: hc.expect, host: hc.host, timeoutMs: hc.timeoutMs,\n });\n }\n return checkPort(port, '127.0.0.1', hc?.timeoutMs);\n}\n\nexport function waitForPort(port: number, opts: { timeout?: number; interval?: number } = {}): Promise<boolean> {\n const { timeout = 45000, interval = 1000 } = opts;\n return new Promise(resolve => {\n const start = Date.now();\n const check = () => {\n checkPort(port).then(ok => {\n if (ok) return resolve(true);\n if (Date.now() - start > timeout) return resolve(false);\n setTimeout(check, interval);\n });\n };\n check();\n });\n}\n\nexport function deriveHealth(isUp: boolean, currentStatus: string): HealthStatus {\n if (currentStatus === 'idle') return 'idle';\n if (isUp) return 'up';\n return currentStatus === 'starting' ? 'wait' : 'down';\n}\n","import { existsSync, readFileSync } from 'node:fs';\n\n/** Reads a `.env`-style file and overlays it on top of `baseEnv`.\n * Lines starting with `#` are comments. Quoted values get the quotes stripped.\n * Existing keys in `baseEnv` win — file values only fill the gaps. */\nexport function parseEnvFile(filePath: string, baseEnv: Record<string, string> = {}): Record<string, string> {\n const env = { ...baseEnv };\n if (!existsSync(filePath)) return env;\n\n for (const line of readFileSync(filePath, 'utf8').split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIdx = trimmed.indexOf('=');\n if (eqIdx === -1) continue;\n const key = trimmed.slice(0, eqIdx).trim();\n let val = trimmed.slice(eqIdx + 1).trim();\n if ((val.startsWith('\"') && val.endsWith('\"')) || (val.startsWith(\"'\") && val.endsWith(\"'\"))) {\n val = val.slice(1, -1);\n }\n if (!env[key]) env[key] = val;\n }\n return env;\n}\n","/** Formats a duration (in ms) as a short human string: 45s, 2m5s, 1h2m, 2d3h. */\nexport function fmtUptime(ms: number): string {\n if (!ms || ms < 0) return '-';\n const s = Math.floor(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m${s % 60}s`;\n const h = Math.floor(m / 60);\n if (h < 24) return `${h}h${m % 60}m`;\n const d = Math.floor(h / 24);\n return `${d}d${h % 24}h`;\n}\n","export interface SearchMatcher {\n test: (line: string) => boolean;\n /** Set when the input was a vim-style /pattern/flags — used to drive highlighting. */\n regex?: RegExp;\n /** True when input started with `/` but produced an invalid regex; UI may show a hint. */\n invalid?: boolean;\n}\n\n/** Compiles a search term to a matcher.\n * - `/foo/` → regex (case-insensitive by default; honors flags after the closing slash)\n * - anything else → case-insensitive substring (existing behavior)\n * - invalid regex → falls back to substring, sets `invalid: true` */\nexport function compileSearchPattern(term: string | null): SearchMatcher | null {\n if (!term) return null;\n const slashed = /^\\/(.+)\\/([gimsuy]*)$/.exec(term);\n if (slashed) {\n const flags = slashed[2]!.includes('i') ? slashed[2]! : slashed[2]! + 'i';\n try {\n const re = new RegExp(slashed[1]!, flags);\n return { test: (l: string) => re.test(l), regex: re };\n } catch {\n const lower = term.toLowerCase();\n return { test: (l: string) => l.toLowerCase().includes(lower), invalid: true };\n }\n }\n const lower = term.toLowerCase();\n return { test: (l: string) => l.toLowerCase().includes(lower) };\n}\n\nexport type LogLevel = 'error' | 'warn' | 'info';\n\n/** Detects the level of a log line by case-insensitive keyword priority:\n * error (and synonyms) > warn > info. Used by the L-level filter. */\nexport function detectLogLevel(line: string): LogLevel {\n const l = line.toLowerCase();\n // Conjugations covered for fail/crash; `error` and `exception` matched as exact word.\n if (/\\b(?:error|err|fail(?:ed|ure|ures|s)?|fatal|exception|crash(?:ed|es)?)\\b/.test(l) || /❌|✗|⛔/.test(line)) return 'error';\n if (/\\b(?:warn(?:ed|ing|s|ings)?|deprec)\\b/.test(l) || /⚠/.test(line)) return 'warn';\n return 'info';\n}\n","/** Returns the env record with values redacted to *** for keys that look\n * secret-ish (token / password / secret / key / auth). Case-insensitive. */\nexport function redactSecrets(env: Record<string, string> | undefined): Record<string, string> {\n if (!env) return {};\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) {\n out[k] = /secret|token|password|api[_-]?key|auth/i.test(k) ? '***' : v;\n }\n return out;\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { join } from 'node:path';\n\n/** Returns true if the service's node_modules is missing or its install stamp\n * doesn't match the current package.json hash. */\nexport function needsInstall(fullCwd: string): boolean {\n const nm = join(fullCwd, 'node_modules');\n if (!existsSync(nm)) return true;\n try {\n const pkgHash = createHash('md5').update(readFileSync(join(fullCwd, 'package.json'))).digest('hex');\n const stampFile = join(nm, '.install-stamp');\n if (existsSync(stampFile) && readFileSync(stampFile, 'utf8') === pkgHash) return false;\n } catch { /* stamp missing or unreadable */ }\n return true;\n}\n\n/** Writes the install stamp file for a service after a successful `npm install`. */\nexport function writeInstallStamp(fullCwd: string): void {\n try {\n const pkgHash = createHash('md5').update(readFileSync(join(fullCwd, 'package.json'))).digest('hex');\n writeFileSync(join(fullCwd, 'node_modules', '.install-stamp'), pkgHash);\n } catch { /* best effort */ }\n}\n","import type { ServiceConfig } from '../config/types.js';\n\n/** Builds the final args list for spawning a service: prepends `--max-old-space-size`\n * for `node` commands when maxMem is set, plus any nodeArgs overrides. */\nexport function buildProcessArgs(svc: ServiceConfig): string[] {\n const extra = svc.nodeArgs ?? [];\n if (!svc.maxMem) return [...extra, ...svc.args];\n if (svc.cmd === 'node') return [`--max-old-space-size=${svc.maxMem}`, ...extra, ...svc.args];\n return [...extra, ...svc.args];\n}\n\n/** Builds the env for spawning a service: merges extraEnv and injects\n * NODE_OPTIONS=--max-old-space-size when maxMem is set and cmd != 'node'. */\nexport function buildProcessEnv(svc: ServiceConfig, baseEnv: Record<string, string>): Record<string, string> {\n const env = { ...baseEnv, ...(svc.extraEnv ?? {}) };\n if (svc.maxMem && svc.cmd !== 'node') {\n const existing = env['NODE_OPTIONS'] ?? '';\n const flag = `--max-old-space-size=${svc.maxMem}`;\n if (!existing.includes('max-old-space-size')) {\n env['NODE_OPTIONS'] = existing ? `${existing} ${flag}` : flag;\n }\n }\n return env;\n}\n","/** Returns a copy of `names` sorted by the requested mode.\n * - `'name'` → alphabetical\n * - `'mem'` → highest mem first (string-parsed)\n * - any other (treated as `'errors'`) → highest error count first */\nexport function sortServiceNames(\n names: string[], sortMode: string,\n statsMap: Record<string, { cpu?: string; mem?: string }>,\n procState: Record<string, { errors?: number }>,\n): string[] {\n if (sortMode === 'name') return names.slice().sort();\n return names.slice().sort((a, b) => {\n if (sortMode === 'mem') {\n return (parseFloat(statsMap[b]?.mem ?? '0') || 0) - (parseFloat(statsMap[a]?.mem ?? '0') || 0);\n }\n return (procState[b]?.errors ?? 0) - (procState[a]?.errors ?? 0);\n });\n}\n\n/** Converts cumulative CPU seconds into a percentage of wall-clock time\n * elapsed since the previous sample. */\nexport function calcCpuPercent(totalCpuSec: number, prevCpu: number, prevTime: number): number {\n const elapsed = (Date.now() - prevTime) / 1000;\n const cpuDelta = totalCpuSec - prevCpu;\n return elapsed > 0 ? (cpuDelta / elapsed) * 100 : 0;\n}\n\n/** Hysteresis state machine for the \"RAM pressure\" banner.\n * - turns on when usagePct ≥ highWatermark\n * - turns off when usagePct < lowWatermark\n * - stays as-is in the dead band between watermarks */\nexport function nextRamBannerVisibility(\n usagePct: number,\n previousVisible: boolean,\n highWatermark = 80,\n lowWatermark = 75,\n): boolean {\n if (usagePct >= highWatermark) return true;\n if (usagePct < lowWatermark) return false;\n return previousVisible;\n}\n","import type { ServiceConfig } from '../config/types.js';\n\n/** Groups a flat list of services by their `phase` field. */\nexport function groupByPhase(services: ServiceConfig[]): Record<number, ServiceConfig[]> {\n const phases: Record<number, ServiceConfig[]> = {};\n for (const s of services) {\n (phases[s.phase] ??= []).push(s);\n }\n return phases;\n}\n","/** Color palette used for the service-tag prefix in the logs panel.\n * Wrapped modulo length when there are more services than entries. */\nexport const tagColors = [\n 'cyan', 'yellow', 'green', 'magenta', 'blue',\n 'red', '#5faf5f', '#d7af5f', '#5f87d7', '#af5faf',\n '#5fd7d7', '#d75f5f', 'white',\n];\n","import { createConnection } from 'node:net';\nimport { createInterface } from 'node:readline';\nimport { existsSync } from 'node:fs';\nimport { defaultSocketPath } from './socket-server.js';\n\nexport { defaultSocketPath };\n\n/** Resolve the socket path, preferring an explicit override. */\nexport function resolveSocket(projectName: string, overridePath?: string): string {\n return overridePath ?? defaultSocketPath(projectName);\n}\n\n/** Throw a friendly error if the socket doesn't exist (devup not running). */\nexport function assertSocketExists(socketPath: string, projectName: string): void {\n if (!existsSync(socketPath)) {\n throw new Error(\n `devup is not running for project \"${projectName}\".\\nStart it with \\`devup\\` first.`,\n );\n }\n}\n\n/** Send a single RPC request and return the result, or throw on error. */\nexport function sendRpc(\n socketPath: string,\n method: string,\n params: Record<string, unknown> = {},\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let settled = false;\n const fail = (err: Error) => { if (!settled) { settled = true; reject(err); } };\n const ok = (v: unknown) => { if (!settled) { settled = true; resolve(v); } };\n\n const c = createConnection(socketPath);\n const rl = createInterface({ input: c });\n // Both the socket AND the readline interface can emit 'error' (readline\n // re-forwards errors from its input stream). Attach to BOTH so an\n // ECONNREFUSED on the socket can't escape as an unhandled error event.\n c.on('error', fail);\n rl.on('error', fail);\n rl.once('line', l => {\n c.end();\n try {\n const msg = JSON.parse(l);\n if (msg.error) fail(new Error(msg.error.message ?? String(msg.error)));\n else ok(msg.result);\n } catch (e: any) {\n fail(e);\n }\n });\n c.write(JSON.stringify({ id: 1, method, params }) + '\\n');\n });\n}\n\nexport interface StreamFrame {\n event: string;\n data: unknown;\n svc?: string;\n}\n\n/** Open a streaming RPC (logs.follow / status.follow).\n * Returns an abort function. The stream runs until abort() is called or the socket closes. */\nexport function openStream(\n socketPath: string,\n method: string,\n params: Record<string, unknown>,\n onFrame: (frame: StreamFrame) => void,\n onError?: (err: Error) => void,\n): () => void {\n const c = createConnection(socketPath);\n const rl = createInterface({ input: c });\n let ackDone = false;\n\n // Both the socket and the readline interface can emit 'error'. Listen on\n // both — without an rl handler an ECONNREFUSED can escape as an unhandled\n // 'error' event and crash the host process.\n const onErr = (err: Error) => onError?.(err);\n c.on('error', onErr);\n rl.on('error', onErr);\n c.write(JSON.stringify({ id: 1, method, params }) + '\\n');\n\n rl.on('line', l => {\n try {\n const msg = JSON.parse(l);\n if (!ackDone) {\n ackDone = true;\n if (msg.error) { onError?.(new Error(msg.error.message ?? String(msg.error))); c.destroy(); }\n return;\n }\n if (msg.event) onFrame(msg as StreamFrame);\n } catch { /* ignore malformed frames */ }\n });\n\n return () => c.destroy();\n}\n","import { createServer, type Server, type Socket } from 'node:net';\nimport { createInterface } from 'node:readline';\nimport { existsSync, unlinkSync, chmodSync, mkdirSync, statSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { ProcessState } from '../process/types.js';\n\n/** Minimal JSON-RPC-like protocol over a local Unix socket.\n * Request ─► { id?, method, params? } newline-terminated JSON\n * Response ─► { id?, result | error } newline-terminated JSON\n * Stream ─► { id, event, data } pushed until socket closes\n *\n * Auth model: unix socket created with `chmod 0600`. Anyone with read access\n * to the socket file already has the same uid as the devup process — no\n * additional auth needed. Strictly local; TCP exposure is intentionally\n * out of scope. */\n\nexport interface ServiceStatEntry {\n cpu: number; // percent (e.g. 2.3)\n memMB: number; // RSS in MB (e.g. 184.2)\n}\n\nexport interface StatsResult {\n services: Record<string, ServiceStatEntry>;\n system: {\n totalMemMB: number;\n freeMemMB: number;\n cpuCores: number;\n };\n}\n\nexport interface ProxyInfo {\n active: boolean;\n provider: string;\n domain: string;\n tls: boolean;\n routes: Record<string, string>;\n}\n\nexport interface ProjectInfo {\n project: string;\n profiles: Record<string, string[]>;\n}\n\nexport interface RpcContext {\n /** State of every service (read-only snapshot). */\n states(): Map<string, ProcessState>;\n /** Restart a service by name. */\n restart(name: string): Promise<void>;\n /** Stop a service by name. */\n stop(name: string): void;\n /** Tail N most recent log lines for the given service (from the persistent log file). */\n tailLogs(svcName: string, lines: number): Promise<string[]>;\n /** Subscribe to live log lines. Pass null to receive logs from all services.\n * Returns an unsubscribe function. */\n watchLogs(svcName: string | null, onLine: (svc: string, line: string) => void): () => void;\n /** Subscribe to service-state changes. Returns an unsubscribe function. */\n watchStatus(onUpdate: (name: string, state: ProcessState) => void): () => void;\n /** Per-service CPU/mem stats + system totals. */\n getStats(): Promise<StatsResult>;\n /** Active proxy configuration, or null when no proxy is running. */\n getProxyInfo(): ProxyInfo | null;\n /** Project metadata: name and profiles defined in config. */\n getInfo(): ProjectInfo;\n}\n\nexport interface SocketServerHandle {\n server: Server;\n path: string;\n close(): Promise<void>;\n}\n\nexport function defaultSocketPath(projectName: string): string {\n const safe = projectName.replace(/[^a-zA-Z0-9._-]+/g, '_') || 'devup';\n return join(homedir(), '.devup', `sock-${safe}.sock`);\n}\n\nexport async function startSocketServer(\n projectName: string,\n ctx: RpcContext,\n opts: { path?: string; onLog?: (msg: string) => void } = {},\n): Promise<SocketServerHandle> {\n const path = opts.path ?? defaultSocketPath(projectName);\n mkdirSync(dirname(path), { recursive: true });\n\n // Stale socket from a crashed previous run.\n if (existsSync(path)) {\n try {\n const st = statSync(path);\n if (st.isSocket()) unlinkSync(path);\n } catch { /* ignore — listen() will surface the real error */ }\n }\n\n // Track every active client socket so `close()` can destroy them. Without\n // this, `server.close()` waits for all clients to disconnect on their own\n // — and long-lived streaming clients (logs.follow / status.follow, e.g.\n // the VS Code extension) keep the connection open indefinitely, which\n // means `devup down` would hang past its 10 s grace and SIGKILL the daemon\n // before cleanup could run, leaking child processes.\n const activeClients = new Set<Socket>();\n const server = createServer(socket => {\n activeClients.add(socket);\n socket.once('close', () => activeClients.delete(socket));\n handleClient(socket, ctx);\n });\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(path, () => {\n server.off('error', reject);\n try { chmodSync(path, 0o600); } catch { /* best effort on platforms without chmod */ }\n opts.onLog?.(`🔌 control plane at ${path}`);\n resolve();\n });\n });\n\n return {\n server,\n path,\n async close() {\n // Destroy active clients first so server.close() can complete promptly.\n for (const sock of activeClients) sock.destroy();\n activeClients.clear();\n await new Promise<void>(resolve => server.close(() => resolve()));\n if (existsSync(path)) {\n try { unlinkSync(path); } catch { /* ignore */ }\n }\n },\n };\n}\n\nfunction handleClient(socket: Socket, ctx: RpcContext): void {\n const rl = createInterface({ input: socket });\n const unsubs = new Set<() => void>();\n\n socket.on('close', () => {\n for (const unsub of unsubs) unsub();\n unsubs.clear();\n });\n\n rl.on('line', async (line: string) => {\n if (!line.trim()) return;\n let req: { id?: unknown; method?: unknown; params?: unknown };\n try {\n req = JSON.parse(line);\n } catch (e: any) {\n respond(socket, { error: { code: -32700, message: `parse error: ${e.message}` } });\n return;\n }\n if (typeof req.method !== 'string') {\n respond(socket, { id: req.id, error: { code: -32600, message: 'method required' } });\n return;\n }\n const params = (req.params ?? {}) as Record<string, unknown>;\n if (req.method === 'logs.follow' || req.method === 'status.follow') {\n try {\n await handleFollow(socket, req as { id?: unknown; method: string }, params, ctx, unsubs);\n } catch (e: any) {\n respond(socket, { id: req.id, error: { code: -32603, message: e.message ?? String(e) } });\n }\n return;\n }\n try {\n const result = await dispatch(req.method, params, ctx);\n respond(socket, { id: req.id, result });\n } catch (e: any) {\n respond(socket, { id: req.id, error: { code: -32603, message: e.message ?? String(e) } });\n }\n });\n socket.on('error', () => {/* swallow ECONNRESET etc. */});\n}\n\nasync function handleFollow(\n socket: Socket,\n req: { id?: unknown; method: string },\n params: Record<string, unknown>,\n ctx: RpcContext,\n unsubs: Set<() => void>,\n): Promise<void> {\n if (req.method === 'logs.follow') {\n const rawSvc = params['svc'] ?? params['service'];\n const svcName = rawSvc != null ? stringOrThrow(rawSvc, 'svc') : null;\n const tail = Math.max(0, Math.min(1000, Number(params['tail'] ?? 50)));\n\n respond(socket, { id: req.id, result: { ok: true } });\n\n // Replay recent history before going live.\n if (svcName) {\n const lines = await ctx.tailLogs(svcName, tail);\n for (const l of lines) {\n respond(socket, { id: req.id, event: 'log', data: l });\n }\n }\n\n const unsub = ctx.watchLogs(svcName, (svc, line) => {\n respond(socket, { id: req.id, event: 'log', data: line, svc });\n });\n unsubs.add(unsub);\n\n } else {\n // status.follow\n respond(socket, { id: req.id, result: { ok: true } });\n\n // Send current snapshot immediately so the client has something to render.\n const snapshot: Array<Record<string, unknown>> = [];\n for (const [name, st] of ctx.states()) {\n snapshot.push(serializeState(name, st));\n }\n if (snapshot.length) {\n respond(socket, { id: req.id, event: 'status', data: snapshot });\n }\n\n const unsub = ctx.watchStatus((name, state) => {\n respond(socket, { id: req.id, event: 'status', data: [serializeState(name, state)] });\n });\n unsubs.add(unsub);\n }\n}\n\nfunction serializeState(name: string, st: ProcessState): Record<string, unknown> {\n return {\n name,\n status: st.status,\n health: st.health,\n port: st.svc.port,\n type: st.svc.type,\n phase: st.svc.phase,\n errors: st.errors,\n restarts: st.restarts,\n pid: st.pid,\n startedAt: st.startedAt,\n };\n}\n\nfunction respond(socket: Socket, payload: object): void {\n if (socket.writable) socket.write(JSON.stringify(payload) + '\\n');\n}\n\nasync function dispatch(\n method: string,\n params: Record<string, unknown>,\n ctx: RpcContext,\n): Promise<unknown> {\n switch (method) {\n case 'status': {\n const out: Array<Record<string, unknown>> = [];\n for (const [name, st] of ctx.states()) {\n out.push(serializeState(name, st));\n }\n return { services: out, proxy: ctx.getProxyInfo() };\n }\n case 'stats':\n return await ctx.getStats();\n case 'info':\n return ctx.getInfo();\n case 'restart': {\n const svc = stringOrThrow(params['svc'] ?? params['service'], 'svc');\n await ctx.restart(svc);\n return { ok: true };\n }\n case 'stop': {\n const svc = stringOrThrow(params['svc'] ?? params['service'], 'svc');\n ctx.stop(svc);\n return { ok: true };\n }\n case 'logs.tail': {\n const svc = stringOrThrow(params['svc'] ?? params['service'], 'svc');\n const lines = Math.max(1, Math.min(10_000, Number(params['lines'] ?? 100)));\n return { lines: await ctx.tailLogs(svc, lines) };\n }\n case 'ping':\n return { ok: true, ts: Date.now() };\n default:\n throw new Error(`unknown method: ${method}`);\n }\n}\n\nfunction stringOrThrow(v: unknown, paramName: string): string {\n if (typeof v !== 'string' || !v.trim()) {\n throw new Error(`param \"${paramName}\" must be a non-empty string`);\n }\n return v;\n}\n","import { spawn } from 'node:child_process';\nimport { writeFileSync, readFileSync, existsSync, unlinkSync, mkdirSync, createReadStream } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir, totalmem, freemem, cpus } from 'node:os';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { createInterface } from 'node:readline';\n\nimport { ProcessManager } from '../process/manager.js';\nimport { LogSink } from '../process/log-sink.js';\nimport { groupByPhase, calcCpuPercent } from '../utils.js';\nimport { waitForPort } from '../process/health.js';\nimport { Broadcaster } from '../utils/broadcaster.js';\nimport { startSocketServer, type SocketServerHandle } from '../control-plane/socket-server.js';\nimport { startExternals, stopExternals, type ExternalProc } from '../process/external.js';\nimport { classifyServices, rewriteServicePort } from '../lazy/classifier.js';\nimport { createLazyProxy, type LazyProxy } from '../lazy/proxy.js';\nimport { watchConfig } from './config-watcher.js';\nimport { findConfigFile } from '../config/loader.js';\n\nimport type { DevStackConfig, ServiceConfig } from '../config/types.js';\nimport type { CliArgs } from '../config/cli.js';\nimport type { Platform } from '../platform/types.js';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from '../proxy-config/types.js';\nimport type { ProcessState } from '../process/types.js';\n\nconst SAFE = /[^a-zA-Z0-9._-]+/g;\nconst sanitize = (n: string) => n.replace(SAFE, '_').replace(/^_+|_+$/g, '') || 'devup';\nconst devupDir = () => join(homedir(), '.devup');\n\nexport function pidPathFor(projectName: string): string {\n return join(devupDir(), `${sanitize(projectName)}.pid`);\n}\nexport function bootErrorPathFor(projectName: string): string {\n return join(devupDir(), `${sanitize(projectName)}.boot-error`);\n}\n\nfunction pidAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\n/** Inspect the PID file. `pid=null` means no daemon recorded.\n * `stale=true` means a pid file exists but the recorded pid is not alive. */\nexport function isDaemonRunning(projectName: string): { pid: number | null; stale: boolean } {\n const path = pidPathFor(projectName);\n if (!existsSync(path)) return { pid: null, stale: false };\n let pid: number;\n try {\n pid = Number(readFileSync(path, 'utf8').trim());\n if (!pid || !Number.isFinite(pid)) return { pid: null, stale: true };\n } catch {\n return { pid: null, stale: true };\n }\n return pidAlive(pid) ? { pid, stale: false } : { pid, stale: true };\n}\n\n// ── Daemon child body ──────────────────────────────────────────────────────\n\nexport interface DaemonOpts {\n config: DevStackConfig;\n services: ServiceConfig[];\n cliArgs: CliArgs;\n platform: Platform;\n env: Record<string, string>;\n baseCwd: string;\n proxyProvider: ProxyConfigProvider | null;\n proxyOpts: ProxyOpts | null;\n}\n\n/** Runs in the detached child process. Boots the stack, opens the control\n * plane, writes the PID file when ready (the parent's success signal), then\n * stays alive until SIGTERM/SIGINT. */\nexport async function daemonBody(opts: DaemonOpts): Promise<void> {\n const { config, services, cliArgs, platform, env, baseCwd, proxyProvider, proxyOpts } = opts;\n const projectName = config.name;\n const errPath = bootErrorPathFor(projectName);\n const pidPath = pidPathFor(projectName);\n\n mkdirSync(devupDir(), { recursive: true });\n if (existsSync(errPath)) { try { unlinkSync(errPath); } catch { /* ignore */ } }\n\n // Always write logs to disk in daemon mode (no terminal to scroll back through).\n const logSink = new LogSink({ projectName, rootDir: cliArgs.logDir });\n\n const logBus = new Broadcaster<{ svc: string; text: string }>();\n const stateBus = new Broadcaster<{ name: string; state: ProcessState }>();\n const lazyProxies = new Map<string, LazyProxy>();\n const prevCpuMap = new Map<string, { time: number; cpu: number }>();\n let externals: ExternalProc[] = [];\n let socket: SocketServerHandle | null = null;\n let healthTimer: NodeJS.Timeout | null = null;\n let proxyTimer: NodeJS.Timeout | null = null;\n let stopConfigWatcher: (() => void) | null = null;\n\n const writeDevupLog = (text: string) => {\n logSink.write('devup', text);\n logBus.emit({ svc: 'devup', text });\n };\n\n const mgr = new ProcessManager({\n baseCwd, env, platform,\n events: {\n onLog: (svcName, text) => {\n logSink.write(svcName, text);\n logBus.emit({ svc: svcName, text });\n },\n onStateChange: (name, state) => stateBus.emit({ name, state }),\n },\n });\n\n const cleanup = async (): Promise<void> => {\n if (healthTimer) clearInterval(healthTimer);\n if (proxyTimer) clearInterval(proxyTimer);\n if (stopConfigWatcher) { try { stopConfigWatcher(); } catch { /* ignore */ } }\n for (const p of lazyProxies.values()) p.destroy();\n if (socket) await socket.close().catch(() => {});\n await mgr.cleanup().catch(() => {});\n if (externals.length) {\n await stopExternals(externals, platform, {\n baseCwd, env,\n onLog: (svc, msg) => logSink.write(`ext:${svc}`, msg),\n }).catch(() => {});\n }\n if (proxyProvider && proxyOpts && cliArgs.proxy) {\n try { proxyProvider.clear(proxyOpts); } catch { /* ignore */ }\n }\n await logSink.close().catch(() => {});\n if (existsSync(pidPath)) { try { unlinkSync(pidPath); } catch { /* ignore */ } }\n };\n\n let shuttingDown = false;\n const onSignal = () => {\n if (shuttingDown) return;\n shuttingDown = true;\n cleanup().then(() => process.exit(0), () => process.exit(1));\n };\n process.on('SIGTERM', onSignal);\n process.on('SIGINT', onSignal);\n\n try {\n // ── Externals (DBs, queues) — must be healthy before phase 0 ──\n if (config.external?.length) {\n writeDevupLog(`▶ externals (${config.external.length})`);\n const result = await startExternals(config.external, {\n baseCwd, env, platform,\n onLog: (svc, msg) => { logSink.write(`ext:${svc}`, msg); logBus.emit({ svc: `ext:${svc}`, text: msg }); },\n });\n externals = result.procs;\n if (!result.allHealthy) {\n throw new Error(`externals failed: ${result.failed.join(', ')}`);\n }\n }\n\n // ── Boot phases ──\n if (cliArgs.lazy && config.lazy) {\n await bootLazy(mgr, services, config.lazy, cliArgs.lazyTimeout, lazyProxies);\n } else {\n await bootNormal(mgr, services);\n }\n\n // ── Control plane ──\n socket = await startSocketServer(projectName, {\n states: () => mgr.state,\n restart: (n) => mgr.restart(n),\n stop: (n) => mgr.stop(n),\n tailLogs: async (svcName, lines) => {\n const file = logSink.pathFor(svcName);\n if (!existsSync(file)) return [];\n return new Promise<string[]>((resolve, reject) => {\n const buf: string[] = [];\n const rl = createInterface({ input: createReadStream(file, { encoding: 'utf8' }) });\n rl.on('line', l => { buf.push(l); if (buf.length > lines) buf.shift(); });\n rl.on('close', () => resolve(buf));\n rl.on('error', reject);\n });\n },\n watchLogs: (svcName, onLine) => logBus.subscribe(({ svc, text }) => {\n if (svcName === null || svc === svcName) onLine(svc, text);\n }),\n watchStatus: (onUpdate) => stateBus.subscribe(({ name, state }) => onUpdate(name, state)),\n async getStats() {\n const pids: number[] = [];\n const pidToName = new Map<number, string>();\n for (const [name, st] of mgr.state) {\n if (st.pid) { pids.push(st.pid); pidToName.set(st.pid, name); }\n }\n const raw = pids.length ? await platform.getProcessStats(pids) : new Map();\n const services: Record<string, { cpu: number; memMB: number }> = {};\n for (const [name] of mgr.state) {\n services[name] = { cpu: 0, memMB: 0 };\n }\n for (const [pid, data] of raw) {\n const name = pidToName.get(pid);\n if (!name) continue;\n const prev = prevCpuMap.get(name) ?? { time: Date.now(), cpu: 0 };\n const cpu = calcCpuPercent(data.cpuSeconds, prev.cpu, prev.time);\n prevCpuMap.set(name, { time: Date.now(), cpu: data.cpuSeconds });\n services[name] = { cpu: Math.round(cpu * 10) / 10, memMB: Math.round((data.rss / 1024) * 10) / 10 };\n }\n return {\n services,\n system: {\n totalMemMB: Math.round(totalmem() / 1024 / 1024),\n freeMemMB: Math.round(freemem() / 1024 / 1024),\n cpuCores: cpus().length,\n },\n };\n },\n getProxyInfo() {\n if (!proxyProvider || !proxyOpts || !cliArgs.proxy) return null;\n return {\n active: true,\n provider: proxyProvider.name,\n domain: proxyOpts.domain,\n tls: proxyOpts.tls,\n routes: proxyOpts.routes,\n };\n },\n getInfo() {\n return { project: projectName, profiles: config.profiles ?? {} };\n },\n }, { onLog: msg => writeDevupLog(msg) });\n\n // ── Health poller (keeps state.health fresh for control-plane consumers) ──\n healthTimer = setInterval(() => { void mgr.checkAllHealth(); }, 3000);\n\n // ── Proxy sync (write traefik/nginx/caddy config when state changes) ──\n if (proxyProvider && proxyOpts && cliArgs.proxy) {\n let lastContent: string | null = null;\n const sync = () => {\n const svcStates = new Map<string, ServiceState>();\n for (const [n, st] of mgr.state) {\n svcStates.set(n, { port: st.svc.port, health: st.health, realPort: (st.svc as { realPort?: number }).realPort });\n }\n const content = proxyProvider.generate(svcStates, proxyOpts);\n if (content === lastContent) return;\n lastContent = content;\n try { proxyProvider.write(content, proxyOpts); } catch { /* ignore — best-effort */ }\n };\n sync();\n proxyTimer = setInterval(sync, 3000);\n }\n\n // ── Hot-reload watcher (opt-in via --watch-config) ──\n if (cliArgs.watchConfig) {\n try {\n const configPath = findConfigFile(baseCwd, cliArgs.configPath);\n writeDevupLog(`👀 watching ${configPath}`);\n stopConfigWatcher = watchConfig({\n configPath, baseCwd, manager: mgr,\n log: msg => writeDevupLog(msg),\n });\n } catch (e: any) {\n writeDevupLog(`⚠ watch-config disabled: ${e.message ?? String(e)}`);\n }\n }\n\n // ── Write PID file (signals \"ready\" to the parent process) ──\n writeFileSync(pidPath, String(process.pid));\n writeDevupLog(`✓ daemon ready (pid=${process.pid})`);\n\n // Stay alive. The open socket server + child procs keep the event loop running.\n // SIGTERM/SIGINT handler does the actual exit.\n } catch (e: any) {\n try { writeFileSync(errPath, e.message ?? String(e)); } catch { /* ignore */ }\n try { writeDevupLog(`❌ boot failed: ${e.message ?? String(e)}`); } catch { /* ignore */ }\n await cleanup().catch(() => {});\n process.exit(1);\n }\n}\n\nasync function bootNormal(mgr: ProcessManager, services: ServiceConfig[]): Promise<void> {\n const phases = groupByPhase(services);\n let colorIdx = 0;\n for (const num of Object.keys(phases).map(Number).sort((a, b) => a - b)) {\n for (const svc of phases[num]!) {\n const ci = colorIdx++;\n await mgr.install(svc, ci);\n await mgr.start(svc, ci);\n }\n const apis = phases[num]!.filter(s => s.type === 'api');\n if (apis.length) await Promise.all(apis.map(s => waitForPort(s.port, { timeout: 45000 })));\n phases[num]!.filter(s => s.type === 'web').forEach(s => {\n const st = mgr.state.get(s.name);\n if (st) st.status = 'running';\n });\n }\n}\n\nasync function bootLazy(\n mgr: ProcessManager,\n services: ServiceConfig[],\n lazyCfg: NonNullable<DevStackConfig['lazy']>,\n lazyTimeout: number,\n lazyProxies: Map<string, LazyProxy>,\n): Promise<void> {\n const { alwaysOn, lazy } = classifyServices(services, lazyCfg);\n const phases = groupByPhase(alwaysOn);\n let colorIdx = 0;\n for (const num of Object.keys(phases).map(Number).sort((a, b) => a - b)) {\n for (const svc of phases[num]!) {\n const ci = colorIdx++;\n await mgr.install(svc, ci);\n await mgr.start(svc, ci);\n }\n const apis = phases[num]!.filter(s => s.type === 'api');\n if (apis.length) await Promise.all(apis.map(s => waitForPort(s.port, { timeout: 45000 })));\n phases[num]!.filter(s => s.type === 'web').forEach(s => {\n const st = mgr.state.get(s.name);\n if (st) st.status = 'running';\n });\n }\n for (const svc of lazy) {\n const ci = colorIdx++;\n const rewritten = rewriteServicePort(svc);\n mgr.state.set(svc.name, {\n svc: rewritten, proc: null, pid: null,\n status: 'idle', health: 'idle',\n errors: 0, restarts: 0, startedAt: null,\n intentionalStop: false, colorIdx: ci,\n });\n const proxy = createLazyProxy({\n listenPort: svc.port, targetPort: rewritten.realPort, timeoutMin: lazyTimeout,\n onDemandStart: async () => {\n await mgr.install(rewritten, ci);\n await mgr.start(rewritten, ci);\n const ok = await waitForPort(rewritten.realPort, { timeout: 45000 });\n const st = mgr.state.get(svc.name);\n if (st) { st.status = ok ? 'running' : 'timeout'; if (ok) st.health = 'up'; }\n },\n onIdleStop: () => {\n mgr.stop(svc.name);\n const st = mgr.state.get(svc.name);\n if (st) { st.status = 'idle'; st.health = 'idle'; st.pid = null; st.proc = null; st.startedAt = null; }\n },\n isAlive: () => {\n const st = mgr.state.get(svc.name);\n return !!st && !!st.proc && !st.proc.killed && st.health === 'up';\n },\n });\n lazyProxies.set(svc.name, proxy);\n }\n}\n\n// ── Parent process: spawn detached child and wait for ready signal ──────────\n\nexport interface DetachedOpts extends DaemonOpts {\n out?: (line: string) => void;\n}\n\n/** Runs in the parent process. Validates state, spawns the daemon child\n * detached, polls for the PID file (ready) or boot-error file (failure),\n * prints the welcome line, and returns the exit code. */\nexport async function runDetached(opts: DetachedOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => process.stdout.write(l + '\\n'));\n const projectName = opts.config.name;\n\n if (process.platform === 'win32') {\n out('❌ daemon mode (devup up -d) is not yet supported on Windows. Run `devup` to use the TUI instead.');\n return 1;\n }\n\n const existing = isDaemonRunning(projectName);\n if (existing.pid && !existing.stale) {\n out(`❌ daemon already running for \"${projectName}\" (pid=${existing.pid}). Run \\`devup down\\` to stop it.`);\n return 1;\n }\n if (existing.stale) {\n out(`ℹ removing stale pid file for \"${projectName}\"`);\n try { unlinkSync(pidPathFor(projectName)); } catch { /* ignore */ }\n }\n\n mkdirSync(devupDir(), { recursive: true });\n const errPath = bootErrorPathFor(projectName);\n const pidPath = pidPathFor(projectName);\n if (existsSync(errPath)) { try { unlinkSync(errPath); } catch { /* ignore */ } }\n\n // Strip the subcommand and detach flags from argv; the child reuses everything else.\n const filteredArgs = process.argv.slice(2).filter((arg, i) => {\n if (i === 0 && arg === 'up') return false;\n if (arg === '-d' || arg === '--detach') return false;\n return true;\n });\n\n out(`⏳ starting devup in detached mode for \"${projectName}\"...`);\n\n // Preserve any node-level args (e.g. --loader tsx in dev) so the child can be re-executed.\n const child = spawn(process.execPath, [...process.execArgv, process.argv[1]!, ...filteredArgs], {\n detached: true,\n stdio: 'ignore',\n env: { ...process.env, DEVUP_DAEMON_CHILD: '1' },\n cwd: opts.baseCwd,\n });\n child.unref();\n\n // Poll for the PID file (success) or boot-error file (failure). Max wait: 90s.\n const deadline = Date.now() + 90_000;\n while (Date.now() < deadline) {\n if (existsSync(pidPath)) {\n const pid = Number(readFileSync(pidPath, 'utf8').trim());\n out('');\n out(`🚀 devup detached (PID ${pid})`);\n out(' inspect: devup ctl status');\n out(' logs: devup ctl logs <svc> --follow');\n out(' stop: devup down');\n return 0;\n }\n if (existsSync(errPath)) {\n const msg = readFileSync(errPath, 'utf8').trim();\n out(`❌ daemon boot failed: ${msg}`);\n try { unlinkSync(errPath); } catch { /* ignore */ }\n return 1;\n }\n await sleep(200);\n }\n\n out(`❌ daemon did not become ready within 90s. Killing child (pid=${child.pid}).`);\n if (child.pid) { try { process.kill(child.pid, 'SIGTERM'); } catch { /* ignore */ } }\n return 1;\n}\n\n// ── devup down ─────────────────────────────────────────────────────────────\n\nexport async function stopDaemon(\n projectName: string,\n opts: { out?: (line: string) => void; gracePeriodMs?: number } = {},\n): Promise<number> {\n const out = opts.out ?? ((l: string) => process.stdout.write(l + '\\n'));\n const grace = opts.gracePeriodMs ?? 10_000;\n const status = isDaemonRunning(projectName);\n\n if (!status.pid) {\n out(`ℹ no daemon running for \"${projectName}\".`);\n return 1;\n }\n if (status.stale) {\n out(`ℹ stale pid file for \"${projectName}\" (pid=${status.pid} not alive). Removing.`);\n try { unlinkSync(pidPathFor(projectName)); } catch { /* ignore */ }\n return 1;\n }\n\n out(`⏳ stopping daemon (pid=${status.pid})...`);\n try {\n process.kill(status.pid, 'SIGTERM');\n } catch (e: any) {\n out(`❌ cannot signal pid=${status.pid}: ${e.message}`);\n return 1;\n }\n\n const deadline = Date.now() + grace;\n while (Date.now() < deadline) {\n if (!pidAlive(status.pid)) {\n out(`✓ stopped daemon (pid=${status.pid})`);\n const p = pidPathFor(projectName);\n if (existsSync(p)) { try { unlinkSync(p); } catch { /* ignore */ } }\n return 0;\n }\n await sleep(200);\n }\n\n out(`⚠ daemon did not exit within ${(grace / 1000).toFixed(0)}s; sending SIGKILL.`);\n try { process.kill(status.pid, 'SIGKILL'); } catch { /* ignore */ }\n const p = pidPathFor(projectName);\n if (existsSync(p)) { try { unlinkSync(p); } catch { /* ignore */ } }\n return 0;\n}\n","import { join } from 'node:path';\nimport type { ChildProcess } from 'node:child_process';\nimport type { Platform } from '../platform/types.js';\nimport type { ServiceConfig } from '../config/types.js';\nimport type { ProcessState, ProcessManagerEvents } from './types.js';\nimport { installService } from './installer.js';\nimport { Spawner } from './spawner.js';\nimport { Restarter } from './restarter.js';\nimport { HealthPoller } from './health-poller.js';\nimport { Lifecycle } from './lifecycle.js';\n\n// Re-export the helpers + constants so existing imports keep working.\nexport { compileReadyPattern, extractWatchPaths } from './internals.js';\n\n/** Thin facade composing Spawner, Restarter, HealthPoller, and Lifecycle.\n * All four components share the same `state` Map and `procs` Set, so\n * mutations from one are visible to the others.\n *\n * Public API is unchanged from the pre-refactor monolithic class —\n * every TUI / orchestrator / control-plane call site keeps working. */\nexport class ProcessManager {\n readonly state = new Map<string, ProcessState>();\n private readonly procs = new Set<ChildProcess>();\n private readonly baseCwd: string;\n private readonly env: Record<string, string>;\n private readonly events: ProcessManagerEvents;\n private readonly spawner: Spawner;\n private readonly restarter: Restarter;\n private readonly healthPoller: HealthPoller;\n private readonly lifecycle: Lifecycle;\n\n constructor(opts: {\n baseCwd: string;\n env: Record<string, string>;\n platform: Platform;\n events: ProcessManagerEvents;\n }) {\n this.baseCwd = opts.baseCwd;\n this.env = opts.env;\n this.events = opts.events;\n\n this.lifecycle = new Lifecycle({\n state: this.state, procs: this.procs, platform: opts.platform,\n });\n\n // Forward declaration: the spawner needs onCrash, which the restarter implements.\n // We assign after both exist via the closure below.\n let restarterRef: Restarter | null = null;\n this.spawner = new Spawner({\n baseCwd: opts.baseCwd, env: opts.env,\n state: this.state, procs: this.procs,\n events: opts.events, lifecycle: this.lifecycle,\n onCrash: (svc, state, colorIdx) => restarterRef?.scheduleAutoRestart(svc, state, colorIdx),\n });\n this.restarter = new Restarter({\n state: this.state, events: opts.events,\n spawner: this.spawner, lifecycle: this.lifecycle,\n });\n restarterRef = this.restarter;\n\n this.healthPoller = new HealthPoller({\n state: this.state, events: opts.events,\n });\n }\n\n install(svc: ServiceConfig, colorIdx?: number): Promise<boolean> {\n const cwd = join(this.baseCwd, svc.cwd);\n const idx = colorIdx ?? this.state.get(svc.name)?.colorIdx ?? 0;\n return installService(cwd, this.env, msg => this.events.onLog(svc.name, msg, idx));\n }\n\n start(svc: ServiceConfig, colorIdx: number, isRestart = false): Promise<void> {\n return this.spawner.start(svc, colorIdx, isRestart);\n }\n\n stop(name: string): void {\n this.lifecycle.stop(name);\n }\n\n restart(name: string): Promise<void> {\n return this.restarter.restart(name);\n }\n\n checkAllHealth(): Promise<void> {\n return this.healthPoller.checkAll();\n }\n\n cleanup(opts: { gracePeriodMs?: number } = {}): Promise<void> {\n return this.lifecycle.cleanup(opts);\n }\n}\n","import { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { needsInstall, writeInstallStamp } from '../utils.js';\n\nexport function installService(\n cwd: string, env: Record<string, string>,\n onLog?: (msg: string) => void,\n): Promise<boolean> {\n if (!existsSync(cwd)) {\n onLog?.(`⚠ directory not found: ${cwd}`);\n return Promise.resolve(false);\n }\n if (!needsInstall(cwd)) {\n onLog?.('✅ dependencies up to date');\n return Promise.resolve(true);\n }\n onLog?.('📦 npm install...');\n return new Promise(resolve => {\n // En Windows, npm es usualmente npm.cmd\n const command = process.platform === 'win32' ? 'npm.cmd' : 'npm';\n const proc = spawn(command, ['install'], { cwd, env, stdio: ['ignore', 'ignore', 'pipe'] });\n let stderr = '';\n proc.stderr?.on('data', (d: Buffer) => { stderr += d.toString(); });\n proc.on('close', code => {\n if (code !== 0) {\n onLog?.(`⚠ npm install failed: ${stderr.split('\\n')[0]}`);\n resolve(false);\n } else {\n writeInstallStamp(cwd);\n onLog?.('✅ dependencies ready');\n resolve(true);\n }\n });\n proc.on('error', (err) => {\n onLog?.(`⚠ spawn error: ${err.message}`);\n resolve(false);\n });\n });\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport type { ServiceConfig } from '../config/types.js';\nimport type { ProcessState, ProcessManagerEvents } from './types.js';\nimport { isPortBindable } from './health.js';\nimport { buildProcessArgs, buildProcessEnv } from '../utils.js';\nimport { lineBuffer, compileReadyPattern, extractWatchPaths } from './internals.js';\nimport type { Lifecycle } from './lifecycle.js';\n\ninterface SpawnerOpts {\n baseCwd: string;\n env: Record<string, string>;\n state: Map<string, ProcessState>;\n procs: Set<ChildProcess>;\n events: ProcessManagerEvents;\n lifecycle: Lifecycle;\n /** Called when a service exits non-zero, so the Restarter can schedule auto-restart. */\n onCrash: (svc: ServiceConfig, state: ProcessState, colorIdx: number) => void;\n}\n\n/** Owns the spawn lifecycle: port check → preBuild → watch-path pre-flight →\n * spawn → wire stdio (readyPattern + errorPattern + log) → watchBuild → close\n * handler. On crash, delegates to `onCrash` (the Restarter wires this). */\nexport class Spawner {\n private readonly baseCwd: string;\n private readonly env: Record<string, string>;\n private readonly state: Map<string, ProcessState>;\n private readonly procs: Set<ChildProcess>;\n private readonly events: ProcessManagerEvents;\n private readonly lifecycle: Lifecycle;\n private readonly onCrash: SpawnerOpts['onCrash'];\n\n constructor(opts: SpawnerOpts) {\n this.baseCwd = opts.baseCwd;\n this.env = opts.env;\n this.state = opts.state;\n this.procs = opts.procs;\n this.events = opts.events;\n this.lifecycle = opts.lifecycle;\n this.onCrash = opts.onCrash;\n }\n\n async start(svc: ServiceConfig, colorIdx: number, isRestart = false): Promise<void> {\n const cwd = join(this.baseCwd, svc.cwd);\n\n // Port occupied check (APIs only — webs are assumed to manage their own).\n // Use bind-based test so we catch every state that would EADDRINUSE the\n // spawned service, not just sockets that already accept connections.\n if (svc.type === 'api') {\n const bindable = await isPortBindable(svc.port);\n if (!bindable && !isRestart) {\n this.log(svc.name, `⚠ port ${svc.port} already in use — skipping`, colorIdx);\n this.recordCrashedState(svc, colorIdx);\n return;\n }\n }\n\n // preBuild: run synchronously before spawning the service.\n if (svc.preBuild) {\n const built = await this.runPreBuild(svc, cwd, colorIdx);\n if (!built) {\n this.recordCrashedState(svc, colorIdx);\n return;\n }\n }\n\n const args = buildProcessArgs(svc);\n\n // Pre-flight: every --watch / --watch-path must resolve to an existing path.\n const missingWatchPaths = extractWatchPaths(args)\n .filter(p => !existsSync(resolve(cwd, p)));\n if (missingWatchPaths.length) {\n this.log(svc.name, `⚠ missing watch paths: ${missingWatchPaths.join(', ')}`, colorIdx);\n this.recordCrashedState(svc, colorIdx);\n return;\n }\n\n const env = buildProcessEnv(svc, this.env);\n const proc = spawn(svc.cmd, args, { cwd, env, detached: true, stdio: ['ignore', 'pipe', 'pipe'] });\n\n const prev = this.state.get(svc.name);\n const state: ProcessState = {\n svc, proc, pid: proc.pid ?? null,\n status: 'starting', health: 'wait',\n errors: prev?.errors ?? 0,\n restarts: prev?.restarts ?? 0,\n startedAt: Date.now(),\n intentionalStop: false,\n colorIdx,\n };\n this.state.set(svc.name, state);\n this.procs.add(proc);\n this.events.onStateChange(svc.name, state);\n\n this.wireStdio(proc, svc, state, colorIdx);\n this.wireCloseHandler(proc, svc, state, colorIdx);\n\n // watchBuild: side-car process running alongside the service.\n if (svc.watchBuild) {\n state.watchProc = this.spawnWatchBuild(svc, cwd, env, colorIdx);\n }\n\n this.log(svc.name, isRestart ? `🔄 restarted (:${svc.port})` : `🚀 started (:${svc.port})`, colorIdx);\n }\n\n private wireStdio(proc: ChildProcess, svc: ServiceConfig, state: ProcessState, colorIdx: number): void {\n const readyRegex = compileReadyPattern(svc.readyPattern);\n const markReadyIfMatch = (line: string) => {\n if (!readyRegex || state.health === 'up') return;\n if (readyRegex.test(line)) {\n state.health = 'up';\n if (state.status === 'starting') state.status = 'running';\n this.events.onStateChange(svc.name, state);\n }\n };\n const errorRegex = compileReadyPattern(svc.errorPattern);\n const countsAsError = (line: string) => errorRegex ? errorRegex.test(line) : true;\n\n const stdoutBuf = lineBuffer(line => { markReadyIfMatch(line); this.log(svc.name, line, colorIdx); });\n const stderrBuf = lineBuffer(line => {\n if (countsAsError(line)) state.errors += 1;\n markReadyIfMatch(line);\n this.log(svc.name, line, colorIdx);\n });\n\n proc.stdout?.on('data', (d: Buffer) => stdoutBuf.push(d));\n proc.stderr?.on('data', (d: Buffer) => stderrBuf.push(d));\n proc.stdout?.on('end', () => stdoutBuf.flush());\n proc.stderr?.on('end', () => stderrBuf.flush());\n }\n\n private wireCloseHandler(proc: ChildProcess, svc: ServiceConfig, state: ProcessState, colorIdx: number): void {\n proc.on('close', code => {\n this.procs.delete(proc);\n this.lifecycle.stopWatchProc(state);\n if (state.intentionalStop) { state.intentionalStop = false; return; }\n if (code === 0) {\n state.status = 'stopped'; state.health = 'down';\n this.events.onStateChange(svc.name, state);\n return;\n }\n state.status = 'crashed'; state.health = 'down';\n this.log(svc.name, `❌ exited with code ${code}`, colorIdx);\n this.events.onStateChange(svc.name, state);\n this.onCrash(svc, state, colorIdx);\n });\n }\n\n private runPreBuild(svc: ServiceConfig, cwd: string, colorIdx: number): Promise<boolean> {\n this.log(svc.name, `🔨 preBuild: ${svc.preBuild}`, colorIdx);\n return new Promise(res => {\n const isWin = process.platform === 'win32';\n const shell = isWin ? 'cmd.exe' : 'sh';\n const shellFlag = isWin ? '/c' : '-c';\n const env = buildProcessEnv(svc, this.env);\n const child = spawn(shell, [shellFlag, svc.preBuild!], { cwd, env, stdio: ['ignore', 'pipe', 'pipe'] });\n\n const outBuf = lineBuffer(line => this.log(svc.name, `[build] ${line}`, colorIdx));\n const errBuf = lineBuffer(line => this.log(svc.name, `[build] ${line}`, colorIdx));\n child.stdout?.on('data', (d: Buffer) => outBuf.push(d));\n child.stderr?.on('data', (d: Buffer) => errBuf.push(d));\n\n child.on('error', err => {\n this.log(svc.name, `[build] ❌ ${err.message}`, colorIdx);\n res(false);\n });\n child.on('close', code => {\n outBuf.flush(); errBuf.flush();\n if (code === 0) {\n this.log(svc.name, `[build] ✅ done`, colorIdx);\n res(true);\n } else {\n this.log(svc.name, `[build] ❌ exited with code ${code}`, colorIdx);\n res(false);\n }\n });\n });\n }\n\n private spawnWatchBuild(svc: ServiceConfig, cwd: string, env: Record<string, string>, colorIdx: number): ChildProcess {\n this.log(svc.name, `👀 watchBuild: ${svc.watchBuild}`, colorIdx);\n const isWin = process.platform === 'win32';\n const shell = isWin ? 'cmd.exe' : 'sh';\n const shellFlag = isWin ? '/c' : '-c';\n const child = spawn(shell, [shellFlag, svc.watchBuild!], {\n cwd, env, detached: true, stdio: ['ignore', 'pipe', 'pipe'],\n });\n const outBuf = lineBuffer(line => this.log(svc.name, `[watch] ${line}`, colorIdx));\n const errBuf = lineBuffer(line => this.log(svc.name, `[watch] ${line}`, colorIdx));\n child.stdout?.on('data', (d: Buffer) => outBuf.push(d));\n child.stderr?.on('data', (d: Buffer) => errBuf.push(d));\n child.on('error', err => this.log(svc.name, `[watch] ❌ ${err.message}`, colorIdx));\n return child;\n }\n\n /** Create a state entry in 'crashed' status without spawning a process\n * (used when preBuild fails or pre-flight checks fail). */\n private recordCrashedState(svc: ServiceConfig, colorIdx: number): void {\n const prev = this.state.get(svc.name);\n this.state.set(svc.name, {\n svc, proc: null, pid: null,\n status: 'crashed', health: 'down',\n errors: prev?.errors ?? 0,\n restarts: prev?.restarts ?? 0,\n startedAt: null,\n intentionalStop: false,\n colorIdx,\n });\n this.events.onStateChange(svc.name, this.state.get(svc.name)!);\n }\n\n private log(name: string, text: string, colorIdx: number): void {\n this.events.onLog(name, text, colorIdx);\n }\n}\n","/** Buffered line splitter. Calls `onLine` for every newline-terminated chunk,\n * preserves leftover for the next push. `flush()` emits any remaining tail. */\nexport function lineBuffer(onLine: (line: string) => void) {\n let buf = '';\n return {\n push(chunk: Buffer) {\n buf += chunk.toString();\n let idx;\n while ((idx = buf.indexOf('\\n')) !== -1) {\n const line = buf.slice(0, idx).replace(/\\r$/, '');\n buf = buf.slice(idx + 1);\n if (line.length) onLine(line);\n }\n },\n flush() {\n if (buf.length) { onLine(buf); buf = ''; }\n },\n };\n}\n\n/** Accepts both '/foo/' (vim-style) and bare 'foo'. Case-insensitive by default. */\nexport function compileReadyPattern(pattern: string | undefined): RegExp | null {\n if (!pattern) return null;\n const slashed = /^\\/(.+)\\/([gimsuy]*)$/.exec(pattern);\n try {\n if (slashed) return new RegExp(slashed[1]!, slashed[2] || 'i');\n return new RegExp(pattern, 'i');\n } catch {\n return null;\n }\n}\n\n/** Extracts the value tokens of `--watch` / `--watch-path` / `--watch=X` / `--watch-path=X`\n * from a command's args list. Accepts both `--flag value` and `--flag=value` forms. */\nexport function extractWatchPaths(args: string[]): string[] {\n const watchFlags = new Set(['--watch', '--watch-path']);\n const out: string[] = [];\n for (let i = 0; i < args.length; i++) {\n const a = args[i]!;\n if (watchFlags.has(a)) {\n const v = args[i + 1];\n if (v && !v.startsWith('-')) { out.push(v); i++; }\n continue;\n }\n const eq = a.indexOf('=');\n if (eq > 0 && watchFlags.has(a.slice(0, eq))) {\n out.push(a.slice(eq + 1));\n }\n }\n return out;\n}\n\nexport const MAX_RESTARTS = 3;\nexport const BACKOFF_BASE_MS = 2000;\n","import type { ServiceConfig } from '../config/types.js';\nimport type { ProcessState, ProcessManagerEvents } from './types.js';\nimport type { Spawner } from './spawner.js';\nimport type { Lifecycle } from './lifecycle.js';\nimport { MAX_RESTARTS, BACKOFF_BASE_MS } from './internals.js';\n\ninterface RestarterOpts {\n state: Map<string, ProcessState>;\n events: ProcessManagerEvents;\n spawner: Spawner;\n lifecycle: Lifecycle;\n}\n\n/** Two responsibilities:\n * 1. Manual restart (`restart(name)`) — full stop + respawn, **resets** the\n * auto-restart counter so the user gets a fresh budget.\n * 2. Auto-restart on crash (`scheduleAutoRestart`) — exponential backoff,\n * capped at MAX_RESTARTS. Spawner invokes this in its close handler. */\nexport class Restarter {\n private readonly state: Map<string, ProcessState>;\n private readonly events: ProcessManagerEvents;\n private readonly spawner: Spawner;\n private readonly lifecycle: Lifecycle;\n\n constructor(opts: RestarterOpts) {\n this.state = opts.state;\n this.events = opts.events;\n this.spawner = opts.spawner;\n this.lifecycle = opts.lifecycle;\n }\n\n async restart(name: string): Promise<void> {\n const st = this.state.get(name);\n if (!st) return;\n this.lifecycle.stop(name);\n // Manual restart: reset auto-restart counter so user gets a fresh budget\n st.restarts = 0;\n const delay = st.proc ? 1500 : 100;\n await new Promise(r => setTimeout(r, delay));\n await this.spawner.start(st.svc, st.colorIdx, true);\n this.events.onLog(name, '🔄 manual restart', st.colorIdx);\n }\n\n scheduleAutoRestart(svc: ServiceConfig, state: ProcessState, colorIdx: number): void {\n if (state.restarts >= MAX_RESTARTS) {\n this.events.onLog(svc.name, '⛔ max restarts reached', colorIdx);\n return;\n }\n state.restarts++;\n const delay = BACKOFF_BASE_MS * Math.pow(2, state.restarts - 1);\n this.events.onLog(svc.name, `🔄 auto-restart ${state.restarts}/${MAX_RESTARTS} in ${delay}ms...`, colorIdx);\n setTimeout(() => void this.spawner.start(svc, colorIdx, true), delay);\n }\n}\n","import type { ProcessState, ProcessManagerEvents } from './types.js';\nimport { checkHealth, deriveHealth } from './health.js';\n\ninterface HealthPollerOpts {\n state: Map<string, ProcessState>;\n events: ProcessManagerEvents;\n}\n\n/** Runs one round of health probes across every service in `state`.\n * Suppresses probes during `healthCheck.startPeriod` grace window. */\nexport class HealthPoller {\n private readonly state: Map<string, ProcessState>;\n private readonly events: ProcessManagerEvents;\n\n constructor(opts: HealthPollerOpts) {\n this.state = opts.state;\n this.events = opts.events;\n }\n\n async checkAll(): Promise<void> {\n for (const [name, st] of this.state) {\n if (!st.pid || st.status === 'idle') {\n st.health = st.status === 'idle' ? 'idle' : 'down';\n continue;\n }\n // Grace period: suppress probes during the first N seconds after startedAt.\n // Keeps state.errors clean during slow boots (Angular cold-start, etc.).\n const startPeriodMs = (st.svc.healthCheck?.startPeriod ?? 0) * 1000;\n if (startPeriodMs > 0 && st.startedAt && Date.now() - st.startedAt < startPeriodMs) {\n continue; // status stays 'starting', health stays 'wait'\n }\n const isUp = await checkHealth(st.svc.port, st.svc.healthCheck);\n const prev = st.health;\n st.health = deriveHealth(isUp, st.status);\n if (st.health === 'up' && st.status === 'starting') st.status = 'running';\n if (prev !== st.health) this.events.onStateChange(name, st);\n }\n }\n}\n","import type { ChildProcess } from 'node:child_process';\nimport type { Platform } from '../platform/types.js';\nimport type { ProcessState } from './types.js';\n\ninterface LifecycleOpts {\n state: Map<string, ProcessState>;\n procs: Set<ChildProcess>;\n platform: Platform;\n}\n\n/** Owns the kill-tree, watchBuild teardown, and graceful cleanup with SIGKILL\n * fallback. Stateless beyond what's passed in via opts. */\nexport class Lifecycle {\n private readonly state: Map<string, ProcessState>;\n private readonly procs: Set<ChildProcess>;\n private readonly platform: Platform;\n\n constructor(opts: LifecycleOpts) {\n this.state = opts.state;\n this.procs = opts.procs;\n this.platform = opts.platform;\n }\n\n /** Manual / external stop of a single service. Marks `intentionalStop` so the\n * close handler doesn't auto-restart, kills the process tree, tears down the\n * side-car watchBuild process if any. */\n stop(name: string): void {\n const st = this.state.get(name);\n if (!st?.proc || !st.pid) return;\n st.intentionalStop = true;\n this.platform.killTree(st.pid);\n this.stopWatchProc(st);\n }\n\n /** Tears down the side-car `watchBuild` process for a service (if any) and\n * clears the reference. Safe to call repeatedly. */\n stopWatchProc(state: ProcessState): void {\n const wp = state.watchProc;\n if (!wp || !wp.pid) return;\n try { this.platform.killTree(wp.pid); } catch { /* already dead */ }\n state.watchProc = null;\n }\n\n /** Graceful shutdown of every spawned process. Waits `gracePeriodMs` (default\n * 3000) for clean exits, then SIGKILLs anything still alive. */\n async cleanup(opts: { gracePeriodMs?: number } = {}): Promise<void> {\n const grace = opts.gracePeriodMs ?? 3000;\n const procs = [...this.procs];\n if (!procs.length) return;\n\n for (const proc of procs) {\n const st = this.findStateByProc(proc);\n if (st) {\n st.intentionalStop = true;\n this.stopWatchProc(st);\n }\n if (proc.pid) this.platform.killTree(proc.pid);\n }\n // Any side-car watch processes whose service hasn't been seen above\n // (e.g. preBuild-failed services).\n for (const st of this.state.values()) this.stopWatchProc(st);\n\n const waits = procs.map(p =>\n p.exitCode !== null || p.signalCode !== null\n ? Promise.resolve()\n : new Promise<void>(resolve => p.once('close', () => resolve())),\n );\n\n let timedOut = false;\n await Promise.race([\n Promise.all(waits),\n new Promise<void>(resolve => setTimeout(() => { timedOut = true; resolve(); }, grace)),\n ]);\n\n if (timedOut) {\n for (const proc of procs) {\n if (proc.pid && proc.exitCode === null && proc.signalCode === null) {\n this.platform.killTree(proc.pid, 'SIGKILL');\n }\n }\n await Promise.race([\n Promise.all(waits),\n new Promise<void>(resolve => setTimeout(resolve, 1000)),\n ]);\n }\n }\n\n private findStateByProc(proc: ChildProcess): ProcessState | undefined {\n for (const st of this.state.values()) if (st.proc === proc) return st;\n return undefined;\n }\n}\n","import { existsSync, mkdirSync, renameSync, createWriteStream, type WriteStream } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { homedir } from 'node:os';\n\nexport interface LogSinkOpts {\n /** Project name used as a subdirectory under the log root. */\n projectName: string;\n /** Root directory (default: ~/.devup/logs). */\n rootDir?: string;\n /** Rotate the previous run's file to <svc>.log.prev on first write. Default: true. */\n rotateOnStart?: boolean;\n}\n\n/** Persist service logs to disk, one file per service, append-only.\n * On the first write for a service, rotates any previous <svc>.log to <svc>.log.prev. */\nexport class LogSink {\n private readonly dir: string;\n private readonly rotateOnStart: boolean;\n private readonly streams = new Map<string, WriteStream>();\n private readonly seen = new Set<string>();\n\n constructor(opts: LogSinkOpts) {\n const root = opts.rootDir ?? join(homedir(), '.devup', 'logs');\n this.dir = join(root, sanitize(opts.projectName));\n this.rotateOnStart = opts.rotateOnStart ?? true;\n mkdirSync(this.dir, { recursive: true });\n }\n\n /** Returns the file path for a service log (useful for tests / UI). */\n pathFor(svcName: string): string {\n return join(this.dir, `${sanitize(svcName)}.log`);\n }\n\n write(svcName: string, line: string): void {\n const stream = this.streamFor(svcName);\n stream.write(`${new Date().toISOString()} ${line}\\n`);\n }\n\n async close(): Promise<void> {\n const closes = [...this.streams.values()].map(\n s => new Promise<void>(r => s.end(() => r())),\n );\n this.streams.clear();\n this.seen.clear();\n await Promise.all(closes);\n }\n\n private streamFor(svcName: string): WriteStream {\n let s = this.streams.get(svcName);\n if (s) return s;\n const file = this.pathFor(svcName);\n if (this.rotateOnStart && !this.seen.has(svcName) && existsSync(file)) {\n try {\n mkdirSync(dirname(file), { recursive: true });\n renameSync(file, file + '.prev');\n } catch { /* best effort */ }\n }\n this.seen.add(svcName);\n s = createWriteStream(file, { flags: 'a' });\n s.on('error', () => { /* swallow — disk full / permission, etc. */ });\n this.streams.set(svcName, s);\n return s;\n }\n}\n\nfunction sanitize(name: string): string {\n return name.replace(/[^a-zA-Z0-9._-]+/g, '_').replace(/^_+|_+$/g, '') || 'devup';\n}\n","export class Broadcaster<T> {\n private readonly subs = new Set<(v: T) => void>();\n\n subscribe(fn: (v: T) => void): () => void {\n this.subs.add(fn);\n return () => this.subs.delete(fn);\n }\n\n emit(v: T): void {\n for (const fn of this.subs) {\n try { fn(v); } catch { /* subscriber errors must not kill the bus */ }\n }\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { join } from 'node:path';\nimport type { ExternalService } from '../config/types.js';\nimport type { Platform } from '../platform/types.js';\nimport { checkHealth } from './health.js';\n\nconst DEFAULT_START_TIMEOUT_S = 60;\n\nexport interface ExternalProc {\n svc: ExternalService;\n proc: ChildProcess;\n pid: number | null;\n}\n\nexport interface StartExternalsOpts {\n baseCwd: string;\n env: Record<string, string>;\n platform: Platform;\n onLog?: (svcName: string, msg: string) => void;\n}\n\nexport interface StartExternalsResult {\n procs: ExternalProc[];\n allHealthy: boolean;\n failed: string[];\n}\n\n/** Spawn each external sequentially; for those with healthCheck, wait until it passes\n * (up to startTimeout seconds) before moving on. Returns the spawned handles and a\n * failure summary the caller can act on. */\nexport async function startExternals(\n externals: ExternalService[],\n opts: StartExternalsOpts,\n): Promise<StartExternalsResult> {\n const procs: ExternalProc[] = [];\n const failed: string[] = [];\n\n for (const svc of externals) {\n const proc = spawnExternal(svc, opts);\n procs.push({ svc, proc, pid: proc.pid ?? null });\n\n if (!svc.healthCheck) {\n opts.onLog?.(svc.name, '✅ started (no healthCheck)');\n continue;\n }\n\n if (svc.healthCheck.type === 'tcp' && !svc.port) {\n opts.onLog?.(svc.name, '⚠ tcp healthCheck requires `port` — skipping wait');\n continue;\n }\n\n const timeoutMs = (svc.startTimeout ?? DEFAULT_START_TIMEOUT_S) * 1000;\n const ok = await waitHealthy(svc, timeoutMs);\n if (ok) {\n opts.onLog?.(svc.name, '✅ healthy');\n } else {\n opts.onLog?.(svc.name, `❌ never became healthy (timeout ${timeoutMs / 1000}s)`);\n failed.push(svc.name);\n }\n }\n\n return { procs, allHealthy: failed.length === 0, failed };\n}\n\n/** Kill the externals and run any `stopCmd`s. Best-effort, fire-and-forget for the stopCmds. */\nexport async function stopExternals(\n procs: ExternalProc[],\n platform: Platform,\n opts: { baseCwd: string; env: Record<string, string>; onLog?: (svc: string, msg: string) => void } = {} as any,\n): Promise<void> {\n for (const { svc, proc, pid } of procs) {\n try {\n if (pid) platform.killTree(pid);\n if (svc.stopCmd) {\n opts.onLog?.(svc.name, `🧹 ${svc.stopCmd}`);\n await new Promise<void>(resolve => {\n const isWin = process.platform === 'win32';\n const shell = isWin ? 'cmd.exe' : 'sh';\n const flag = isWin ? '/c' : '-c';\n const cwd = svc.cwd ? join(opts.baseCwd, svc.cwd) : opts.baseCwd;\n const env = { ...opts.env, ...(svc.extraEnv ?? {}) };\n const child = spawn(shell, [flag, svc.stopCmd!], { cwd, env, stdio: 'ignore' });\n child.on('close', () => resolve());\n child.on('error', () => resolve());\n // 10s hard cap so a hung docker stop doesn't block forever\n setTimeout(() => resolve(), 10_000);\n });\n }\n } catch { /* best-effort */ }\n void proc; // keep TS happy\n }\n}\n\nfunction spawnExternal(svc: ExternalService, opts: StartExternalsOpts): ChildProcess {\n const isWin = process.platform === 'win32';\n const shell = isWin ? 'cmd.exe' : 'sh';\n const flag = isWin ? '/c' : '-c';\n const cwd = svc.cwd ? join(opts.baseCwd, svc.cwd) : opts.baseCwd;\n const env = { ...opts.env, ...(svc.extraEnv ?? {}) };\n\n opts.onLog?.(svc.name, `🚀 ${svc.cmd}`);\n const child = spawn(shell, [flag, svc.cmd], {\n cwd, env, detached: true, stdio: ['ignore', 'pipe', 'pipe'],\n });\n child.stdout?.on('data', (d: Buffer) => opts.onLog?.(svc.name, d.toString().trimEnd()));\n child.stderr?.on('data', (d: Buffer) => opts.onLog?.(svc.name, d.toString().trimEnd()));\n child.on('error', err => opts.onLog?.(svc.name, `❌ spawn error: ${err.message}`));\n return child;\n}\n\nasync function waitHealthy(svc: ExternalService, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n const port = svc.port!;\n while (Date.now() < deadline) {\n if (await checkHealth(port, svc.healthCheck)) return true;\n await new Promise(r => setTimeout(r, 500));\n }\n return false;\n}\n","import net from 'node:net';\nimport { waitForPort } from '../process/health.js';\n\nexport interface LazyProxyOpts {\n listenPort: number;\n targetPort: number;\n timeoutMin: number;\n onDemandStart: () => Promise<void>;\n onIdleStop: () => void;\n isAlive: () => boolean;\n onLog?: (msg: string) => void;\n}\n\nexport interface LazyProxy {\n server: net.Server;\n resetTimer: () => void;\n destroy: () => void;\n}\n\nexport function createLazyProxy(opts: LazyProxyOpts): LazyProxy {\n const { listenPort, targetPort, timeoutMin, onDemandStart, onIdleStop, isAlive, onLog } = opts;\n let idleTimer: ReturnType<typeof setTimeout> | null = null;\n let lastActivity = Date.now();\n let starting = false;\n let serviceReady = false;\n let pendingConns: net.Socket[] = [];\n const activeConns = new Set<net.Socket>();\n\n function bumpActivity() {\n lastActivity = Date.now();\n }\n\n function scheduleIdleCheck() {\n if (idleTimer) clearTimeout(idleTimer);\n if (timeoutMin <= 0) return;\n const periodMs = timeoutMin * 60_000;\n idleTimer = setTimeout(() => {\n const elapsed = Date.now() - lastActivity;\n if (activeConns.size > 0 || elapsed < periodMs) {\n // Aún activa o tráfico reciente — re-agenda\n scheduleIdleCheck();\n return;\n }\n serviceReady = false;\n onLog?.(`💤 idle ${timeoutMin}min — stopping`);\n onIdleStop();\n }, periodMs);\n }\n\n function pipeToTarget(client: net.Socket) {\n const target = net.createConnection({ port: targetPort, host: '127.0.0.1', allowHalfOpen: true });\n activeConns.add(client);\n\n const cleanup = () => {\n activeConns.delete(client);\n bumpActivity();\n };\n\n target.on('error', () => { client.destroy(); cleanup(); });\n client.on('error', () => { target.destroy(); cleanup(); });\n client.on('close', cleanup);\n target.on('close', cleanup);\n\n target.on('connect', () => {\n target.on('data', (chunk) => { bumpActivity(); if (!client.destroyed) client.write(chunk); });\n client.on('data', (chunk) => { bumpActivity(); if (!target.destroyed) target.write(chunk); });\n target.on('end', () => { if (!client.destroyed) client.end(); });\n client.on('end', () => { if (!target.destroyed) target.end(); });\n });\n }\n\n async function handleConnection(client: net.Socket) {\n bumpActivity();\n client.on('error', () => {}); // Prevent uncaught ECONNRESET\n\n if (serviceReady && isAlive()) {\n pipeToTarget(client);\n return;\n }\n\n pendingConns.push(client);\n client.on('close', () => { pendingConns = pendingConns.filter(s => s !== client); });\n\n if (starting) return;\n starting = true;\n\n onLog?.('⚡ on-demand start');\n let ok = false;\n try {\n await onDemandStart();\n ok = await waitForPort(targetPort, { timeout: 45000, interval: 500 });\n if (ok) serviceReady = true;\n else onLog?.('⚠ timeout waiting for service');\n } catch (e: unknown) {\n onLog?.(`❌ start failed: ${(e as Error).message}`);\n }\n starting = false;\n\n const conns = pendingConns.splice(0);\n if (!ok) {\n for (const conn of conns) {\n if (!conn.destroyed) conn.destroy();\n }\n return;\n }\n for (const conn of conns) {\n if (!conn.destroyed) pipeToTarget(conn);\n }\n }\n\n const server = net.createServer({ allowHalfOpen: true }, socket => handleConnection(socket));\n server.listen(listenPort, '0.0.0.0');\n scheduleIdleCheck();\n\n return {\n server,\n resetTimer: bumpActivity,\n destroy: () => {\n if (idleTimer) clearTimeout(idleTimer);\n pendingConns.forEach(s => s.destroy());\n activeConns.forEach(s => s.destroy());\n server.close();\n },\n };\n}\n","import { watchFile, unwatchFile, type Stats } from 'node:fs';\nimport { loadConfig } from '../config/loader.js';\nimport { validateConfig, formatValidationErrors } from '../config/validator.js';\nimport { diffServices, summariseDiff } from '../config/diff.js';\nimport type { ProcessManager } from '../process/manager.js';\n\nexport interface ConfigWatchOpts {\n configPath: string;\n baseCwd: string;\n manager: ProcessManager;\n /** Receives status lines: success, validation errors, reload errors. */\n log: (msg: string) => void;\n}\n\n/** Re-loads the config, validates it, diffs against the running set, and\n * applies add/remove/restart at the service level. A failed validation\n * leaves the running set untouched. Pure (idempotent given the same\n * config file + manager state), so both the TUI hook and the daemon\n * can call it directly. */\nexport async function applyConfigChange(opts: ConfigWatchOpts): Promise<void> {\n const { configPath, baseCwd, manager, log } = opts;\n try {\n const nextCfg = await loadConfig(configPath);\n const errs = validateConfig(nextCfg, baseCwd);\n if (errs.length) {\n log(`⚠ config reload failed:\\n${formatValidationErrors(errs)}`);\n return;\n }\n const currentSvcs = [...manager.state.values()].map(s => s.svc);\n const diff = diffServices(currentSvcs, nextCfg.services);\n if (!diff.added.length && !diff.removed.length && !diff.changed.length) return;\n\n for (const name of diff.removed) {\n manager.stop(name);\n manager.state.delete(name);\n }\n let colorIdx = currentSvcs.length;\n for (const { next } of diff.changed) {\n const prev = manager.state.get(next.name);\n const ci = prev?.colorIdx ?? colorIdx++;\n manager.stop(next.name);\n // Brief pause so the previous process releases its port before the new one starts.\n await new Promise(r => setTimeout(r, 800));\n await manager.install(next, ci);\n await manager.start(next, ci, true);\n }\n for (const next of diff.added) {\n const ci = colorIdx++;\n await manager.install(next, ci);\n await manager.start(next, ci);\n }\n log(`🔁 config reloaded: ${summariseDiff(diff)}`);\n } catch (e: any) {\n log(`⚠ config reload error: ${e.message}`);\n }\n}\n\n/** Watch a config file and call applyConfigChange on each save, debounced\n * to 250 ms. Uses `fs.watchFile` (polling, 500 ms) rather than `fs.watch`\n * for cross-platform reliability — `fs.watch` on a single file is flaky\n * on macOS (FSEvents) and has its own quirks on Windows. Polling a single\n * file every 500 ms is negligible cost for a long-running daemon.\n * In-flight guard coalesces back-to-back saves. Returns a cleanup function. */\nexport function watchConfig(opts: ConfigWatchOpts): () => void {\n let debounceTimer: NodeJS.Timeout | null = null;\n let reloadInFlight = false;\n let reloadAgain = false;\n\n const trigger = async () => {\n if (reloadInFlight) { reloadAgain = true; return; }\n reloadInFlight = true;\n try {\n await applyConfigChange(opts);\n } finally {\n reloadInFlight = false;\n if (reloadAgain) { reloadAgain = false; void trigger(); }\n }\n };\n\n const listener = (curr: Stats, prev: Stats) => {\n // watchFile fires on every poll; skip when nothing actually changed.\n if (curr.mtimeMs === prev.mtimeMs && curr.size === prev.size) return;\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => void trigger(), 250);\n };\n\n watchFile(opts.configPath, { interval: 500 }, listener);\n\n return () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n unwatchFile(opts.configPath, listener);\n };\n}\n","import type { ServiceConfig } from './types.js';\n\nexport interface ServiceDiff {\n added: ServiceConfig[];\n removed: string[];\n changed: Array<{ next: ServiceConfig; prev: ServiceConfig }>;\n unchanged: string[];\n}\n\n/** Fields whose change requires a respawn. Anything else (icon, etc.) is metadata. */\nconst SPAWN_RELEVANT: (keyof ServiceConfig)[] = [\n 'cwd', 'cmd', 'args', 'port', 'phase', 'maxMem', 'preBuild', 'watchBuild',\n 'nodeArgs', 'extraEnv', 'healthCheck', 'readyPattern', 'errorPattern', 'type',\n];\n\nfunction hasSpawnRelevantChange(prev: ServiceConfig, next: ServiceConfig): boolean {\n for (const k of SPAWN_RELEVANT) {\n if (JSON.stringify(prev[k]) !== JSON.stringify(next[k])) return true;\n }\n return false;\n}\n\n/** Computes the set-difference between two service lists by name.\n * - added: in `next` but not in `prev`\n * - removed: in `prev` but not in `next`\n * - changed: in both but with a spawn-relevant field change\n * - unchanged: in both with identical spawn-relevant fields */\nexport function diffServices(prev: ServiceConfig[], next: ServiceConfig[]): ServiceDiff {\n const prevByName = new Map(prev.map(s => [s.name, s]));\n const nextByName = new Map(next.map(s => [s.name, s]));\n\n const added: ServiceConfig[] = [];\n const removed: string[] = [];\n const changed: Array<{ next: ServiceConfig; prev: ServiceConfig }> = [];\n const unchanged: string[] = [];\n\n for (const [name, p] of prevByName) {\n if (!nextByName.has(name)) { removed.push(name); continue; }\n const n = nextByName.get(name)!;\n if (hasSpawnRelevantChange(p, n)) changed.push({ prev: p, next: n });\n else unchanged.push(name);\n }\n for (const [name, n] of nextByName) {\n if (!prevByName.has(name)) added.push(n);\n }\n return { added, removed, changed, unchanged };\n}\n\n/** Short human-readable summary for the TUI banner. */\nexport function summariseDiff(d: ServiceDiff): string {\n const parts: string[] = [];\n if (d.added.length) parts.push(`+${d.added.length} added`);\n if (d.removed.length) parts.push(`-${d.removed.length} removed`);\n if (d.changed.length) parts.push(`~${d.changed.length} changed`);\n if (!parts.length) parts.push('no changes');\n return parts.join(', ');\n}\n","/** Find and resolve conflicts on devup-managed ports — i.e. some other\n * process is already listening on a port we want, so the spawn would\n * fail with EADDRINUSE.\n *\n * Resolution is offered as a pre-boot step in three flavours:\n * 1. `--kill-port-conflicts` flag → auto-kill, no prompt.\n * 2. Interactive TTY → list conflicts, ask for confirmation.\n * 3. Non-interactive (CI, piped) → fail with the list as instructions.\n *\n * Detection uses `lsof` on Linux/macOS. Windows support is intentionally\n * out of scope for v1 (daemon mode itself doesn't run on Windows yet).\n * When `lsof` is unavailable the conflict is reported without a holder\n * (the user gets the port number but not the PID). */\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { setTimeout as sleep } from 'node:timers/promises';\nimport { isPortBindable } from './health.js';\nimport type { ServiceConfig } from '../config/types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface PortHolder {\n pid: number;\n command: string;\n}\n\nexport interface PortConflict {\n service: string;\n port: number;\n holder: PortHolder | null;\n}\n\nconst isUnix = process.platform === 'linux' || process.platform === 'darwin';\n\n/** Run `lsof` to find what's listening on a port. Returns the first matching\n * PID + command, or null if nothing's there (or lsof isn't available). */\nexport async function findPortHolder(port: number): Promise<PortHolder | null> {\n if (!isUnix) return null;\n try {\n // -nP no DNS / port-name resolution (fast)\n // -iTCP:N restrict to TCP port N\n // -sTCP:LISTEN only LISTEN state (skip established/closed)\n // -F pcn output: pid + command, machine-readable\n const { stdout } = await execAsync(`lsof -nP -iTCP:${port} -sTCP:LISTEN -F pcn`);\n return parseLsof(stdout);\n } catch {\n // lsof exits non-zero when nothing matches OR when lsof is missing.\n return null;\n }\n}\n\nfunction parseLsof(stdout: string): PortHolder | null {\n // -F output: groups of fields, one per line, prefixed by a tag char.\n // p<pid> c<command> n<name> …\n let pid: number | null = null;\n let cmd = '';\n for (const line of stdout.split('\\n')) {\n if (!line) continue;\n const tag = line[0];\n const value = line.slice(1);\n if (tag === 'p') {\n // New record. Emit the previous one if complete.\n if (pid != null) return { pid, command: cmd || 'unknown' };\n pid = Number(value);\n } else if (tag === 'c') {\n cmd = value;\n }\n }\n if (pid != null) return { pid, command: cmd || 'unknown' };\n return null;\n}\n\n/** Scan every configured service for port conflicts. APIs and webs both —\n * pre-boot we want to surface any conflict the user will hit during spawn,\n * regardless of service type. Web dev servers (Vite, ng serve, etc.) handle\n * port-collision retry at runtime, but pre-boot the user typically wants to\n * reclaim THE configured port, not let the dev server roll it. */\nexport async function scanPortConflicts(services: ServiceConfig[]): Promise<PortConflict[]> {\n const conflicts: PortConflict[] = [];\n for (const svc of services) {\n const bindable = await isPortBindable(svc.port);\n if (bindable) continue;\n const holder = await findPortHolder(svc.port);\n conflicts.push({ service: svc.name, port: svc.port, holder });\n }\n return conflicts;\n}\n\n/** SIGTERM with grace, falling back to SIGKILL after `graceMs`. */\nexport async function killHolder(pid: number, graceMs = 3000): Promise<boolean> {\n try { process.kill(pid, 'SIGTERM'); } catch { return false; }\n const deadline = Date.now() + graceMs;\n while (Date.now() < deadline) {\n if (!pidAlive(pid)) return true;\n await sleep(100);\n }\n try { process.kill(pid, 'SIGKILL'); } catch { /* already dead */ }\n // Final check: did SIGKILL land?\n await sleep(100);\n return !pidAlive(pid);\n}\n\nfunction pidAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\nexport interface ResolveOpts {\n autoKill: boolean;\n out: (line: string) => void;\n /** Returns true if user confirms, false otherwise. Skipped when autoKill or\n * when stdin is not a TTY. */\n prompt?: () => Promise<boolean>;\n /** If stdin is not a TTY and autoKill is false, resolution fails by default.\n * Tests pass `isInteractive: true` with a mocked prompt to bypass. */\n isInteractive?: boolean;\n}\n\n/** Returns true if all conflicts were resolved (no holders left), false if the\n * user declined or some kills failed. */\nexport async function resolvePortConflicts(\n conflicts: PortConflict[],\n opts: ResolveOpts,\n): Promise<boolean> {\n if (!conflicts.length) return true;\n\n const { autoKill, out, prompt, isInteractive = process.stdin.isTTY ?? false } = opts;\n\n // Render the conflict list.\n out('⚠ Port conflicts detected on the following services:');\n out('');\n const maxName = Math.max(...conflicts.map(c => c.service.length), 8);\n for (const c of conflicts) {\n const holder = c.holder\n ? `pid=${c.holder.pid} process=${c.holder.command}`\n : `(unable to identify holder${isUnix ? '' : ' — Windows not supported'})`;\n out(` :${String(c.port).padEnd(6)} ${c.service.padEnd(maxName)} ${holder}`);\n }\n out('');\n\n if (autoKill) {\n return await killAll(conflicts, out);\n }\n\n if (!isInteractive || !prompt) {\n out('Re-run with --kill-port-conflicts to take them over, or stop them yourself.');\n return false;\n }\n\n const confirmed = await prompt();\n if (!confirmed) {\n out('Aborted — no processes killed.');\n return false;\n }\n return await killAll(conflicts, out);\n}\n\nasync function killAll(conflicts: PortConflict[], out: (l: string) => void): Promise<boolean> {\n let allOk = true;\n for (const c of conflicts) {\n if (!c.holder) {\n out(`✗ :${c.port} ${c.service}: holder unknown, cannot kill — skipped`);\n allOk = false;\n continue;\n }\n const ok = await killHolder(c.holder.pid);\n if (ok) {\n out(`✓ :${c.port} ${c.service}: killed pid=${c.holder.pid}`);\n } else {\n out(`✗ :${c.port} ${c.service}: pid=${c.holder.pid} survived SIGKILL`);\n allOk = false;\n }\n }\n return allOk;\n}\n","import type { Platform } from './types.js';\n\nexport async function detectPlatform(): Promise<Platform> {\n switch (process.platform) {\n case 'linux': {\n const { LinuxPlatform } = await import('./linux.js');\n return new LinuxPlatform();\n }\n case 'darwin': {\n const { DarwinPlatform } = await import('./darwin.js');\n return new DarwinPlatform();\n }\n case 'win32': {\n const { Win32Platform } = await import('./win32.js');\n return new Win32Platform();\n }\n default:\n throw new Error(`Unsupported platform: ${process.platform}`);\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from './types.js';\n\nconst EMPTY_CONFIG = 'http:\\n routers: {}\\n services: {}\\n';\n\nexport class TraefikProvider implements ProxyConfigProvider {\n readonly name = 'traefik';\n\n generate(services: Map<string, ServiceState>, opts: ProxyOpts): string {\n const routers: string[] = [];\n const svcs: string[] = [];\n\n for (const [name, st] of services) {\n if (st.health !== 'up') continue;\n const sub = opts.routes[name];\n if (sub === undefined) continue;\n\n const rule = sub ? `Host(\\`${sub}.${opts.domain}\\`)` : `Host(\\`${opts.domain}\\`)`;\n const safe = name.replace(/[^a-z0-9-]/g, '-');\n const port = st.realPort ?? st.port;\n\n let router = ` ${safe}:\\n rule: \"${rule}\"\\n service: ${safe}\\n entryPoints:\\n - ${opts.entrypoint}`;\n if (opts.tls) router += `\\n tls:\\n certResolver: le`;\n routers.push(router);\n\n svcs.push(` ${safe}:\\n loadBalancer:\\n servers:\\n - url: \"http://${opts.host}:${port}\"`);\n }\n\n if (!routers.length) return EMPTY_CONFIG;\n return `http:\\n routers:\\n${routers.join('\\n')}\\n services:\\n${svcs.join('\\n')}\\n`;\n }\n\n write(content: string, opts: ProxyOpts): void {\n const dir = dirname(opts.confPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(opts.confPath, content);\n }\n\n clear(opts: ProxyOpts): void {\n this.write(EMPTY_CONFIG, opts);\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from './types.js';\n\nconst EMPTY_CONFIG = '# devup: no healthy services\\n';\n\n/** Generates an Nginx server-block config file.\n * Drop it into /etc/nginx/conf.d/ or include from your main nginx.conf. */\nexport class NginxProvider implements ProxyConfigProvider {\n readonly name = 'nginx';\n\n generate(services: Map<string, ServiceState>, opts: ProxyOpts): string {\n const blocks: string[] = [];\n\n for (const [name, st] of services) {\n if (st.health !== 'up') continue;\n const sub = opts.routes[name];\n if (sub === undefined) continue;\n\n const serverName = sub ? `${sub}.${opts.domain}` : opts.domain;\n const port = st.realPort ?? st.port;\n const listen = opts.tls ? '443 ssl' : '80';\n\n const tlsBlock = opts.tls\n ? ` ssl_certificate /etc/nginx/certs/${serverName}.crt;\\n` +\n ` ssl_certificate_key /etc/nginx/certs/${serverName}.key;\\n`\n : '';\n\n blocks.push(\n `server {\\n` +\n ` listen ${listen};\\n` +\n ` server_name ${serverName};\\n` +\n tlsBlock +\n ` location / {\\n` +\n ` proxy_pass http://${opts.host}:${port};\\n` +\n ` proxy_set_header Host $host;\\n` +\n ` proxy_set_header X-Real-IP $remote_addr;\\n` +\n ` proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\\n` +\n ` proxy_set_header X-Forwarded-Proto $scheme;\\n` +\n ` proxy_http_version 1.1;\\n` +\n ` proxy_set_header Upgrade $http_upgrade;\\n` +\n ` proxy_set_header Connection \"upgrade\";\\n` +\n ` }\\n` +\n `}`,\n );\n }\n\n if (!blocks.length) return EMPTY_CONFIG;\n return blocks.join('\\n\\n') + '\\n';\n }\n\n write(content: string, opts: ProxyOpts): void {\n const dir = dirname(opts.confPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(opts.confPath, content);\n }\n\n clear(opts: ProxyOpts): void {\n this.write(EMPTY_CONFIG, opts);\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from './types.js';\n\nconst EMPTY_CONFIG = '# devup: no healthy services\\n';\n\n/** Generates a Caddyfile.\n * Tip: point Caddy at it with `caddy run --config <path> --adapter caddyfile` or include it. */\nexport class CaddyProvider implements ProxyConfigProvider {\n readonly name = 'caddy';\n\n generate(services: Map<string, ServiceState>, opts: ProxyOpts): string {\n const blocks: string[] = [];\n\n for (const [name, st] of services) {\n if (st.health !== 'up') continue;\n const sub = opts.routes[name];\n if (sub === undefined) continue;\n\n const host = sub ? `${sub}.${opts.domain}` : opts.domain;\n const port = st.realPort ?? st.port;\n const siteAddr = opts.tls ? host : `http://${host}`;\n\n blocks.push(\n `${siteAddr} {\\n` +\n ` reverse_proxy ${opts.host}:${port}\\n` +\n `}`,\n );\n }\n\n if (!blocks.length) return EMPTY_CONFIG;\n return blocks.join('\\n\\n') + '\\n';\n }\n\n write(content: string, opts: ProxyOpts): void {\n const dir = dirname(opts.confPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(opts.confPath, content);\n }\n\n clear(opts: ProxyOpts): void {\n this.write(EMPTY_CONFIG, opts);\n }\n}\n","import type { ProxyConfigProvider } from './types.js';\nimport { TraefikProvider } from './traefik.js';\nimport { NginxProvider } from './nginx.js';\nimport { CaddyProvider } from './caddy.js';\n\nconst providers: Record<string, () => ProxyConfigProvider> = {\n traefik: () => new TraefikProvider(),\n nginx: () => new NginxProvider(),\n caddy: () => new CaddyProvider(),\n};\n\nexport function detectProxyProvider(name: string): ProxyConfigProvider {\n const factory = providers[name];\n if (!factory) {\n const available = Object.keys(providers).join(', ');\n throw new Error(`Unknown proxy provider: \"${name}\". Available: ${available}`);\n }\n return factory();\n}\n","import React, { useCallback, useRef } from 'react';\nimport { Box, Text } from 'ink';\nimport type { Platform } from '../platform/types.js';\nimport type { DevStackConfig, ServiceConfig } from '../config/types.js';\nimport type { CliArgs } from '../config/cli.js';\nimport type { ProxyConfigProvider, ProxyOpts } from '../proxy-config/types.js';\nimport type { LogSink } from '../process/log-sink.js';\nimport { useProcessManager } from './hooks/useProcessManager.js';\nimport { useKeyBindings } from './hooks/useKeyBindings.js';\nimport { useProxySync } from './hooks/useProxySync.js';\nimport { useTerminalSize } from './hooks/useTerminalSize.js';\nimport { useLogsPause } from './hooks/useLogsPause.js';\nimport { useControlPlane } from './hooks/useControlPlane.js';\nimport { useHotReload } from './hooks/useHotReload.js';\nimport { useContextualTips } from './hooks/useContextualTips.js';\nimport { useBootSequence } from './hooks/useBootSequence.js';\nimport { LogsPanel } from './LogsPanel.js';\nimport { StatsPanel } from './StatsPanel.js';\nimport { StatusBar } from './StatusBar.js';\nimport { ServiceList } from './ServiceList.js';\nimport { SearchInput } from './SearchInput.js';\nimport type { LazyProxy } from '../lazy/proxy.js';\nimport { stopExternals, type ExternalProc } from '../process/external.js';\n\n/** Builds the URL to open in the browser when the user picks a service.\n * Honors the proxy + TLS settings: if --proxy is active and the service has\n * a route, opens https://<sub>.<domain>; otherwise falls back to http://localhost:<port>. */\nexport function buildServiceUrl(\n name: string,\n port: number,\n proxyActive: boolean,\n proxyOpts: ProxyOpts | null,\n): string {\n if (proxyActive && proxyOpts) {\n const sub = proxyOpts.routes[name];\n if (sub !== undefined) {\n const host = sub ? `${sub}.${proxyOpts.domain}` : proxyOpts.domain;\n const scheme = proxyOpts.tls ? 'https' : 'http';\n return `${scheme}://${host}`;\n }\n }\n return `http://localhost:${port}`;\n}\n\ninterface Props {\n config: DevStackConfig;\n services: ServiceConfig[];\n cliArgs: CliArgs;\n platform: Platform;\n env: Record<string, string>;\n baseCwd: string;\n proxyProvider: ProxyConfigProvider | null;\n proxyOpts: ProxyOpts | null;\n logSink: LogSink | null;\n}\n\nexport function App({ config, services, cliArgs, platform, env, baseCwd, proxyProvider, proxyOpts, logSink }: Props) {\n const rows = useTerminalSize();\n const logsHeight = Math.floor(rows * 0.65);\n const statsHeight = rows - logsHeight - 2; // 2 for header + statusbar\n const maxNameLen = Math.max(...services.map(s => s.name.length), 10);\n\n const pm = useProcessManager(platform, baseCwd, env, logSink);\n const lazyProxies = useRef<Map<string, LazyProxy>>(new Map());\n const externals = useRef<ExternalProc[]>([]);\n\n const kb = useKeyBindings({\n onQuit: () => { void shutdown(); },\n onClearLogs: pm.clearLogs,\n onToggleProxy: () => {},\n });\n\n const proxyCtx = proxyProvider && proxyOpts ? { provider: proxyProvider, opts: proxyOpts } : null;\n const socketServer = useControlPlane(pm.manager, config.name, logSink, pm.pushLog, pm.logBus, pm.stateBus, platform, proxyCtx, config.profiles ?? {});\n\n const shutdown = useCallback(async () => {\n lazyProxies.current.forEach(p => p.destroy());\n await socketServer.current?.close();\n await pm.cleanup();\n if (externals.current.length) {\n await stopExternals(externals.current, platform, {\n baseCwd, env,\n onLog: (svc, msg) => pm.pushLog(`ext:${svc}`, msg, 12),\n });\n externals.current = [];\n }\n await logSink?.close();\n process.exit(0);\n }, [pm, logSink, platform, baseCwd, env, socketServer]);\n\n useHotReload(pm.manager, cliArgs, baseCwd, pm.pushLog);\n useLogsPause(pm.setPaused, kb.logsPaused, kb.logsScrollOffset);\n const activeTip = useContextualTips(pm.logs.length, !!kb.searchTerm, !!kb.logFilter, pm.states);\n useProxySync(proxyProvider, proxyOpts, pm.states, kb.proxyEnabled);\n useBootSequence(pm.manager, config, services, cliArgs, platform, env, baseCwd,\n { lazyProxies, externals }, pm.pushLog);\n\n const handleFilterSelect = useCallback((name: string) => kb.setFilter(name), [kb]);\n const handleRestartSelect = useCallback((name: string) => { pm.restart(name); kb.setModal('none'); }, [pm, kb]);\n const handleOpenSelect = useCallback((name: string) => {\n const st = pm.states.get(name);\n if (st) {\n const url = buildServiceUrl(name, st.svc.port, cliArgs.proxy, proxyOpts);\n platform.openBrowser(url);\n }\n kb.setModal('none');\n }, [pm, platform, kb, cliArgs.proxy, proxyOpts]);\n\n const icon = config.icon ?? '📦';\n const modeLabel = cliArgs.lazy && config.lazy ? 'lazy' : 'normal';\n\n return (\n <Box flexDirection=\"column\" height={rows}>\n <Box>\n <Text bold color=\"cyan\"> {icon} {config.name} — devup — {services.length} services ({modeLabel}) </Text>\n {activeTip && <Text dimColor> · {activeTip}</Text>}\n </Box>\n\n <LogsPanel\n logs={pm.logs} filter={kb.logFilter} searchTerm={kb.searchTerm}\n paused={kb.logsPaused} showTimestamps={kb.showTimestamps}\n maxNameLen={maxNameLen} height={logsHeight} focused={kb.panel === 'logs'}\n scrollOffset={kb.logsScrollOffset} resetScroll={kb.resetLogsScroll}\n levelFilter={kb.levelFilter}\n filteredColorIdx={kb.logFilter ? (pm.states.get(kb.logFilter)?.colorIdx ?? null) : null}\n />\n\n <StatsPanel\n states={pm.states} stats={pm.stats} sortMode={kb.sortMode}\n maxNameLen={maxNameLen} height={statsHeight} focused={kb.panel === 'stats'}\n scrollOffset={kb.statsScrollOffset} resetScroll={kb.resetStatsScroll}\n verbose={kb.verboseStats}\n />\n\n {kb.modal === 'filter' && (\n <ServiceList title=\"Filter by service\" services={pm.states} onSelect={handleFilterSelect} onClose={() => kb.setModal('none')} />\n )}\n {kb.modal === 'restart' && (\n <ServiceList title=\"Restart service\" services={pm.states} onSelect={handleRestartSelect} onClose={() => kb.setModal('none')} />\n )}\n {kb.modal === 'open' && (\n <ServiceList title=\"Open in browser\" services={pm.states} onSelect={handleOpenSelect} onClose={() => kb.setModal('none')} filterType=\"web\" />\n )}\n {kb.modal === 'search' && (\n <SearchInput onSubmit={kb.setSearch} onClose={() => kb.setModal('none')} />\n )}\n\n <StatusBar />\n </Box>\n );\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { ProcessManager } from '../../process/manager.js';\nimport type { ProcessState } from '../../process/types.js';\nimport type { Platform } from '../../platform/types.js';\nimport type { ServiceConfig } from '../../config/types.js';\nimport { calcCpuPercent, detectLogLevel, type LogLevel } from '../../utils.js';\nimport { LogSink } from '../../process/log-sink.js';\nimport { Broadcaster } from '../../utils/broadcaster.js';\n\nexport interface LogEntry {\n svcName: string;\n text: string;\n colorIdx: number;\n ts: number;\n level: LogLevel;\n}\n\nexport interface ServiceStats {\n cpu: string;\n mem: string;\n}\n\nexport function useProcessManager(\n platform: Platform,\n baseCwd: string,\n env: Record<string, string>,\n logSink: LogSink | null = null,\n) {\n const [states, setStates] = useState<Map<string, ProcessState>>(new Map());\n const [logs, setLogs] = useState<LogEntry[]>([]);\n const [stats, setStats] = useState<Map<string, ServiceStats>>(new Map());\n const mgrRef = useRef<ProcessManager | null>(null);\n const prevCpu = useRef<Map<string, { time: number; cpu: number }>>(new Map());\n const pausedRef = useRef(false);\n const pendingLogsRef = useRef<LogEntry[]>([]);\n const sinkRef = useRef<LogSink | null>(logSink);\n sinkRef.current = logSink;\n\n // Stable broadcaster instances — control plane subscribers tap into these.\n const logBus = useRef(new Broadcaster<{ svc: string; text: string }>());\n const stateBus = useRef(new Broadcaster<{ name: string; state: ProcessState }>());\n\n useEffect(() => {\n const mgr = new ProcessManager({\n baseCwd, env, platform,\n events: {\n onLog: (svcName, text, colorIdx) => {\n sinkRef.current?.write(svcName, text);\n logBus.current.emit({ svc: svcName, text });\n const entry: LogEntry = { svcName, text, colorIdx, ts: Date.now(), level: detectLogLevel(text) };\n if (pausedRef.current) {\n pendingLogsRef.current.push(entry);\n if (pendingLogsRef.current.length > 5000) {\n pendingLogsRef.current = pendingLogsRef.current.slice(-5000);\n }\n return;\n }\n setLogs(prev => {\n const next = prev.concat(entry);\n return next.length > 5000 ? next.slice(-5000) : next;\n });\n },\n onStateChange: (name, state) => {\n stateBus.current.emit({ name, state });\n setStates(new Map(mgr.state));\n },\n },\n });\n mgrRef.current = mgr;\n return () => { mgr.cleanup(); };\n }, [baseCwd, env, platform]);\n\n // Health + stats polling\n useEffect(() => {\n const id = setInterval(async () => {\n const mgr = mgrRef.current;\n if (!mgr) return;\n await mgr.checkAllHealth();\n setStates(new Map(mgr.state));\n\n const pids: number[] = [];\n const pidMap = new Map<number, string>();\n for (const [name, st] of mgr.state) {\n if (st.pid) { pids.push(st.pid); pidMap.set(st.pid, name); }\n }\n if (pids.length) {\n const raw = await platform.getProcessStats(pids);\n const next = new Map<string, ServiceStats>();\n for (const [pid, data] of raw) {\n const name = pidMap.get(pid);\n if (!name) continue;\n const prev = prevCpu.current.get(name) ?? { time: Date.now(), cpu: 0 };\n const cpuPct = calcCpuPercent(data.cpuSeconds, prev.cpu, prev.time);\n prevCpu.current.set(name, { time: Date.now(), cpu: data.cpuSeconds });\n next.set(name, { cpu: cpuPct.toFixed(1) + '%', mem: (data.rss / 1024).toFixed(1) + ' MB' });\n }\n setStats(next);\n }\n }, 3000);\n return () => clearInterval(id);\n }, [platform]);\n\n const mgr = mgrRef.current;\n\n const clearLogs = useCallback(() => { pendingLogsRef.current = []; setLogs([]); }, []);\n\n /** Push a log line not tied to a ProcessManager-managed service (e.g. externals). */\n const pushLog = useCallback((svcName: string, text: string, colorIdx = 0) => {\n sinkRef.current?.write(svcName, text);\n logBus.current.emit({ svc: svcName, text });\n const entry: LogEntry = { svcName, text, colorIdx, ts: Date.now(), level: detectLogLevel(text) };\n if (pausedRef.current) {\n pendingLogsRef.current.push(entry);\n if (pendingLogsRef.current.length > 5000) {\n pendingLogsRef.current = pendingLogsRef.current.slice(-5000);\n }\n return;\n }\n setLogs(prev => {\n const next = prev.concat(entry);\n return next.length > 5000 ? next.slice(-5000) : next;\n });\n }, []);\n\n const setPaused = useCallback((paused: boolean) => {\n pausedRef.current = paused;\n if (!paused && pendingLogsRef.current.length) {\n const flush = pendingLogsRef.current;\n pendingLogsRef.current = [];\n setLogs(prev => {\n const next = prev.concat(flush);\n return next.length > 5000 ? next.slice(-5000) : next;\n });\n }\n }, []);\n\n return {\n states, logs, stats,\n start: useCallback((svc: ServiceConfig, colorIdx: number) => mgr?.start(svc, colorIdx), [mgr]),\n stop: useCallback((name: string) => mgr?.stop(name), [mgr]),\n restart: useCallback((name: string) => mgr?.restart(name), [mgr]),\n install: useCallback((svc: ServiceConfig, colorIdx: number) => mgr?.install(svc, colorIdx), [mgr]),\n cleanup: useCallback(() => mgr?.cleanup(), [mgr]),\n clearLogs,\n setPaused,\n pushLog,\n manager: mgr,\n logBus: logBus.current,\n stateBus: stateBus.current,\n };\n}\n","import { useInput } from 'ink';\nimport React, { useState, useCallback } from 'react';\n\nexport type Modal = 'none' | 'filter' | 'restart' | 'open' | 'search';\nexport type Panel = 'logs' | 'stats';\n\nexport type LevelFilter = 'all' | 'error' | 'warn';\n\nexport interface KeyState {\n panel: Panel;\n modal: Modal;\n logFilter: string | null;\n searchTerm: string | null;\n logsPaused: boolean;\n showTimestamps: boolean;\n sortIdx: number;\n proxyEnabled: boolean;\n logsScrollOffset: number;\n statsScrollOffset: number;\n levelFilter: LevelFilter;\n verboseStats: boolean;\n}\n\nconst SORT_MODES = ['name', 'mem', 'errors'] as const;\n\n// delta < 0 = mover vista hacia arriba; delta > 0 = hacia abajo.\n// Para logs el offset crece hacia atrás (más viejo), para stats crece hacia abajo (siguientes filas).\nfunction scrollBy(setState: React.Dispatch<React.SetStateAction<KeyState>>, delta: number) {\n setState(s => {\n if (s.panel === 'logs') {\n // up visual → más viejas → bottomOffset + |delta|\n const next = s.logsScrollOffset - delta;\n return { ...s, logsScrollOffset: Math.max(0, next) };\n }\n const next = s.statsScrollOffset + delta;\n return { ...s, statsScrollOffset: Math.max(0, next) };\n });\n}\n\nfunction scrollTo(setState: React.Dispatch<React.SetStateAction<KeyState>>, target: 'top' | 'bottom') {\n setState(s => {\n if (s.panel === 'logs') {\n // top visual = línea más vieja = bottomOffset máximo\n return { ...s, logsScrollOffset: target === 'top' ? Number.MAX_SAFE_INTEGER : 0 };\n }\n return { ...s, statsScrollOffset: target === 'top' ? 0 : Number.MAX_SAFE_INTEGER };\n });\n}\n\nexport function useKeyBindings(opts: {\n onQuit: () => void;\n onClearLogs: () => void;\n onToggleProxy: () => void;\n}) {\n const [state, setState] = useState<KeyState>({\n panel: 'logs', modal: 'none', logFilter: null, searchTerm: null,\n logsPaused: false, showTimestamps: false, sortIdx: 0, proxyEnabled: false,\n logsScrollOffset: 0, statsScrollOffset: 0, levelFilter: 'all', verboseStats: false,\n });\n\n const LEVEL_CYCLE: LevelFilter[] = ['all', 'error', 'warn'];\n\n const setModal = useCallback((modal: Modal) => setState(s => ({ ...s, modal })), []);\n const setFilter = useCallback((f: string | null) => setState(s => ({ ...s, logFilter: f, modal: 'none' })), []);\n const setSearch = useCallback((t: string | null) => setState(s => ({ ...s, searchTerm: t, modal: 'none' })), []);\n\n const isActive = process.stdin.isTTY ?? false;\n\n useInput((input, key) => {\n if (state.modal !== 'none') return;\n\n if (input === 'q' || (key.ctrl && input === 'c')) opts.onQuit();\n // ── Scroll (ctrl + tecla evaluado primero para no chocar con letras simples) ──\n else if (key.ctrl && input === 'a') scrollTo(setState, 'top');\n else if (key.ctrl && input === 'e') scrollTo(setState, 'bottom');\n else if (key.ctrl && input === 'b') scrollBy(setState, -10); // PgUp\n else if (key.ctrl && input === 'f') scrollBy(setState, +10); // PgDn\n else if (key.upArrow) scrollBy(setState, -1);\n else if (key.downArrow) scrollBy(setState, +1);\n else if (input === '[') scrollBy(setState, -10);\n else if (input === ']') scrollBy(setState, +10);\n // ── Acciones ──\n else if (input === 'c') opts.onClearLogs();\n else if (key.tab) setState(s => ({ ...s, panel: s.panel === 'logs' ? 'stats' : 'logs' }));\n else if (input === 'f') setModal('filter');\n else if (input === 'r') setModal('restart');\n else if (input === 'o') setModal('open');\n else if (input === '/') setModal('search');\n else if (input === 'a') setState(s => ({ ...s, logFilter: null, searchTerm: null, levelFilter: 'all' }));\n else if (input === 'p') setState(s => ({ ...s, logsPaused: !s.logsPaused }));\n else if (input === 't') setState(s => ({ ...s, showTimestamps: !s.showTimestamps }));\n else if (input === 's') setState(s => ({ ...s, sortIdx: (s.sortIdx + 1) % SORT_MODES.length }));\n else if (input === 'T') { opts.onToggleProxy(); setState(s => ({ ...s, proxyEnabled: !s.proxyEnabled })); }\n else if (input === 'L') setState(s => ({ ...s, levelFilter: LEVEL_CYCLE[(LEVEL_CYCLE.indexOf(s.levelFilter) + 1) % LEVEL_CYCLE.length]! }));\n else if (input === 'v') setState(s => ({ ...s, verboseStats: !s.verboseStats }));\n }, { isActive });\n\n return { \n ...state, \n setModal, \n setFilter, \n setSearch, \n sortMode: SORT_MODES[state.sortIdx]!,\n // Funciones para resetear el scroll cuando cambia el contenido\n resetLogsScroll: useCallback(() => setState(s => ({ ...s, logsScrollOffset: 0 })), []),\n resetStatsScroll: useCallback(() => setState(s => ({ ...s, statsScrollOffset: 0 })), []),\n };\n}\n","import { useEffect, useRef } from 'react';\nimport type { ProxyConfigProvider, ProxyOpts, ServiceState } from '../../proxy-config/types.js';\nimport type { ProcessState } from '../../process/types.js';\n\nexport function useProxySync(\n provider: ProxyConfigProvider | null,\n opts: ProxyOpts | null,\n states: Map<string, ProcessState>,\n enabled: boolean,\n) {\n const statesRef = useRef(states);\n const lastContentRef = useRef<string | null>(null);\n statesRef.current = states;\n\n useEffect(() => {\n if (!provider || !opts || !enabled) return;\n\n const sync = () => {\n const svcStates = new Map<string, ServiceState>();\n for (const [name, st] of statesRef.current) {\n svcStates.set(name, { port: st.svc.port, health: st.health, realPort: (st.svc as any).realPort });\n }\n const content = provider.generate(svcStates, opts);\n if (content === lastContentRef.current) return;\n lastContentRef.current = content;\n provider.write(content, opts);\n };\n\n sync();\n const id = setInterval(sync, 3000);\n return () => {\n clearInterval(id);\n lastContentRef.current = null;\n };\n }, [provider, opts, enabled]);\n}\n","import { useEffect, useState } from 'react';\nimport { useStdout } from 'ink';\n\n/** Returns the current terminal row count, re-rendering on resize.\n * Falls back to 40 when stdout isn't available (non-TTY mode). */\nexport function useTerminalSize(): number {\n const { stdout } = useStdout();\n const [rows, setRows] = useState(stdout?.rows ?? 40);\n useEffect(() => {\n if (!stdout) return;\n const onResize = () => setRows(stdout.rows ?? 40);\n stdout.on('resize', onResize);\n return () => { stdout.off('resize', onResize); };\n }, [stdout]);\n return rows;\n}\n","import { useEffect } from 'react';\n\n/** Couples the keyboard pause state (explicit `p` toggle OR auto-pause when\n * scrolled up) with the process manager's logs sink. */\nexport function useLogsPause(\n setPaused: (paused: boolean) => void,\n logsPaused: boolean,\n logsScrollOffset: number,\n): void {\n useEffect(() => {\n setPaused(logsPaused || logsScrollOffset > 0);\n }, [logsPaused, logsScrollOffset, setPaused]);\n}\n","import { useEffect, useRef } from 'react';\nimport { createInterface } from 'node:readline';\nimport { createReadStream, existsSync } from 'node:fs';\nimport { totalmem, freemem, cpus } from 'node:os';\nimport type { ProcessManager } from '../../process/manager.js';\nimport type { LogSink } from '../../process/log-sink.js';\nimport type { Broadcaster } from '../../utils/broadcaster.js';\nimport type { ProcessState } from '../../process/types.js';\nimport type { Platform } from '../../platform/types.js';\nimport type { ProxyConfigProvider, ProxyOpts } from '../../proxy-config/types.js';\nimport { startSocketServer, type SocketServerHandle } from '../../control-plane/socket-server.js';\nimport { calcCpuPercent } from '../../utils.js';\n\n/** Lifecycle of the Unix-socket JSON-RPC control plane. Mounts when the\n * manager is ready; tears down on unmount.\n *\n * On listen failure (perms, dir missing, port already-in-use on the inode)\n * devup keeps running without the control plane and logs a single notice. */\nexport function useControlPlane(\n manager: ProcessManager | null,\n projectName: string,\n logSink: LogSink | null,\n pushLog: (svc: string, msg: string, colorIdx?: number) => void,\n logBus: Broadcaster<{ svc: string; text: string }>,\n stateBus: Broadcaster<{ name: string; state: ProcessState }>,\n platform: Platform,\n proxy: { provider: ProxyConfigProvider; opts: ProxyOpts } | null,\n profiles: Record<string, string[]>,\n): React.RefObject<SocketServerHandle | null> {\n const handleRef = useRef<SocketServerHandle | null>(null);\n const prevCpuMap = useRef(new Map<string, { time: number; cpu: number }>());\n\n useEffect(() => {\n if (!manager) return;\n let handle: SocketServerHandle | null = null;\n (async () => {\n try {\n handle = await startSocketServer(projectName, {\n states: () => manager.state,\n restart: (name) => manager.restart(name),\n stop: (name) => manager.stop(name),\n tailLogs: async (svcName, lines) => {\n if (!logSink) return [];\n const file = logSink.pathFor(svcName);\n if (!existsSync(file)) return [];\n return new Promise<string[]>((resolve, reject) => {\n const buf: string[] = [];\n const rl = createInterface({ input: createReadStream(file, { encoding: 'utf8' }) });\n rl.on('line', l => { buf.push(l); if (buf.length > lines) buf.shift(); });\n rl.on('close', () => resolve(buf));\n rl.on('error', reject);\n });\n },\n watchLogs: (svcName, onLine) => {\n return logBus.subscribe(({ svc, text }) => {\n if (svcName === null || svc === svcName) onLine(svc, text);\n });\n },\n watchStatus: (onUpdate) => {\n return stateBus.subscribe(({ name, state }) => onUpdate(name, state));\n },\n async getStats() {\n const pids: number[] = [];\n const pidToName = new Map<number, string>();\n for (const [name, st] of manager.state) {\n if (st.pid) { pids.push(st.pid); pidToName.set(st.pid, name); }\n }\n const raw = pids.length ? await platform.getProcessStats(pids) : new Map();\n const services: Record<string, { cpu: number; memMB: number }> = {};\n for (const [name] of manager.state) {\n services[name] = { cpu: 0, memMB: 0 };\n }\n for (const [pid, data] of raw) {\n const name = pidToName.get(pid);\n if (!name) continue;\n const prev = prevCpuMap.current.get(name) ?? { time: Date.now(), cpu: 0 };\n const cpu = calcCpuPercent(data.cpuSeconds, prev.cpu, prev.time);\n prevCpuMap.current.set(name, { time: Date.now(), cpu: data.cpuSeconds });\n services[name] = { cpu: Math.round(cpu * 10) / 10, memMB: Math.round((data.rss / 1024) * 10) / 10 };\n }\n return {\n services,\n system: {\n totalMemMB: Math.round(totalmem() / 1024 / 1024),\n freeMemMB: Math.round(freemem() / 1024 / 1024),\n cpuCores: cpus().length,\n },\n };\n },\n getProxyInfo() {\n if (!proxy) return null;\n return {\n active: true,\n provider: proxy.provider.name,\n domain: proxy.opts.domain,\n tls: proxy.opts.tls,\n routes: proxy.opts.routes,\n };\n },\n getInfo() {\n return { project: projectName, profiles };\n },\n }, { onLog: msg => pushLog('devup', msg, 12) });\n handleRef.current = handle;\n } catch (e: any) {\n pushLog('devup', `⚠ control plane disabled: ${e.message}`, 5);\n }\n })();\n return () => { void handle?.close(); handleRef.current = null; };\n }, [manager, projectName, logSink, pushLog, logBus, stateBus, platform, proxy, profiles]);\n return handleRef;\n}\n","import { useEffect } from 'react';\nimport type { ProcessManager } from '../../process/manager.js';\nimport type { CliArgs } from '../../config/cli.js';\nimport { findConfigFile } from '../../config/loader.js';\nimport { watchConfig } from '../../orchestrator/config-watcher.js';\n\n/** Watches the resolved config file when --watch-config is on. Bridge between\n * React's lifecycle and the pure `watchConfig` helper used by the daemon. */\nexport function useHotReload(\n manager: ProcessManager | null,\n cliArgs: CliArgs,\n baseCwd: string,\n pushLog: (svc: string, msg: string, colorIdx?: number) => void,\n): void {\n useEffect(() => {\n if (!cliArgs.watchConfig || !manager) return;\n let configPath: string;\n try {\n configPath = findConfigFile(baseCwd, cliArgs.configPath);\n } catch (e: any) {\n pushLog('devup', `⚠ watch-config disabled: ${e.message}`, 5);\n return;\n }\n pushLog('devup', `👀 watching ${configPath}`, 12);\n return watchConfig({\n configPath, baseCwd, manager,\n log: msg => pushLog('devup', msg, msg.startsWith('⚠') ? 5 : 12),\n });\n }, [cliArgs.watchConfig, cliArgs.configPath, baseCwd, manager, pushLog]);\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { ProcessState } from '../../process/types.js';\nimport { pickTip } from '../tips.js';\nimport { isCrashLooped } from '../StatsPanel.js';\n\n/** Surfaces a one-liner tip in teachable moments (high log volume, crash\n * loop, etc.). Each tip shows at most once per session and auto-clears\n * after 12 s. */\nexport function useContextualTips(\n totalLogs: number,\n hasSearch: boolean,\n hasFilter: boolean,\n states: Map<string, ProcessState>,\n): string | null {\n const shownTips = useRef<Set<string>>(new Set());\n const [activeTip, setActiveTip] = useState<string | null>(null);\n\n useEffect(() => {\n const tip = pickTip({\n totalLogs,\n hasSearch,\n hasFilter,\n crashLoopedCount: [...states.values()].filter(isCrashLooped).length,\n shown: shownTips.current,\n });\n if (tip && tip.message !== activeTip) {\n shownTips.current.add(tip.id);\n setActiveTip(tip.message);\n const timer = setTimeout(() => setActiveTip(null), 12_000);\n return () => clearTimeout(timer);\n }\n }, [totalLogs, states, hasSearch, hasFilter, activeTip]);\n\n return activeTip;\n}\n","/** Contextual tips for new users. Pure function — easy to test, easy to extend. */\n\nexport interface TipState {\n totalLogs: number;\n hasSearch: boolean;\n hasFilter: boolean;\n crashLoopedCount: number;\n /** IDs of tips already shown this session — they don't repeat. */\n shown: Set<string>;\n}\n\nexport interface Tip {\n id: string;\n message: string;\n}\n\n/** Picks the highest-priority unseen tip whose conditions are met,\n * or null if no tip applies right now. */\nexport function pickTip(state: TipState): Tip | null {\n // Order = priority. Higher-impact first.\n if (state.crashLoopedCount > 0 && !state.shown.has('crashed')) {\n return { id: 'crashed', message: 'tip: press r to restart, or check the log of the failing service' };\n }\n if (state.totalLogs > 1000 && !state.hasSearch && !state.shown.has('search')) {\n return { id: 'search', message: 'tip: press / to search in logs' };\n }\n if (state.totalLogs > 500 && !state.hasFilter && !state.shown.has('filter')) {\n return { id: 'filter', message: 'tip: press f to filter logs by service' };\n }\n return null;\n}\n","import React, { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport type { ProcessState } from '../process/types.js';\nimport type { ServiceStats } from './hooks/useProcessManager.js';\nimport { fmtUptime, sortServiceNames, tagColors, redactSecrets, buildProcessArgs, nextRamBannerVisibility } from '../utils.js';\nimport os from 'node:os';\n\ninterface Props {\n states: Map<string, ProcessState>;\n stats: Map<string, ServiceStats>;\n sortMode: string;\n maxNameLen: number;\n height: number;\n focused: boolean;\n scrollOffset: number;\n resetScroll: () => void;\n verbose?: boolean;\n}\n\nconst H: Record<string, { c: string; color: string }> = {\n up: { c: '●', color: 'green' }, wait: { c: '●', color: 'yellow' },\n down: { c: '●', color: 'red' }, idle: { c: '○', color: 'blue' },\n};\n\n/** Matches the constant in ProcessManager — kept in sync manually. */\nexport const MAX_RESTARTS = 3;\n\nexport function isCrashLooped(st: ProcessState): boolean {\n return st.status === 'crashed' && st.restarts >= MAX_RESTARTS;\n}\n\nfunction Row({ name, st, stat, ml, verbose }: { name: string; st: ProcessState; stat?: ServiceStats; ml: number; verbose?: boolean }) {\n const looped = isCrashLooped(st);\n const indicator = looped\n ? <Text color=\"red\" bold>✖</Text>\n : <Text color={(H[st.health] ?? H['down']!).color}>{(H[st.health] ?? H['down']!).c}</Text>;\n const color = tagColors[st.colorIdx % tagColors.length]!;\n const sc = looped ? 'red' : st.status === 'running' ? 'green' : st.status === 'starting' ? 'yellow' : st.status === 'idle' ? 'blue' : 'red';\n const statusLabel = looped ? 'looping' : st.status;\n const up = st.startedAt ? fmtUptime(Date.now() - st.startedAt) : '-';\n\n if (!verbose) {\n return (\n <Text>\n {indicator} <Text color={color}>{name.padEnd(ml)}</Text> {String(st.svc.port).padStart(5)} <Text color={sc} bold={looped}>{statusLabel.padEnd(8)}</Text> {(stat?.cpu ?? '-').padStart(6)} {(stat?.mem ?? '-').padStart(8)} {String(st.errors).padStart(3)} {String(st.restarts).padStart(3)} {up.padStart(6)}\n </Text>\n );\n }\n\n // Verbose: row + 2 indented lines with the resolved cmd/args and extraEnv.\n const resolvedArgs = buildProcessArgs(st.svc).join(' ');\n const env = redactSecrets(st.svc.extraEnv);\n const envStr = Object.entries(env).map(([k, v]) => `${k}=${v}`).join(' ');\n return (\n <Box flexDirection=\"column\">\n <Text>\n {indicator} <Text color={color}>{name.padEnd(ml)}</Text> {String(st.svc.port).padStart(5)} <Text color={sc} bold={looped}>{statusLabel.padEnd(8)}</Text> {(stat?.cpu ?? '-').padStart(6)} {(stat?.mem ?? '-').padStart(8)} {String(st.errors).padStart(3)} {String(st.restarts).padStart(3)} {up.padStart(6)}\n </Text>\n <Text dimColor> cmd: {st.svc.cmd} {resolvedArgs}</Text>\n {envStr && <Text dimColor> env: {envStr}</Text>}\n </Box>\n );\n}\n\nfunction ColHeader({ ml }: { ml: number }) {\n return <Text bold>H {'Service'.padEnd(ml)} {'Port'.padStart(5)} {'Status'.padEnd(8)} {'CPU'.padStart(6)} {'Mem'.padStart(8)} Err Rst {'Up'.padStart(6)}</Text>;\n}\n\nexport function StatsPanel({ states, stats, sortMode, maxNameLen, height, focused, scrollOffset, resetScroll, verbose = false }: Props) {\n const names = [...states.keys()];\n const stObj = Object.fromEntries([...states].map(([k, v]) => [k, { errors: v.errors }]));\n const statsObj = Object.fromEntries([...stats].map(([k, v]) => [k, v]));\n\n const apis = sortServiceNames(names.filter(n => states.get(n)!.svc.type === 'api'), sortMode, statsObj, stObj);\n const webs = sortServiceNames(names.filter(n => states.get(n)!.svc.type === 'web'), sortMode, statsObj, stObj);\n\n // System stats\n const cpus = os.cpus().length;\n const totalGB = (os.totalmem() / 1024 / 1024 / 1024).toFixed(1);\n const usedGB = (parseFloat(totalGB) - os.freemem() / 1024 / 1024 / 1024).toFixed(1);\n const load = os.loadavg()[0]!.toFixed(2);\n\n // Stack totals\n let totalCpu = 0, totalMemMB = 0, totalErrors = 0, totalRestarts = 0;\n for (const name of names) {\n const s = stats.get(name);\n if (s) {\n const c = parseFloat(s.cpu); if (!isNaN(c)) totalCpu += c;\n const m = parseFloat(s.mem); if (!isNaN(m)) totalMemMB += m;\n }\n totalErrors += states.get(name)?.errors ?? 0;\n totalRestarts += states.get(name)?.restarts ?? 0;\n }\n const stackMem = totalMemMB >= 1024 ? (totalMemMB / 1024).toFixed(2) + ' GB' : totalMemMB.toFixed(1) + ' MB';\n\n const ml = maxNameLen;\n const contentHeight = Math.max(1, height - 2);\n const rowsPerCol = Math.max(1, contentHeight - 2); // header row + col header\n\n // scrollOffset = topOffset (filas por debajo de la primera, 0 = primera fila)\n const maxRows = Math.max(0, Math.max(apis.length, webs.length) - rowsPerCol);\n const effectiveOffset = scrollOffset === Number.MAX_SAFE_INTEGER\n ? maxRows\n : Math.min(scrollOffset, maxRows);\n const apiStartIndex = Math.min(effectiveOffset, Math.max(0, apis.length - rowsPerCol));\n const webStartIndex = Math.min(effectiveOffset, Math.max(0, webs.length - rowsPerCol));\n\n const visibleApis = apis.slice(apiStartIndex, apiStartIndex + rowsPerCol);\n const visibleWebs = webs.slice(webStartIndex, webStartIndex + rowsPerCol);\n\n // Reset scroll cuando cambia el modo de ordenamiento\n useEffect(() => {\n resetScroll();\n }, [sortMode, resetScroll]);\n\n const totalRowsLong = Math.max(apis.length, webs.length);\n const positionInfo = focused && totalRowsLong > 0\n ? `(${effectiveOffset + 1}-${Math.min(effectiveOffset + rowsPerCol, totalRowsLong)}/${totalRowsLong})`\n : '';\n const scrolled = effectiveOffset > 0;\n const loopedCount = [...states.values()].filter(isCrashLooped).length;\n\n // RAM pressure banner with hysteresis (80% on, 75% off).\n const ramPct = (parseFloat(usedGB) / parseFloat(totalGB)) * 100;\n const [ramBanner, setRamBanner] = useState(false);\n useEffect(() => {\n setRamBanner(prev => nextRamBannerVisibility(ramPct, prev));\n }, [ramPct]);\n\n // Top consumers when the banner is active.\n const topConsumers = ramBanner\n ? [...stats.entries()]\n .map(([n, s]) => ({ name: n, mb: parseFloat(s.mem) || 0 }))\n .sort((a, b) => b.mb - a.mb)\n .slice(0, 3)\n : [];\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={focused ? 'green' : 'gray'} height={height}>\n <Box>\n <Text bold color=\"green\"> Stats {positionInfo}</Text>\n {scrolled && <Text color=\"yellow\"> [SCROLL]</Text>}\n {loopedCount > 0 && <Text color=\"red\" bold> ⚠ {loopedCount} need attention</Text>}\n <Text dimColor> System: {cpus}c Load {load} RAM {usedGB}/{totalGB}GB</Text>\n <Text dimColor> │ </Text>\n <Text dimColor>Stack: CPU {totalCpu.toFixed(1)}% RAM {stackMem} Err {totalErrors} Rst {totalRestarts} Svcs {names.length}</Text>\n {sortMode !== 'name' && <Text dimColor> │ Sort: {sortMode}</Text>}\n </Box>\n {ramBanner && (\n <Box>\n <Text color=\"yellow\" bold> ⚠ RAM {ramPct.toFixed(0)}% — top: </Text>\n <Text color=\"yellow\">{topConsumers.map(c => `${c.name} ${c.mb.toFixed(0)}MB`).join(', ')}</Text>\n </Box>\n )}\n <Box flexGrow={1}>\n {/* Left column: APIs */}\n <Box flexDirection=\"column\" flexGrow={1} flexBasis={0}>\n <Text bold color=\"cyan\"> APIs ({apis.length})</Text>\n <ColHeader ml={ml} />\n {visibleApis.map(n => (\n <Row key={n} name={n} st={states.get(n)!} stat={stats.get(n)} ml={ml} verbose={verbose} />\n ))}\n </Box>\n {/* Separator */}\n <Box flexDirection=\"column\" width={1}>\n {Array.from({ length: contentHeight }, (_, i) => <Text key={i} dimColor>│</Text>)}\n </Box>\n {/* Right column: Webs */}\n <Box flexDirection=\"column\" flexGrow={1} flexBasis={0}>\n <Text bold color=\"magenta\"> Webs ({webs.length})</Text>\n <ColHeader ml={ml} />\n {visibleWebs.map(n => (\n <Row key={n} name={n} st={states.get(n)!} stat={stats.get(n)} ml={ml} verbose={verbose} />\n ))}\n </Box>\n </Box>\n </Box>\n );\n}\n","import { useEffect, useState } from 'react';\nimport type { Platform } from '../../platform/types.js';\nimport type { DevStackConfig, ServiceConfig } from '../../config/types.js';\nimport type { CliArgs } from '../../config/cli.js';\nimport type { ProcessManager } from '../../process/manager.js';\nimport type { ProcessState } from '../../process/types.js';\nimport { groupByPhase } from '../../utils.js';\nimport { waitForPort } from '../../process/health.js';\nimport { classifyServices, rewriteServicePort } from '../../lazy/classifier.js';\nimport { createLazyProxy, type LazyProxy } from '../../lazy/proxy.js';\nimport { startExternals, type ExternalProc } from '../../process/external.js';\n\ninterface BootRefs {\n lazyProxies: React.RefObject<Map<string, LazyProxy>>;\n externals: React.RefObject<ExternalProc[]>;\n}\n\n/** Orchestrates the boot:\n * 1. Externals first (docker compose etc.) — abort if any unhealthy.\n * 2. In lazy mode: start always-on services in phase order, register lazy\n * TCP proxies for the rest.\n * 3. In normal mode: start every service in phase order.\n *\n * Within each phase, APIs are awaited via waitForPort; webs are not. */\nexport function useBootSequence(\n manager: ProcessManager | null,\n config: DevStackConfig,\n services: ServiceConfig[],\n cliArgs: CliArgs,\n platform: Platform,\n env: Record<string, string>,\n baseCwd: string,\n refs: BootRefs,\n pushLog: (svc: string, msg: string, colorIdx?: number) => void,\n): void {\n const [booted, setBooted] = useState(false);\n\n useEffect(() => {\n if (booted || !manager) return;\n setBooted(true);\n const mgr = manager;\n\n (async () => {\n const lazyMode = cliArgs.lazy;\n const lazyTimeout = cliArgs.lazyTimeout;\n\n // External dependencies (DBs, queues, etc.) — must be healthy before phase 0.\n if (config.external?.length) {\n const result = await startExternals(config.external, {\n baseCwd, env, platform,\n onLog: (svc, msg) => pushLog(`ext:${svc}`, msg, 12),\n });\n refs.externals.current = result.procs;\n if (!result.allHealthy) {\n pushLog('devup', `❌ external(s) failed: ${result.failed.join(', ')}. Aborting boot.`, 5);\n return;\n }\n }\n\n if (lazyMode && config.lazy) {\n // ── Lazy mode ──\n const { alwaysOn, lazy } = classifyServices(services, config.lazy);\n\n // Boot always-on services normally\n const aoPhases = groupByPhase(alwaysOn);\n let colorIdx = 0;\n for (const num of Object.keys(aoPhases).map(Number).sort((a, b) => a - b)) {\n const svcs = aoPhases[num]!;\n for (const svc of svcs) {\n const ci = colorIdx++;\n await mgr.install(svc, ci);\n await mgr.start(svc, ci);\n }\n const apis = svcs.filter(s => s.type === 'api');\n if (apis.length) await Promise.all(apis.map(s => waitForPort(s.port, { timeout: 45000 })));\n svcs.filter(s => s.type === 'web').forEach(s => {\n const st = mgr.state.get(s.name);\n if (st) st.status = 'running';\n });\n }\n\n // Set up lazy proxies\n for (const svc of lazy) {\n const ci = colorIdx++;\n const rewritten = rewriteServicePort(svc);\n\n // Register as idle in process state\n const idleState: ProcessState = {\n svc: rewritten, proc: null, pid: null,\n status: 'idle', health: 'idle',\n errors: 0, restarts: 0, startedAt: null,\n intentionalStop: false, colorIdx: ci,\n };\n mgr.state.set(svc.name, idleState);\n\n const proxy = createLazyProxy({\n listenPort: svc.port,\n targetPort: rewritten.realPort,\n timeoutMin: lazyTimeout,\n onDemandStart: async () => {\n await mgr.install(rewritten, ci);\n await mgr.start(rewritten, ci);\n const ok = await waitForPort(rewritten.realPort, { timeout: 45000 });\n const st = mgr.state.get(svc.name);\n if (st) {\n st.status = ok ? 'running' : 'timeout';\n if (ok) st.health = 'up';\n }\n },\n onIdleStop: () => {\n mgr.stop(svc.name);\n const st = mgr.state.get(svc.name);\n if (st) { st.status = 'idle'; st.health = 'idle'; st.pid = null; st.proc = null; st.startedAt = null; }\n },\n isAlive: () => {\n const st = mgr.state.get(svc.name);\n return !!st && !!st.proc && !st.proc.killed && st.health === 'up';\n },\n });\n\n refs.lazyProxies.current!.set(svc.name, proxy);\n }\n } else {\n // ── Normal mode ──\n const phases = groupByPhase(services);\n let colorIdx = 0;\n for (const num of Object.keys(phases).map(Number).sort((a, b) => a - b)) {\n const svcs = phases[num]!;\n for (const svc of svcs) {\n const ci = colorIdx++;\n await mgr.install(svc, ci);\n await mgr.start(svc, ci);\n }\n const apis = svcs.filter(s => s.type === 'api');\n if (apis.length) await Promise.all(apis.map(s => waitForPort(s.port, { timeout: 45000 })));\n svcs.filter(s => s.type === 'web').forEach(s => {\n const st = mgr.state.get(s.name);\n if (st) st.status = 'running';\n });\n }\n }\n })();\n }, [booted, manager, services, cliArgs, config.lazy, config.external, baseCwd, env, platform, refs, pushLog]);\n}\n","import React, { useEffect, useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport type { LogEntry } from './hooks/useProcessManager.js';\nimport { tagColors, compileSearchPattern } from '../utils.js';\n\n/** Border color resolution rules:\n * - focused wins (cyan), so the active-pane affordance is never lost\n * - filtered + we know the service color → use it (subtle reinforcement)\n * - otherwise gray */\nexport function resolveBorder(focused: boolean, filter: string | null, filteredColorIdx: number | null): string {\n if (focused) return 'cyan';\n if (filter && filteredColorIdx !== null && filteredColorIdx >= 0) {\n return tagColors[filteredColorIdx % tagColors.length]!;\n }\n return 'gray';\n}\n\ninterface Props {\n logs: LogEntry[];\n filter: string | null;\n searchTerm: string | null;\n paused: boolean;\n showTimestamps: boolean;\n maxNameLen: number;\n height: number;\n focused: boolean;\n scrollOffset: number;\n resetScroll: () => void;\n levelFilter?: 'all' | 'error' | 'warn';\n /** When non-null, used to tint the panel border with the filtered service's tag color\n * (subtle reinforcement of \"you're seeing only this service\"). */\n filteredColorIdx?: number | null;\n}\n\nexport function LogsPanel({ logs, filter, searchTerm, paused, showTimestamps, maxNameLen, height, focused, scrollOffset, resetScroll, levelFilter = 'all', filteredColorIdx = null }: Props) {\n const byService = filter ? logs.filter(l => l.svcName === filter) : logs;\n const filtered = levelFilter === 'all'\n ? byService\n : levelFilter === 'error'\n ? byService.filter(l => l.level === 'error')\n : byService.filter(l => l.level === 'error' || l.level === 'warn');\n const contentHeight = Math.max(1, height - 2);\n const totalLines = filtered.length;\n\n // scrollOffset = \"líneas por encima del fondo\": 0 = follow latest, N = N líneas atrás.\n const maxOffset = Math.max(0, totalLines - contentHeight);\n const effectiveOffset = scrollOffset === Number.MAX_SAFE_INTEGER\n ? maxOffset\n : Math.min(scrollOffset, maxOffset);\n const startIndex = Math.max(0, totalLines - contentHeight - effectiveOffset);\n const endIndex = Math.min(startIndex + contentHeight, totalLines);\n const visible = filtered.slice(startIndex, endIndex);\n\n // Reset scroll cuando cambia el filtro o búsqueda — vuelve a seguir lo último.\n useEffect(() => {\n resetScroll();\n }, [filter, searchTerm, resetScroll]);\n\n const matcher = useMemo(() => compileSearchPattern(searchTerm), [searchTerm]);\n\n const scrolled = effectiveOffset > 0;\n const label = [\n 'Logs',\n filter ? `[${filter}]` : '',\n searchTerm ? `/${searchTerm}` : '',\n matcher?.invalid ? '(invalid regex)' : '',\n levelFilter !== 'all' ? `[level: ${levelFilter}${levelFilter === 'warn' ? '+error' : ''}]` : '',\n paused ? '[PAUSED]' : '',\n scrolled ? '[SCROLL]' : '',\n `${filtered.length} lines`,\n focused && totalLines > 0 ? `(${startIndex + 1}-${endIndex}/${totalLines})` : '',\n ].filter(Boolean).join(' ');\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={resolveBorder(focused, filter, filteredColorIdx)} height={height}>\n <Box><Text bold color=\"cyan\"> {label} </Text></Box>\n {visible.map((entry, i) => {\n const color = tagColors[entry.colorIdx % tagColors.length]!;\n const ts = showTimestamps ? new Date(entry.ts).toLocaleTimeString('en-GB') + ' ' : '';\n const line = entry.text;\n const isMatch = matcher ? matcher.test(line) : false;\n return (\n <Box key={i}>\n {showTimestamps && <Text dimColor>{ts}</Text>}\n <Text color={color}>[{entry.svcName.padEnd(maxNameLen)}]</Text>\n <Text> </Text>\n {isMatch ? <Text backgroundColor=\"yellow\" color=\"black\">{line}</Text> : <Text>{line}</Text>}\n </Box>\n );\n })}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nexport function StatusBar() {\n return (\n <Box>\n <Text>\n <Text bold>q</Text> Quit <Text bold>Tab</Text> Switch <Text bold>↑↓</Text> Scroll <Text bold>PgUp/PgDn</Text> Page <Text bold>Ctrl+A/E</Text> Home/End <Text bold>c</Text> Clear <Text bold>f</Text> Filter <Text bold>L</Text> Level <Text bold>a</Text> All <Text bold>r</Text> Restart <Text bold>/</Text> Search <Text bold>s</Text> Sort <Text bold>o</Text> Open <Text bold>p</Text> Pause <Text bold>t</Text> Time <Text bold>v</Text> Verbose <Text bold>T</Text> Proxy\n </Text>\n </Box>\n );\n}\n","import React, { useState, useMemo } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { ProcessState } from '../process/types.js';\n\ninterface Props {\n title: string;\n services: Map<string, ProcessState>;\n onSelect: (name: string) => void;\n onClose: () => void;\n filterType?: 'api' | 'web';\n}\n\nexport function ServiceList({ title, services, onSelect, onClose, filterType }: Props) {\n const allNames = useMemo(\n () => [...services.keys()].filter(n => !filterType || services.get(n)!.svc.type === filterType),\n [services, filterType],\n );\n const [idx, setIdx] = useState(0);\n const [query, setQuery] = useState('');\n\n const names = useMemo(() => {\n if (!query) return allNames;\n const q = query.toLowerCase();\n return allNames.filter(n => n.toLowerCase().includes(q));\n }, [allNames, query]);\n\n // Clamp selected index when the list shrinks\n const clamped = Math.min(idx, Math.max(0, names.length - 1));\n\n useInput((input, key) => {\n if (key.escape) {\n if (query) setQuery(''); // first Esc clears filter\n else onClose(); // second Esc closes\n return;\n }\n if (key.return) {\n if (names[clamped]) onSelect(names[clamped]!);\n return;\n }\n if (key.upArrow) { setIdx(i => Math.max(0, i - 1)); return; }\n if (key.downArrow) { setIdx(i => Math.min(names.length - 1, i + 1)); return; }\n if (key.backspace || key.delete) { setQuery(q => q.slice(0, -1)); setIdx(0); return; }\n if (input && !key.ctrl && !key.meta && input.length === 1) {\n setQuery(q => q + input);\n setIdx(0);\n }\n }, { isActive: process.stdin.isTTY ?? false });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\"> {title} {query && <Text color=\"yellow\">[{query}]</Text>}</Text>\n {names.length === 0 ? (\n <Text dimColor> (no matches) </Text>\n ) : (\n names.map((name, i) => (\n <Box key={name}>\n <Text color={i === clamped ? 'cyan' : undefined} inverse={i === clamped}> {name} :{services.get(name)!.svc.port} </Text>\n </Box>\n ))\n )}\n <Text dimColor>type to filter ↑↓ navigate Enter select Esc clear/close</Text>\n </Box>\n );\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\n\ninterface Props {\n onSubmit: (term: string | null) => void;\n onClose: () => void;\n}\n\nexport function SearchInput({ onSubmit, onClose }: Props) {\n const [value, setValue] = useState('');\n\n useInput((input, key) => {\n if (key.escape) onClose();\n else if (key.return) onSubmit(value.trim() || null);\n else if (key.backspace || key.delete) setValue(v => v.slice(0, -1));\n else if (input && !key.ctrl && !key.meta) setValue(v => v + input);\n }, { isActive: process.stdin.isTTY ?? false });\n\n return (\n <Box borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text bold color=\"yellow\">Search: </Text>\n <Text>{value}</Text>\n <Text dimColor>█</Text>\n </Box>\n );\n}\n","import type { DevStackConfig, ServiceConfig } from '../config/types.js';\nimport type { CliArgs } from '../config/cli.js';\nimport type { ProxyConfigProvider, ProxyOpts } from '../proxy-config/types.js';\nimport type { ServiceState } from '../proxy-config/types.js';\nimport { groupByPhase, buildProcessArgs, buildProcessEnv } from '../utils.js';\nimport { classifyServices, rewriteServicePort, getLazyRealPort } from '../lazy/classifier.js';\n\nexport interface DryRunOpts {\n config: DevStackConfig;\n services: ServiceConfig[];\n cliArgs: CliArgs;\n env: Record<string, string>;\n baseCwd: string;\n proxyProvider: ProxyConfigProvider | null;\n proxyOpts: ProxyOpts | null;\n}\n\nexport function renderDryRun(opts: DryRunOpts): string {\n const { config, services, cliArgs, env, proxyProvider, proxyOpts } = opts;\n const lines: string[] = [];\n\n lines.push(`Project: ${config.icon ?? '📦'} ${config.name}`);\n lines.push(`Mode: ${cliArgs.lazy && config.lazy ? 'lazy' : 'normal'}`);\n if (cliArgs.profile) lines.push(`Profile: ${cliArgs.profile}`);\n lines.push(`Services: ${services.length}`);\n lines.push('');\n\n if (config.external?.length) {\n lines.push(`Externals (${config.external.length}):`);\n for (const ext of config.external) {\n const hc = ext.healthCheck;\n const hcTag = hc\n ? ` health=${hc.type}${hc.type === 'http' ? ' ' + (hc.path ?? '/') : ''} :${ext.port ?? '?'}`\n : '';\n lines.push(` - ${ext.name.padEnd(20)} ${ext.cmd}${hcTag}`);\n }\n lines.push('');\n }\n\n const lazyMode = cliArgs.lazy && !!config.lazy;\n let alwaysOn: ServiceConfig[] = services;\n let lazy: ServiceConfig[] = [];\n if (lazyMode) {\n const c = classifyServices(services, config.lazy!);\n alwaysOn = c.alwaysOn;\n lazy = c.lazy;\n }\n\n const phases = groupByPhase(alwaysOn);\n const phaseNums = Object.keys(phases).map(Number).sort((a, b) => a - b);\n for (const num of phaseNums) {\n lines.push(`Phase ${num}:`);\n for (const svc of phases[num]!) {\n lines.push(formatService(svc, env, false));\n }\n }\n\n if (lazy.length) {\n lines.push('');\n lines.push('Lazy (on-demand):');\n for (const svc of lazy) {\n const rewritten = rewriteServicePort(svc);\n lines.push(formatService(rewritten, env, true));\n lines.push(` proxy :${svc.port} → :${getLazyRealPort(svc.port)} (idle timeout ${cliArgs.lazyTimeout}m)`);\n }\n }\n\n if (proxyProvider && proxyOpts) {\n lines.push('');\n lines.push(`Proxy: ${proxyProvider.name} → ${proxyOpts.confPath}`);\n // Simulamos todas las rutas como \"up\" para mostrar el output\n const svcStates = new Map<string, ServiceState>();\n for (const svc of services) {\n const real = lazyMode && !alwaysOn.includes(svc) ? getLazyRealPort(svc.port) : undefined;\n svcStates.set(svc.name, { port: svc.port, health: 'up', realPort: real });\n }\n const content = proxyProvider.generate(svcStates, proxyOpts);\n lines.push('');\n lines.push('--- generated config ---');\n lines.push(content);\n }\n\n return lines.join('\\n');\n}\n\nfunction formatService(svc: ServiceConfig, env: Record<string, string>, isLazy: boolean): string {\n const args = buildProcessArgs(svc);\n const cmdLine = [svc.cmd, ...args].join(' ');\n const built = buildProcessEnv(svc, env);\n const extraEnv = Object.keys(svc.extraEnv ?? {}).length\n ? ' env=' + Object.entries(svc.extraEnv!).map(([k, v]) => `${k}=${v}`).join(' ')\n : '';\n const memTag = svc.maxMem ? ` mem=${svc.maxMem}MB` : '';\n const hc = svc.healthCheck;\n const hcTag = hc?.type === 'http' ? ` health=http ${hc.path ?? '/'}` : '';\n const lazyTag = isLazy ? ' [lazy]' : '';\n void built;\n return ` - ${svc.name.padEnd(20)} (${svc.type}) :${svc.port} ${cmdLine}${memTag}${hcTag}${lazyTag}${extraEnv}`;\n}\n\nexport function runDryRun(opts: DryRunOpts): void {\n // eslint-disable-next-line no-console\n console.log(renderDryRun(opts));\n}\n","import { ProcessManager } from '../process/manager.js';\nimport { checkHealth } from '../process/health.js';\nimport { groupByPhase } from '../utils.js';\nimport type { DevStackConfig, ServiceConfig } from '../config/types.js';\nimport type { CliArgs } from '../config/cli.js';\nimport type { Platform } from '../platform/types.js';\nimport type { LogSink } from '../process/log-sink.js';\nimport { startExternals, stopExternals, type ExternalProc } from '../process/external.js';\n\nexport interface OnceOpts {\n config: DevStackConfig;\n services: ServiceConfig[];\n cliArgs: CliArgs;\n platform: Platform;\n env: Record<string, string>;\n baseCwd: string;\n logSink: LogSink | null;\n /** For testing: override stdout. */\n out?: (line: string) => void;\n}\n\n/** Boots services phase-by-phase, waits until each API is healthy, then returns.\n * Returns 0 if everything came up within onceTimeout, 1 otherwise. */\nexport async function runOnce(opts: OnceOpts): Promise<number> {\n const out = opts.out ?? ((l: string) => console.log(l));\n const { config, services, cliArgs, platform, env, baseCwd, logSink } = opts;\n\n const mgr = new ProcessManager({\n baseCwd, env, platform,\n events: {\n onLog: (svc, text) => { logSink?.write(svc, text); out(`[${svc}] ${text}`); },\n onStateChange: () => {},\n },\n });\n\n // External dependencies (DBs, queues, etc.) before phase 0.\n let externals: ExternalProc[] = [];\n if (config.external?.length) {\n out(`▶ externals (${config.external.length})`);\n const result = await startExternals(config.external, {\n baseCwd, env, platform,\n onLog: (svc, msg) => { logSink?.write(`ext:${svc}`, msg); out(`[ext:${svc}] ${msg}`); },\n });\n externals = result.procs;\n if (!result.allHealthy) {\n out(`✗ externals failed: ${result.failed.join(', ')}`);\n await stopExternals(externals, platform, { baseCwd, env });\n await mgr.cleanup();\n return 1;\n }\n }\n\n const phases = groupByPhase(services);\n const phaseNums = Object.keys(phases).map(Number).sort((a, b) => a - b);\n const apiNames = services.filter(s => s.type === 'api').map(s => s.name);\n const deadline = Date.now() + cliArgs.onceTimeout * 1000;\n let colorIdx = 0;\n\n for (const num of phaseNums) {\n out(`▶ phase ${num}`);\n for (const svc of phases[num]!) {\n const ci = colorIdx++;\n const installed = await mgr.install(svc, ci);\n if (!installed) {\n out(`✗ install failed for ${svc.name}`);\n await mgr.cleanup();\n await stopExternals(externals, platform, { baseCwd, env });\n return 1;\n }\n await mgr.start(svc, ci);\n }\n\n // Wait for all APIs in this phase\n const apis = phases[num]!.filter(s => s.type === 'api');\n for (const api of apis) {\n const ok = await waitHealthy(api, deadline);\n if (!ok) {\n out(`✗ ${api.name} did not become healthy within ${cliArgs.onceTimeout}s`);\n await mgr.cleanup();\n await stopExternals(externals, platform, { baseCwd, env });\n return 1;\n }\n out(`✓ ${api.name} ready`);\n const st = mgr.state.get(api.name);\n if (st) { st.status = 'running'; st.health = 'up'; }\n }\n }\n\n const summary = `ready: ${apiNames.length} APIs in ${((cliArgs.onceTimeout * 1000 - (deadline - Date.now())) / 1000).toFixed(1)}s`;\n out(summary);\n await mgr.cleanup();\n await stopExternals(externals, platform, { baseCwd, env });\n return 0;\n}\n\nasync function waitHealthy(svc: ServiceConfig, deadline: number): Promise<boolean> {\n while (Date.now() < deadline) {\n const ok = await checkHealth(svc.port, svc.healthCheck);\n if (ok) return true;\n await new Promise(r => setTimeout(r, 500));\n }\n return false;\n}\n","export interface ServiceConfig {\n name: string;\n cwd: string;\n cmd: string;\n args: string[];\n type: 'api' | 'web';\n port: number;\n phase: number;\n maxMem?: number;\n preBuild?: string;\n watchBuild?: string;\n nodeArgs?: string[];\n extraEnv?: Record<string, string>;\n healthCheck?: HealthCheckConfig;\n /** Case-insensitive regex. When a line of the service's stdout/stderr matches,\n * the service is immediately marked as `up` without waiting for the next\n * health-check poll. Speeds up phase transitions on cold boots.\n * Examples: '/ready in \\\\d+ ms/' (Vite), '/compiled successfully/' (Angular). */\n readyPattern?: string;\n /** Case-insensitive regex. When set, only stderr lines matching this pattern\n * bump `state.errors`. Without it, every non-empty stderr line counts.\n * Useful for libraries that write info messages to stderr (Angular CLI). */\n errorPattern?: string;\n}\n\nexport interface HealthCheckConfig {\n /** 'tcp' (default) checks that the port accepts connections. 'http' makes an HTTP GET. */\n type: 'tcp' | 'http';\n /** HTTP-only: request path. Default: '/' */\n path?: string;\n /** HTTP-only: acceptable status code(s). Default: 200-299 */\n expect?: number | number[];\n /** Override host for the HTTP check. Default: 127.0.0.1 */\n host?: string;\n /** Per-check socket timeout in ms. Default: 2000 */\n timeoutMs?: number;\n /** Grace period (seconds) before the first probe runs. Useful for slow boots\n * (Angular cold-start, big webpack builds) so failed probes during boot don't\n * pollute state.errors. Default: 0 (no grace). */\n startPeriod?: number;\n}\n\nexport interface LazyConfig {\n alwaysOn: string[];\n timeout?: number;\n}\n\nexport interface ProxyConfig {\n provider: string;\n routes: Record<string, string>;\n confPath?: string;\n host?: string;\n tls?: boolean;\n entrypoint?: string;\n}\n\nexport interface ExternalService {\n /** Friendly name (used in logs and the stats panel). Must be unique within `external`. */\n name: string;\n /** Shell command to start. Will be passed through `sh -c` / `cmd /c`. */\n cmd: string;\n /** Optional working directory (relative to the project root). */\n cwd?: string;\n /** Extra env vars merged on top of the project env. */\n extraEnv?: Record<string, string>;\n /** Optional readiness probe. devup waits for this to return `up` before starting phase 0. */\n healthCheck?: HealthCheckConfig;\n /** Port to probe when `healthCheck` is set. Required for tcp checks. */\n port?: number;\n /** Max seconds to wait for healthCheck to pass before giving up. Default: 60. */\n startTimeout?: number;\n /** Optional shell command run on shutdown (e.g. `docker compose down`). */\n stopCmd?: string;\n}\n\nexport interface DevStackConfig {\n name: string;\n icon?: string;\n envFile?: string;\n env?: Record<string, string>;\n services: ServiceConfig[];\n lazy?: LazyConfig;\n proxy?: ProxyConfig;\n /** Named lists of service names — selectable with --profile <name>. */\n profiles?: Record<string, string[]>;\n /** Optional external dependencies (DBs, queues) started before phase 0. */\n external?: ExternalService[];\n}\n\nexport function defineConfig(config: DevStackConfig): DevStackConfig {\n return config;\n}\n"],"mappings":";;;AAAA,OAAOA,YAAW;AAClB,SAAS,cAAc;AACvB,SAAS,gBAAAC,eAAc,oBAAoB;AAC3C,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAC9B,SAAS,iBAAAC,sBAAqB;AAC9B,SAAS,WAAAC,gBAAe;;;ACLxB,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAG9B,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,eAAe,KAAa,UAA2B;AACrE,MAAI,UAAU;AACZ,UAAM,OAAO,QAAQ,KAAK,QAAQ;AAClC,QAAI,CAAC,WAAW,IAAI,EAAG,OAAM,IAAI,MAAM,qBAAqB,IAAI,EAAE;AAClE,WAAO;AAAA,EACT;AACA,aAAW,QAAQ,cAAc;AAC/B,UAAM,OAAO,KAAK,KAAK,IAAI;AAC3B,QAAI,WAAW,IAAI,EAAG,QAAO;AAAA,EAC/B;AACA,QAAM,IAAI;AAAA,IACR,mCAAmC,aAAa,KAAK,IAAI,CAAC;AAAA;AAAA,EAE5D;AACF;AAEA,eAAsB,WAAW,YAA6C;AAC5E,MAAI,WAAW,SAAS,OAAO,GAAG;AAChC,UAAM,MAAM,MAAM,SAAS,YAAY,MAAM;AAC7C,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB;AAGA,QAAM,MAAM,cAAc,UAAU,EAAE;AACtC,QAAM,MAAM,MAAM,OAAO;AACzB,QAAM,SAAS,IAAI,WAAW;AAE9B,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,OAAO,QAAQ,GAAG;AAC5E,UAAM,IAAI,MAAM,uFAAuF;AAAA,EACzG;AAEA,SAAO;AACT;;;AC5CA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,WAAAC,gBAAe;;;ACCjB,IAAM,mBAAmB;AAQzB,SAAS,iBAAiB,UAA2B,QAAyC;AACnG,QAAM,cAAc,IAAI,IAAI,QAAQ,YAAY,CAAC,CAAC;AAClD,QAAM,WAA4B,CAAC;AACnC,QAAM,OAAwB,CAAC;AAE/B,aAAW,OAAO,UAAU;AAC1B,QAAI,YAAY,IAAI,IAAI,IAAI,EAAG,UAAS,KAAK,GAAG;AAAA,QAC3C,MAAK,KAAK,GAAG;AAAA,EACpB;AACA,SAAO,EAAE,UAAU,KAAK;AAC1B;AAEO,SAAS,gBAAgB,cAA8B;AAC5D,SAAO,eAAe;AACxB;AAEO,SAAS,mBAAmB,KAAgF;AACjH,QAAM,WAAW,gBAAgB,IAAI,IAAI;AACzC,QAAM,OAAO,IAAI,KAAK,IAAI,OAAK,MAAM,OAAO,IAAI,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC;AAC5E,QAAM,WAAW,EAAE,GAAG,IAAI,UAAU,eAAe,OAAO,QAAQ,EAAE;AACpE,SAAO,EAAE,GAAG,KAAK,MAAM,UAAU,MAAM,UAAU,UAAU,cAAc,IAAI,KAAK;AACpF;;;ADbO,SAAS,gBAAgB,QAA6C;AAC3E,QAAM,WAAgC,CAAC;AACvC,MAAI,CAAC,OAAO,UAAU,OAAQ,QAAO;AAErC,aAAW,OAAO,OAAO,UAAU;AAGjC,UAAM,KAAK,IAAI,WAAW,MAAM;AAChC,QAAI,OAAO,QAAW;AACpB,YAAM,WAAW,OAAO,IAAI,IAAI;AAChC,UAAI,OAAO,UAAU;AACnB,iBAAS,KAAK;AAAA,UACZ,OAAO,YAAY,IAAI,IAAI;AAAA,UAC3B,SAAS,kBAAkB,EAAE,yBAAyB,IAAI,IAAI,8BAA8B,IAAI,IAAI,2CAA2C,EAAE;AAAA,QACnJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,yBAAyB,UAAuC;AAC9E,SAAO,SAAS,IAAI,OAAK,YAAO,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AACpE;AAEO,SAAS,eAAe,QAAwB,KAAgC;AACrF,QAAM,SAA4B,CAAC;AAEnC,MAAI,CAAC,OAAO,MAAM,KAAK,GAAG;AACxB,WAAO,KAAK,EAAE,OAAO,QAAQ,SAAS,2BAA2B,CAAC;AAAA,EACpE;AAEA,MAAI,CAAC,OAAO,UAAU,QAAQ;AAC5B,WAAO,KAAK,EAAE,OAAO,YAAY,SAAS,mCAAmC,CAAC;AAC9E,WAAO;AAAA,EACT;AAGA,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,OAAO,OAAO,UAAU;AACjC,QAAI,MAAM,IAAI,IAAI,IAAI,GAAG;AACvB,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,2BAA2B,IAAI,IAAI,GAAG,CAAC;AAAA,IACrG;AACA,UAAM,IAAI,IAAI,IAAI;AAAA,EACpB;AAGA,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,OAAO,OAAO,UAAU;AACjC,UAAM,WAAW,MAAM,IAAI,IAAI,IAAI;AACnC,QAAI,UAAU;AACZ,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,QAAQ,IAAI,IAAI,oBAAoB,QAAQ,GAAG,CAAC;AAAA,IAC9G;AACA,UAAM,IAAI,IAAI,MAAM,IAAI,IAAI;AAAA,EAC9B;AAGA,aAAW,OAAO,OAAO,UAAU;AACjC,QAAI,CAAC,IAAI,MAAM,KAAK,EAAG,QAAO,KAAK,EAAE,OAAO,mBAAmB,SAAS,2BAA2B,CAAC;AACpG,QAAI,CAAC,IAAI,KAAK,KAAK,EAAG,QAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,SAAS,SAAS,kBAAkB,CAAC;AACpG,QAAI,CAAC,IAAI,KAAK,KAAK,EAAG,QAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,SAAS,SAAS,kBAAkB,CAAC;AACpG,QAAI,CAAC,IAAI,QAAQ,CAAC,CAAC,OAAO,KAAK,EAAE,SAAS,IAAI,IAAI,GAAG;AACnD,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,iBAAiB,IAAI,IAAI,4BAA4B,CAAC;AAAA,IACpH;AACA,QAAI,OAAO,IAAI,SAAS,YAAY,IAAI,QAAQ,GAAG;AACjD,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,iBAAiB,IAAI,IAAI,GAAG,CAAC;AAAA,IAC3F;AACA,QAAI,OAAO,IAAI,UAAU,YAAY,IAAI,QAAQ,GAAG;AAClD,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,WAAW,SAAS,kBAAkB,IAAI,KAAK,GAAG,CAAC;AAAA,IAC9F;AAGA,QAAI,IAAI,OAAO,CAACC,YAAWC,SAAQ,KAAK,IAAI,GAAG,CAAC,GAAG;AACjD,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,SAAS,SAAS,wBAAwB,IAAI,GAAG,GAAG,CAAC;AAAA,IAChG;AAGA,QAAI,IAAI,iBAAiB,QAAW;AAClC,UAAI,OAAO,IAAI,iBAAiB,YAAY,CAAC,IAAI,aAAa,QAAQ;AACpE,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,kBAAkB,SAAS,0CAA0C,CAAC;AAAA,MACjH,OAAO;AACL,cAAM,UAAU,wBAAwB,KAAK,IAAI,YAAY;AAC7D,YAAI;AACF,cAAI,QAAS,KAAI,OAAO,QAAQ,CAAC,GAAI,QAAQ,CAAC,KAAK,GAAG;AAAA,cACjD,KAAI,OAAO,IAAI,cAAc,GAAG;AAAA,QACvC,SAAS,GAAQ;AACf,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,kBAAkB,SAAS,kBAAkB,EAAE,OAAO,GAAG,CAAC;AAAA,QACrG;AAAA,MACF;AAAA,IACF;AAGA,QAAI,IAAI,iBAAiB,QAAW;AAClC,UAAI,OAAO,IAAI,iBAAiB,YAAY,CAAC,IAAI,aAAa,QAAQ;AACpE,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,kBAAkB,SAAS,0CAA0C,CAAC;AAAA,MACjH,OAAO;AACL,cAAM,UAAU,wBAAwB,KAAK,IAAI,YAAY;AAC7D,YAAI;AACF,cAAI,QAAS,KAAI,OAAO,QAAQ,CAAC,GAAI,QAAQ,CAAC,KAAK,GAAG;AAAA,cACjD,KAAI,OAAO,IAAI,cAAc,GAAG;AAAA,QACvC,SAAS,GAAQ;AACf,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,kBAAkB,SAAS,kBAAkB,EAAE,OAAO,GAAG,CAAC;AAAA,QACrG;AAAA,MACF;AAAA,IACF;AAGA,QAAI,IAAI,aAAa,WAAc,OAAO,IAAI,aAAa,YAAY,CAAC,IAAI,SAAS,KAAK,IAAI;AAC5F,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,cAAc,SAAS,sCAAsC,CAAC;AAAA,IACzG;AACA,QAAI,IAAI,eAAe,WAAc,OAAO,IAAI,eAAe,YAAY,CAAC,IAAI,WAAW,KAAK,IAAI;AAClG,aAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,gBAAgB,SAAS,wCAAwC,CAAC;AAAA,IAC7G;AAGA,QAAI,IAAI,aAAa;AACnB,YAAM,KAAK,IAAI;AACf,UAAI,GAAG,SAAS,SAAS,GAAG,SAAS,QAAQ;AAC3C,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,sBAAsB,SAAS,6BAA6B,GAAG,IAAI,6BAA6B,CAAC;AAAA,MAC5I;AACA,UAAI,GAAG,gBAAgB,WAAc,OAAO,GAAG,gBAAgB,YAAY,GAAG,cAAc,IAAI;AAC9F,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,6BAA6B,SAAS,4DAA4D,GAAG,WAAW,GAAG,CAAC;AAAA,MAC/J;AACA,UAAI,GAAG,SAAS,UAAU,GAAG,QAAQ,CAAC,GAAG,KAAK,WAAW,GAAG,GAAG;AAC7D,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,sBAAsB,SAAS,8CAA8C,GAAG,IAAI,IAAI,CAAC;AAAA,MACpI;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,MAAM,UAAU;AACzB,eAAW,OAAO,OAAO,KAAK,UAAU;AACtC,UAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,eAAO,KAAK,EAAE,OAAO,iBAAiB,SAAS,oBAAoB,GAAG,GAAG,CAAC;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,MAAM;AACf,UAAM,WAAW,IAAI,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC;AACnD,UAAM,YAAY,oBAAI,IAAoB;AAC1C,eAAW,OAAO,OAAO,SAAU,WAAU,IAAI,IAAI,MAAM,IAAI,IAAI;AACnE,eAAW,OAAO,OAAO,UAAU;AACjC,UAAI,SAAS,IAAI,IAAI,IAAI,EAAG;AAC5B,YAAM,WAAW,IAAI,OAAO;AAC5B,YAAM,WAAW,UAAU,IAAI,QAAQ;AACvC,UAAI,YAAY,aAAa,IAAI,MAAM;AACrC,eAAO,KAAK;AAAA,UACV,OAAO,YAAY,IAAI,IAAI;AAAA,UAC3B,SAAS,kBAAkB,QAAQ,OAAO,IAAI,IAAI,IAAI,gBAAgB,2BAA2B,QAAQ;AAAA,QAC3G,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,UAAU;AACnB,UAAM,WAAW,oBAAI,IAAY;AACjC,eAAW,OAAO,OAAO,UAAU;AACjC,UAAI,CAAC,IAAI,MAAM,KAAK,GAAG;AACrB,eAAO,KAAK,EAAE,OAAO,mBAAmB,SAAS,oCAAoC,CAAC;AACtF;AAAA,MACF;AACA,UAAI,SAAS,IAAI,IAAI,IAAI,GAAG;AAC1B,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,4BAA4B,IAAI,IAAI,GAAG,CAAC;AAAA,MACtG;AACA,eAAS,IAAI,IAAI,IAAI;AACrB,UAAI,CAAC,IAAI,KAAK,KAAK,GAAG;AACpB,eAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,SAAS,SAAS,kBAAkB,CAAC;AAAA,MAChF;AACA,UAAI,IAAI,aAAa;AACnB,cAAM,KAAK,IAAI;AACf,YAAI,GAAG,SAAS,SAAS,GAAG,SAAS,QAAQ;AAC3C,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,sBAAsB,SAAS,6BAA6B,GAAG,IAAI,GAAG,CAAC;AAAA,QAClH;AACA,aAAK,GAAG,SAAS,SAAS,GAAG,SAAS,YAAY,OAAO,IAAI,SAAS,YAAY,IAAI,QAAQ,IAAI;AAChG,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,UAAU,SAAS,iDAAiD,IAAI,IAAI,IAAI,CAAC;AAAA,QAC5H;AACA,YAAI,GAAG,SAAS,UAAU,GAAG,QAAQ,CAAC,GAAG,KAAK,WAAW,GAAG,GAAG;AAC7D,iBAAO,KAAK,EAAE,OAAO,YAAY,IAAI,IAAI,sBAAsB,SAAS,sBAAsB,CAAC;AAAA,QACjG;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,OAAO,QAAQ;AACxB,eAAW,OAAO,OAAO,KAAK,OAAO,MAAM,MAAM,GAAG;AAClD,UAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,eAAO,KAAK,EAAE,OAAO,gBAAgB,SAAS,oBAAoB,GAAG,GAAG,CAAC;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,UAAU;AACnB,eAAW,CAAC,SAAS,QAAQ,KAAK,OAAO,QAAQ,OAAO,QAAQ,GAAG;AACjE,UAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,SAAS,QAAQ;AAChD,eAAO,KAAK,EAAE,OAAO,YAAY,OAAO,IAAI,SAAS,YAAY,OAAO,+CAA+C,CAAC;AACxH;AAAA,MACF;AACA,iBAAW,OAAO,UAAU;AAC1B,YAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,iBAAO,KAAK,EAAE,OAAO,YAAY,OAAO,IAAI,SAAS,oBAAoB,GAAG,GAAG,CAAC;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,uBAAuB,QAAmC;AACxE,SAAO,OAAO,IAAI,OAAK,YAAO,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAClE;;;AEjNA,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAEtB,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgDd,SAAS,aAAa,MAAyB;AACpD,QAAM,OAAgB;AAAA,IACpB,MAAM,CAAC;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,aAAa;AAAA,IACb,mBAAmB;AAAA,EACrB;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,OAAO,KAAK,IAAI,CAAC;AAEvB,YAAQ,KAAK;AAAA,MACX,KAAK;AAAgB,aAAK,aAAa;AAAM;AAAK;AAAA,MAClD,KAAK;AAAgB,aAAK,OAAO;AAAM;AAAK;AAAA,MAC5C,KAAK;AAAgB,aAAK,OAAO,MAAM,MAAM,GAAG,KAAK,CAAC;AAAG;AAAK;AAAA,MAC9D,KAAK;AAAgB,aAAK,WAAW,MAAM,MAAM,GAAG;AAAG;AAAK;AAAA,MAC5D,KAAK;AAAgB,aAAK,UAAU;AAAM;AAAK;AAAA,MAC/C,KAAK;AAAgB,aAAK,OAAO;AAAM;AAAA,MACvC,KAAK;AAAgB,aAAK,OAAO;AAAO;AAAA,MACxC,KAAK;AAAgB,aAAK,cAAc,SAAS,QAAQ,IAAI,EAAE,KAAK;AAAsB;AAAK;AAAA,MAC/F,KAAK;AAAgB,aAAK,QAAQ;AAAM;AAAA,MACxC,KAAK;AAAsB,aAAK,YAAY;AAAM;AAAK;AAAA,MACvD,KAAK;AAAsB,aAAK,YAAY;AAAM;AAAK;AAAA,MACvD,KAAK;AAAsB,aAAK,WAAW;AAAM;AAAA,MACjD,KAAK;AAAsB,aAAK,WAAW;AAAO;AAAA,MAClD,KAAK;AAAsB,aAAK,kBAAkB,QAAQ;AAAa;AAAK;AAAA,MAC5E,KAAK;AAAsB,aAAK,SAAS;AAAM;AAAA,MAC/C,KAAK;AAAsB,aAAK,OAAO;AAAM;AAAA,MAC7C,KAAK;AAAsB,aAAK,cAAc,SAAS,QAAQ,IAAI,EAAE,KAAK;AAAsB;AAAK;AAAA,MACrG,KAAK;AAAsB,aAAK,UAAU;AAAO;AAAA,MACjD,KAAK;AAAsB,aAAK,SAAS;AAAM;AAAK;AAAA,MACpD,KAAK;AAAsB,aAAK,cAAc;AAAM;AAAA,MACpD,KAAK;AAAyB,aAAK,oBAAoB;AAAM;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,eACd,UACA,MACA,QACiB;AACjB,MAAI,SAAS;AAEb,MAAI,KAAK,SAAS;AAChB,UAAM,eAAe,QAAQ,WAAW,KAAK,OAAO;AACpD,QAAI,CAAC,cAAc;AACjB,YAAM,YAAY,OAAO,KAAK,QAAQ,YAAY,CAAC,CAAC;AACpD,YAAM,OAAO,UAAU,SAAS,cAAc,UAAU,KAAK,IAAI,CAAC,KAAK;AACvE,YAAM,IAAI,MAAM,qBAAqB,KAAK,OAAO,MAAM,IAAI,EAAE;AAAA,IAC/D;AACA,UAAM,MAAM,IAAI,IAAI,YAAY;AAChC,aAAS,OAAO,OAAO,OAAK,IAAI,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7C,WAAW,KAAK,UAAU;AACxB,UAAM,WAAW,IAAI,IAAI,KAAK,QAAQ;AACtC,aAAS,OAAO,OAAO,OAAK,SAAS,IAAI,EAAE,IAAI,CAAC;AAAA,EAClD,WAAW,KAAK,MAAM;AACpB,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AAAQ,iBAAS,OAAO,OAAO,OAAK,EAAE,SAAS,KAAK;AAAG;AAAA,MAC5D,KAAK;AAAQ,iBAAS,OAAO,OAAO,OAAK,EAAE,SAAS,KAAK;AAAG;AAAA,MAC5D;AAAa,iBAAS,OAAO,OAAO,OAAK,EAAE,KAAK,WAAW,KAAK,IAAK,CAAC;AAAG;AAAA,IAC3E;AAAA,EACF;AAEA,MAAI,KAAK,KAAK,QAAQ;AACpB,UAAM,UAAU,IAAI,IAAI,KAAK,IAAI;AACjC,aAAS,OAAO,OAAO,OAAK,CAAC,QAAQ,IAAI,EAAE,IAAI,CAAC;AAAA,EAClD;AAEA,SAAO;AACT;;;AC5JA,SAAS,SAAAC,cAAa;AACtB,SAAS,oBAAAC,mBAAkB,aAAAC,YAAW,eAAAC,cAAa,cAAAC,cAAY,YAAAC,iBAAgB;AAC/E,SAAS,YAAAC,iBAAgB;AACzB,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,WAAAC,gBAAe;AACxB,SAAS,mBAAAC,wBAAuB;;;ACNhC,OAAO,SAAS;AAChB,OAAO,UAAU;AASV,SAAS,UAAU,MAAc,OAAO,aAAa,YAAY,KAAwB;AAC9F,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAC5B,UAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,WAAO,WAAW,SAAS;AAC3B,WAAO,KAAK,WAAW,MAAM;AAAE,aAAO,QAAQ;AAAG,MAAAA,SAAQ,IAAI;AAAA,IAAG,CAAC;AACjE,WAAO,KAAK,SAAS,MAAM;AAAE,aAAO,QAAQ;AAAG,MAAAA,SAAQ,KAAK;AAAA,IAAG,CAAC;AAChE,WAAO,KAAK,WAAW,MAAM;AAAE,aAAO,QAAQ;AAAG,MAAAA,SAAQ,KAAK;AAAA,IAAG,CAAC;AAClE,WAAO,QAAQ,MAAM,IAAI;AAAA,EAC3B,CAAC;AACH;AAaA,eAAsB,eAAe,MAAgC;AAInE,aAAW,QAAQ,CAAC,WAAW,IAAI,GAAG;AACpC,QAAI,CAAE,MAAM,QAAQ,MAAM,IAAI,EAAI,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,MAAc,MAAgC;AAC7D,SAAO,IAAI,QAAQ,CAAAA,aAAW;AAC5B,UAAM,SAAS,IAAI,aAAa;AAChC,WAAO,KAAK,SAAS,CAAC,QAA+B;AAGnD,UAAI,IAAI,SAAS,gBAAgB,IAAI,SAAS,SAAU,CAAAA,SAAQ,KAAK;AAAA,UAChE,CAAAA,SAAQ,IAAI;AAAA,IACnB,CAAC;AACD,WAAO,KAAK,aAAa,MAAM,OAAO,MAAM,MAAMA,SAAQ,IAAI,CAAC,CAAC;AAChE,WAAO,OAAO,MAAM,IAAI;AAAA,EAC1B,CAAC;AACH;AAEO,SAAS,UACd,MACA,OAAyF,CAAC,GACxE;AAClB,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,SAAS,CAAC,SAAiB;AAC/B,QAAI,KAAK,WAAW,OAAW,QAAO,QAAQ,OAAO,OAAO;AAC5D,QAAI,MAAM,QAAQ,KAAK,MAAM,EAAG,QAAO,KAAK,OAAO,SAAS,IAAI;AAChE,WAAO,SAAS,KAAK;AAAA,EACvB;AACA,SAAO,IAAI,QAAQ,CAAAA,aAAW;AAC5B,UAAM,MAAM,KAAK,IAAI,EAAE,MAAM,MAAM,MAAM,SAAS,UAAU,GAAG,SAAO;AACpE,YAAM,KAAK,OAAO,IAAI,eAAe,YAAY,OAAO,IAAI,UAAU;AACtE,UAAI,OAAO;AACX,MAAAA,SAAQ,EAAE;AAAA,IACZ,CAAC;AACD,QAAI,GAAG,SAAS,MAAMA,SAAQ,KAAK,CAAC;AACpC,QAAI,GAAG,WAAW,MAAM;AAAE,UAAI,QAAQ;AAAG,MAAAA,SAAQ,KAAK;AAAA,IAAG,CAAC;AAAA,EAC5D,CAAC;AACH;AAGO,SAAS,YAAY,MAAc,IAA0C;AAClF,MAAI,IAAI,SAAS,QAAQ;AACvB,WAAO,UAAU,MAAM;AAAA,MACrB,MAAM,GAAG;AAAA,MAAM,QAAQ,GAAG;AAAA,MAAQ,MAAM,GAAG;AAAA,MAAM,WAAW,GAAG;AAAA,IACjE,CAAC;AAAA,EACH;AACA,SAAO,UAAU,MAAM,aAAa,IAAI,SAAS;AACnD;AAEO,SAAS,YAAY,MAAc,OAAgD,CAAC,GAAqB;AAC9G,QAAM,EAAE,UAAU,MAAO,WAAW,IAAK,IAAI;AAC7C,SAAO,IAAI,QAAQ,CAAAA,aAAW;AAC5B,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,QAAQ,MAAM;AAClB,gBAAU,IAAI,EAAE,KAAK,QAAM;AACzB,YAAI,GAAI,QAAOA,SAAQ,IAAI;AAC3B,YAAI,KAAK,IAAI,IAAI,QAAQ,QAAS,QAAOA,SAAQ,KAAK;AACtD,mBAAW,OAAO,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR,CAAC;AACH;AAEO,SAAS,aAAa,MAAe,eAAqC;AAC/E,MAAI,kBAAkB,OAAQ,QAAO;AACrC,MAAI,KAAM,QAAO;AACjB,SAAO,kBAAkB,aAAa,SAAS;AACjD;;;AC5GA,SAAS,cAAAC,aAAY,oBAAoB;AAKlC,SAAS,aAAa,UAAkB,UAAkC,CAAC,GAA2B;AAC3G,QAAM,MAAM,EAAE,GAAG,QAAQ;AACzB,MAAI,CAACA,YAAW,QAAQ,EAAG,QAAO;AAElC,aAAW,QAAQ,aAAa,UAAU,MAAM,EAAE,MAAM,IAAI,GAAG;AAC7D,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AACzC,UAAM,QAAQ,QAAQ,QAAQ,GAAG;AACjC,QAAI,UAAU,GAAI;AAClB,UAAM,MAAM,QAAQ,MAAM,GAAG,KAAK,EAAE,KAAK;AACzC,QAAI,MAAM,QAAQ,MAAM,QAAQ,CAAC,EAAE,KAAK;AACxC,QAAK,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,KAAO,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAI;AAC5F,YAAM,IAAI,MAAM,GAAG,EAAE;AAAA,IACvB;AACA,QAAI,CAAC,IAAI,GAAG,EAAG,KAAI,GAAG,IAAI;AAAA,EAC5B;AACA,SAAO;AACT;;;ACrBO,SAAS,UAAU,IAAoB;AAC5C,MAAI,CAAC,MAAM,KAAK,EAAG,QAAO;AAC1B,QAAM,IAAI,KAAK,MAAM,KAAK,GAAI;AAC9B,MAAI,IAAI,GAAI,QAAO,GAAG,CAAC;AACvB,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,MAAI,IAAI,GAAI,QAAO,GAAG,CAAC,IAAI,IAAI,EAAE;AACjC,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,MAAI,IAAI,GAAI,QAAO,GAAG,CAAC,IAAI,IAAI,EAAE;AACjC,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,SAAO,GAAG,CAAC,IAAI,IAAI,EAAE;AACvB;;;ACCO,SAAS,qBAAqB,MAA2C;AAC9E,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,UAAU,wBAAwB,KAAK,IAAI;AACjD,MAAI,SAAS;AACX,UAAM,QAAQ,QAAQ,CAAC,EAAG,SAAS,GAAG,IAAI,QAAQ,CAAC,IAAK,QAAQ,CAAC,IAAK;AACtE,QAAI;AACF,YAAM,KAAK,IAAI,OAAO,QAAQ,CAAC,GAAI,KAAK;AACxC,aAAO,EAAE,MAAM,CAAC,MAAc,GAAG,KAAK,CAAC,GAAG,OAAO,GAAG;AAAA,IACtD,QAAQ;AACN,YAAMC,SAAQ,KAAK,YAAY;AAC/B,aAAO,EAAE,MAAM,CAAC,MAAc,EAAE,YAAY,EAAE,SAASA,MAAK,GAAG,SAAS,KAAK;AAAA,IAC/E;AAAA,EACF;AACA,QAAM,QAAQ,KAAK,YAAY;AAC/B,SAAO,EAAE,MAAM,CAAC,MAAc,EAAE,YAAY,EAAE,SAAS,KAAK,EAAE;AAChE;AAMO,SAAS,eAAe,MAAwB;AACrD,QAAM,IAAI,KAAK,YAAY;AAE3B,MAAI,2EAA2E,KAAK,CAAC,KAAK,QAAQ,KAAK,IAAI,EAAG,QAAO;AACrH,MAAI,wCAAwC,KAAK,CAAC,KAAK,IAAI,KAAK,IAAI,EAAG,QAAO;AAC9E,SAAO;AACT;;;ACrCO,SAAS,cAAc,KAAiE;AAC7F,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,CAAC,IAAI,0CAA0C,KAAK,CAAC,IAAI,QAAQ;AAAA,EACvE;AACA,SAAO;AACT;;;ACTA,SAAS,cAAAC,aAAY,gBAAAC,eAAc,qBAAqB;AACxD,SAAS,kBAAkB;AAC3B,SAAS,QAAAC,aAAY;AAId,SAAS,aAAa,SAA0B;AACrD,QAAM,KAAKA,MAAK,SAAS,cAAc;AACvC,MAAI,CAACF,YAAW,EAAE,EAAG,QAAO;AAC5B,MAAI;AACF,UAAM,UAAU,WAAW,KAAK,EAAE,OAAOC,cAAaC,MAAK,SAAS,cAAc,CAAC,CAAC,EAAE,OAAO,KAAK;AAClG,UAAM,YAAYA,MAAK,IAAI,gBAAgB;AAC3C,QAAIF,YAAW,SAAS,KAAKC,cAAa,WAAW,MAAM,MAAM,QAAS,QAAO;AAAA,EACnF,QAAQ;AAAA,EAAoC;AAC5C,SAAO;AACT;AAGO,SAAS,kBAAkB,SAAuB;AACvD,MAAI;AACF,UAAM,UAAU,WAAW,KAAK,EAAE,OAAOA,cAAaC,MAAK,SAAS,cAAc,CAAC,CAAC,EAAE,OAAO,KAAK;AAClG,kBAAcA,MAAK,SAAS,gBAAgB,gBAAgB,GAAG,OAAO;AAAA,EACxE,QAAQ;AAAA,EAAoB;AAC9B;;;ACnBO,SAAS,iBAAiB,KAA8B;AAC7D,QAAM,QAAQ,IAAI,YAAY,CAAC;AAC/B,MAAI,CAAC,IAAI,OAAQ,QAAO,CAAC,GAAG,OAAO,GAAG,IAAI,IAAI;AAC9C,MAAI,IAAI,QAAQ,OAAQ,QAAO,CAAC,wBAAwB,IAAI,MAAM,IAAI,GAAG,OAAO,GAAG,IAAI,IAAI;AAC3F,SAAO,CAAC,GAAG,OAAO,GAAG,IAAI,IAAI;AAC/B;AAIO,SAAS,gBAAgB,KAAoB,SAAyD;AAC3G,QAAM,MAAM,EAAE,GAAG,SAAS,GAAI,IAAI,YAAY,CAAC,EAAG;AAClD,MAAI,IAAI,UAAU,IAAI,QAAQ,QAAQ;AACpC,UAAM,WAAW,IAAI,cAAc,KAAK;AACxC,UAAM,OAAO,wBAAwB,IAAI,MAAM;AAC/C,QAAI,CAAC,SAAS,SAAS,oBAAoB,GAAG;AAC5C,UAAI,cAAc,IAAI,WAAW,GAAG,QAAQ,IAAI,IAAI,KAAK;AAAA,IAC3D;AAAA,EACF;AACA,SAAO;AACT;;;ACnBO,SAAS,iBACd,OAAiB,UACjB,UACA,WACU;AACV,MAAI,aAAa,OAAQ,QAAO,MAAM,MAAM,EAAE,KAAK;AACnD,SAAO,MAAM,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAClC,QAAI,aAAa,OAAO;AACtB,cAAQ,WAAW,SAAS,CAAC,GAAG,OAAO,GAAG,KAAK,MAAM,WAAW,SAAS,CAAC,GAAG,OAAO,GAAG,KAAK;AAAA,IAC9F;AACA,YAAQ,UAAU,CAAC,GAAG,UAAU,MAAM,UAAU,CAAC,GAAG,UAAU;AAAA,EAChE,CAAC;AACH;AAIO,SAAS,eAAe,aAAqB,SAAiB,UAA0B;AAC7F,QAAM,WAAW,KAAK,IAAI,IAAI,YAAY;AAC1C,QAAM,WAAW,cAAc;AAC/B,SAAO,UAAU,IAAK,WAAW,UAAW,MAAM;AACpD;AAMO,SAAS,wBACd,UACA,iBACA,gBAAgB,IAChB,eAAe,IACN;AACT,MAAI,YAAY,cAAe,QAAO;AACtC,MAAI,WAAW,aAAc,QAAO;AACpC,SAAO;AACT;;;ACpCO,SAAS,aAAa,UAA4D;AACvF,QAAM,SAA0C,CAAC;AACjD,aAAW,KAAK,UAAU;AACxB,KAAC,OAAO,EAAE,KAAK,MAAM,CAAC,GAAG,KAAK,CAAC;AAAA,EACjC;AACA,SAAO;AACT;;;ACPO,IAAM,YAAY;AAAA,EACvB;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAS;AAAA,EAAW;AAAA,EACtC;AAAA,EAAO;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EACxC;AAAA,EAAW;AAAA,EAAW;AACxB;;;ACNA,SAAS,wBAAwB;AACjC,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,cAAAC,mBAAkB;;;ACF3B,SAAS,oBAA8C;AACvD,SAAS,uBAAuB;AAChC,SAAS,cAAAC,aAAY,YAAY,WAAW,WAAW,gBAAgB;AACvE,SAAS,eAAe;AACxB,SAAS,QAAAC,aAAY;AACrB,SAAS,eAAe;AAoEjB,SAAS,kBAAkB,aAA6B;AAC7D,QAAM,OAAO,YAAY,QAAQ,qBAAqB,GAAG,KAAK;AAC9D,SAAOA,MAAK,QAAQ,GAAG,UAAU,QAAQ,IAAI,OAAO;AACtD;AAEA,eAAsB,kBACpB,aACA,KACA,OAAyD,CAAC,GAC7B;AAC7B,QAAM,OAAO,KAAK,QAAQ,kBAAkB,WAAW;AACvD,YAAU,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAG5C,MAAID,YAAW,IAAI,GAAG;AACpB,QAAI;AACF,YAAM,KAAK,SAAS,IAAI;AACxB,UAAI,GAAG,SAAS,EAAG,YAAW,IAAI;AAAA,IACpC,QAAQ;AAAA,IAAsD;AAAA,EAChE;AAQA,QAAM,gBAAgB,oBAAI,IAAY;AACtC,QAAM,SAAS,aAAa,YAAU;AACpC,kBAAc,IAAI,MAAM;AACxB,WAAO,KAAK,SAAS,MAAM,cAAc,OAAO,MAAM,CAAC;AACvD,iBAAa,QAAQ,GAAG;AAAA,EAC1B,CAAC;AACD,QAAM,IAAI,QAAc,CAACE,UAAS,WAAW;AAC3C,WAAO,KAAK,SAAS,MAAM;AAC3B,WAAO,OAAO,MAAM,MAAM;AACxB,aAAO,IAAI,SAAS,MAAM;AAC1B,UAAI;AAAE,kBAAU,MAAM,GAAK;AAAA,MAAG,QAAQ;AAAA,MAA+C;AACrF,WAAK,QAAQ,8BAAuB,IAAI,EAAE;AAC1C,MAAAA,SAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,QAAQ;AAEZ,iBAAW,QAAQ,cAAe,MAAK,QAAQ;AAC/C,oBAAc,MAAM;AACpB,YAAM,IAAI,QAAc,CAAAA,aAAW,OAAO,MAAM,MAAMA,SAAQ,CAAC,CAAC;AAChE,UAAIF,YAAW,IAAI,GAAG;AACpB,YAAI;AAAE,qBAAW,IAAI;AAAA,QAAG,QAAQ;AAAA,QAAe;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,QAAgB,KAAuB;AAC3D,QAAM,KAAK,gBAAgB,EAAE,OAAO,OAAO,CAAC;AAC5C,QAAM,SAAS,oBAAI,IAAgB;AAEnC,SAAO,GAAG,SAAS,MAAM;AACvB,eAAW,SAAS,OAAQ,OAAM;AAClC,WAAO,MAAM;AAAA,EACf,CAAC;AAED,KAAG,GAAG,QAAQ,OAAO,SAAiB;AACpC,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAI;AACJ,QAAI;AACF,YAAM,KAAK,MAAM,IAAI;AAAA,IACvB,SAAS,GAAQ;AACf,cAAQ,QAAQ,EAAE,OAAO,EAAE,MAAM,QAAQ,SAAS,gBAAgB,EAAE,OAAO,GAAG,EAAE,CAAC;AACjF;AAAA,IACF;AACA,QAAI,OAAO,IAAI,WAAW,UAAU;AAClC,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,EAAE,MAAM,QAAQ,SAAS,kBAAkB,EAAE,CAAC;AACnF;AAAA,IACF;AACA,UAAM,SAAU,IAAI,UAAU,CAAC;AAC/B,QAAI,IAAI,WAAW,iBAAiB,IAAI,WAAW,iBAAiB;AAClE,UAAI;AACF,cAAM,aAAa,QAAQ,KAAyC,QAAQ,KAAK,MAAM;AAAA,MACzF,SAAS,GAAQ;AACf,gBAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,EAAE,MAAM,QAAQ,SAAS,EAAE,WAAW,OAAO,CAAC,EAAE,EAAE,CAAC;AAAA,MAC1F;AACA;AAAA,IACF;AACA,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,IAAI,QAAQ,QAAQ,GAAG;AACrD,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,CAAC;AAAA,IACxC,SAAS,GAAQ;AACf,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,EAAE,MAAM,QAAQ,SAAS,EAAE,WAAW,OAAO,CAAC,EAAE,EAAE,CAAC;AAAA,IAC1F;AAAA,EACF,CAAC;AACD,SAAO,GAAG,SAAS,MAAM;AAAA,EAA8B,CAAC;AAC1D;AAEA,eAAe,aACb,QACA,KACA,QACA,KACA,QACe;AACf,MAAI,IAAI,WAAW,eAAe;AAChC,UAAM,SAAS,OAAO,KAAK,KAAK,OAAO,SAAS;AAChD,UAAM,UAAU,UAAU,OAAO,cAAc,QAAQ,KAAK,IAAI;AAChE,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAM,OAAO,OAAO,MAAM,KAAK,EAAE,CAAC,CAAC;AAErE,YAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,QAAQ,EAAE,IAAI,KAAK,EAAE,CAAC;AAGpD,QAAI,SAAS;AACX,YAAM,QAAQ,MAAM,IAAI,SAAS,SAAS,IAAI;AAC9C,iBAAW,KAAK,OAAO;AACrB,gBAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,OAAO,MAAM,EAAE,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,UAAU,SAAS,CAAC,KAAK,SAAS;AAClD,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,IAC/D,CAAC;AACD,WAAO,IAAI,KAAK;AAAA,EAElB,OAAO;AAEL,YAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,QAAQ,EAAE,IAAI,KAAK,EAAE,CAAC;AAGpD,UAAM,WAA2C,CAAC;AAClD,eAAW,CAAC,MAAM,EAAE,KAAK,IAAI,OAAO,GAAG;AACrC,eAAS,KAAK,eAAe,MAAM,EAAE,CAAC;AAAA,IACxC;AACA,QAAI,SAAS,QAAQ;AACnB,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,UAAU,MAAM,SAAS,CAAC;AAAA,IACjE;AAEA,UAAM,QAAQ,IAAI,YAAY,CAAC,MAAM,UAAU;AAC7C,cAAQ,QAAQ,EAAE,IAAI,IAAI,IAAI,OAAO,UAAU,MAAM,CAAC,eAAe,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,IACtF,CAAC;AACD,WAAO,IAAI,KAAK;AAAA,EAClB;AACF;AAEA,SAAS,eAAe,MAAc,IAA2C;AAC/E,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,GAAG;AAAA,IACX,QAAQ,GAAG;AAAA,IACX,MAAM,GAAG,IAAI;AAAA,IACb,MAAM,GAAG,IAAI;AAAA,IACb,OAAO,GAAG,IAAI;AAAA,IACd,QAAQ,GAAG;AAAA,IACX,UAAU,GAAG;AAAA,IACb,KAAK,GAAG;AAAA,IACR,WAAW,GAAG;AAAA,EAChB;AACF;AAEA,SAAS,QAAQ,QAAgB,SAAuB;AACtD,MAAI,OAAO,SAAU,QAAO,MAAM,KAAK,UAAU,OAAO,IAAI,IAAI;AAClE;AAEA,eAAe,SACb,QACA,QACA,KACkB;AAClB,UAAQ,QAAQ;AAAA,IACd,KAAK,UAAU;AACb,YAAM,MAAsC,CAAC;AAC7C,iBAAW,CAAC,MAAM,EAAE,KAAK,IAAI,OAAO,GAAG;AACrC,YAAI,KAAK,eAAe,MAAM,EAAE,CAAC;AAAA,MACnC;AACA,aAAO,EAAE,UAAU,KAAK,OAAO,IAAI,aAAa,EAAE;AAAA,IACpD;AAAA,IACA,KAAK;AACH,aAAO,MAAM,IAAI,SAAS;AAAA,IAC5B,KAAK;AACH,aAAO,IAAI,QAAQ;AAAA,IACrB,KAAK,WAAW;AACd,YAAM,MAAM,cAAc,OAAO,KAAK,KAAK,OAAO,SAAS,GAAG,KAAK;AACnE,YAAM,IAAI,QAAQ,GAAG;AACrB,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,MAAM,cAAc,OAAO,KAAK,KAAK,OAAO,SAAS,GAAG,KAAK;AACnE,UAAI,KAAK,GAAG;AACZ,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,MAAM,cAAc,OAAO,KAAK,KAAK,OAAO,SAAS,GAAG,KAAK;AACnE,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAQ,OAAO,OAAO,OAAO,KAAK,GAAG,CAAC,CAAC;AAC1E,aAAO,EAAE,OAAO,MAAM,IAAI,SAAS,KAAK,KAAK,EAAE;AAAA,IACjD;AAAA,IACA,KAAK;AACH,aAAO,EAAE,IAAI,MAAM,IAAI,KAAK,IAAI,EAAE;AAAA,IACpC;AACE,YAAM,IAAI,MAAM,mBAAmB,MAAM,EAAE;AAAA,EAC/C;AACF;AAEA,SAAS,cAAc,GAAY,WAA2B;AAC5D,MAAI,OAAO,MAAM,YAAY,CAAC,EAAE,KAAK,GAAG;AACtC,UAAM,IAAI,MAAM,UAAU,SAAS,8BAA8B;AAAA,EACnE;AACA,SAAO;AACT;;;ADlRO,SAAS,cAAc,aAAqB,cAA+B;AAChF,SAAO,gBAAgB,kBAAkB,WAAW;AACtD;AAGO,SAAS,mBAAmB,YAAoB,aAA2B;AAChF,MAAI,CAACG,YAAW,UAAU,GAAG;AAC3B,UAAM,IAAI;AAAA,MACR,qCAAqC,WAAW;AAAA;AAAA,IAClD;AAAA,EACF;AACF;AAGO,SAAS,QACd,YACA,QACA,SAAkC,CAAC,GACjB;AAClB,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,QAAI,UAAU;AACd,UAAM,OAAO,CAAC,QAAe;AAAE,UAAI,CAAC,SAAS;AAAE,kBAAU;AAAM,eAAO,GAAG;AAAA,MAAG;AAAA,IAAE;AAC9E,UAAM,KAAK,CAAC,MAAe;AAAE,UAAI,CAAC,SAAS;AAAE,kBAAU;AAAM,QAAAA,SAAQ,CAAC;AAAA,MAAG;AAAA,IAAE;AAE3E,UAAM,IAAI,iBAAiB,UAAU;AACrC,UAAM,KAAKC,iBAAgB,EAAE,OAAO,EAAE,CAAC;AAIvC,MAAE,GAAG,SAAS,IAAI;AAClB,OAAG,GAAG,SAAS,IAAI;AACnB,OAAG,KAAK,QAAQ,OAAK;AACnB,QAAE,IAAI;AACN,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,CAAC;AACxB,YAAI,IAAI,MAAO,MAAK,IAAI,MAAM,IAAI,MAAM,WAAW,OAAO,IAAI,KAAK,CAAC,CAAC;AAAA,YAChE,IAAG,IAAI,MAAM;AAAA,MACpB,SAAS,GAAQ;AACf,aAAK,CAAC;AAAA,MACR;AAAA,IACF,CAAC;AACD,MAAE,MAAM,KAAK,UAAU,EAAE,IAAI,GAAG,QAAQ,OAAO,CAAC,IAAI,IAAI;AAAA,EAC1D,CAAC;AACH;AAUO,SAAS,WACd,YACA,QACA,QACA,SACA,SACY;AACZ,QAAM,IAAI,iBAAiB,UAAU;AACrC,QAAM,KAAKA,iBAAgB,EAAE,OAAO,EAAE,CAAC;AACvC,MAAI,UAAU;AAKd,QAAM,QAAQ,CAAC,QAAe,UAAU,GAAG;AAC3C,IAAE,GAAG,SAAS,KAAK;AACnB,KAAG,GAAG,SAAS,KAAK;AACpB,IAAE,MAAM,KAAK,UAAU,EAAE,IAAI,GAAG,QAAQ,OAAO,CAAC,IAAI,IAAI;AAExD,KAAG,GAAG,QAAQ,OAAK;AACjB,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,CAAC;AACxB,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,YAAI,IAAI,OAAO;AAAE,oBAAU,IAAI,MAAM,IAAI,MAAM,WAAW,OAAO,IAAI,KAAK,CAAC,CAAC;AAAG,YAAE,QAAQ;AAAA,QAAG;AAC5F;AAAA,MACF;AACA,UAAI,IAAI,MAAO,SAAQ,GAAkB;AAAA,IAC3C,QAAQ;AAAA,IAAgC;AAAA,EAC1C,CAAC;AAED,SAAO,MAAM,EAAE,QAAQ;AACzB;;;AE7FA,SAAS,SAAAC,cAAa;AACtB,SAAS,iBAAAC,gBAAe,gBAAAC,eAAc,cAAAC,cAAY,cAAAC,aAAY,aAAAC,YAAW,wBAAwB;AACjG,SAAS,QAAAC,aAAY;AACrB,SAAS,WAAAC,UAAS,UAAU,SAAS,YAAY;AACjD,SAAS,cAAc,aAAa;AACpC,SAAS,mBAAAC,wBAAuB;;;ACLhC,SAAS,QAAAC,aAAY;;;ACArB,SAAS,aAAa;AACtB,SAAS,cAAAC,mBAAkB;AAGpB,SAAS,eACd,KAAa,KACb,OACkB;AAClB,MAAI,CAACC,YAAW,GAAG,GAAG;AACpB,YAAQ,+BAA0B,GAAG,EAAE;AACvC,WAAO,QAAQ,QAAQ,KAAK;AAAA,EAC9B;AACA,MAAI,CAAC,aAAa,GAAG,GAAG;AACtB,YAAQ,gCAA2B;AACnC,WAAO,QAAQ,QAAQ,IAAI;AAAA,EAC7B;AACA,UAAQ,0BAAmB;AAC3B,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAE5B,UAAM,UAAU,QAAQ,aAAa,UAAU,YAAY;AAC3D,UAAM,OAAO,MAAM,SAAS,CAAC,SAAS,GAAG,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,UAAU,MAAM,EAAE,CAAC;AAC1F,QAAI,SAAS;AACb,SAAK,QAAQ,GAAG,QAAQ,CAAC,MAAc;AAAE,gBAAU,EAAE,SAAS;AAAA,IAAG,CAAC;AAClE,SAAK,GAAG,SAAS,UAAQ;AACvB,UAAI,SAAS,GAAG;AACd,gBAAQ,8BAAyB,OAAO,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE;AACxD,QAAAA,SAAQ,KAAK;AAAA,MACf,OAAO;AACL,0BAAkB,GAAG;AACrB,gBAAQ,2BAAsB;AAC9B,QAAAA,SAAQ,IAAI;AAAA,MACd;AAAA,IACF,CAAC;AACD,SAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,cAAQ,uBAAkB,IAAI,OAAO,EAAE;AACvC,MAAAA,SAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH,CAAC;AACH;;;ACtCA,SAAS,SAAAC,cAAgC;AACzC,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,OAAM,WAAAC,gBAAe;;;ACAvB,SAAS,WAAW,QAAgC;AACzD,MAAI,MAAM;AACV,SAAO;AAAA,IACL,KAAK,OAAe;AAClB,aAAO,MAAM,SAAS;AACtB,UAAI;AACJ,cAAQ,MAAM,IAAI,QAAQ,IAAI,OAAO,IAAI;AACvC,cAAM,OAAO,IAAI,MAAM,GAAG,GAAG,EAAE,QAAQ,OAAO,EAAE;AAChD,cAAM,IAAI,MAAM,MAAM,CAAC;AACvB,YAAI,KAAK,OAAQ,QAAO,IAAI;AAAA,MAC9B;AAAA,IACF;AAAA,IACA,QAAQ;AACN,UAAI,IAAI,QAAQ;AAAE,eAAO,GAAG;AAAG,cAAM;AAAA,MAAI;AAAA,IAC3C;AAAA,EACF;AACF;AAGO,SAAS,oBAAoB,SAA4C;AAC9E,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,UAAU,wBAAwB,KAAK,OAAO;AACpD,MAAI;AACF,QAAI,QAAS,QAAO,IAAI,OAAO,QAAQ,CAAC,GAAI,QAAQ,CAAC,KAAK,GAAG;AAC7D,WAAO,IAAI,OAAO,SAAS,GAAG;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIO,SAAS,kBAAkB,MAA0B;AAC1D,QAAM,aAAa,oBAAI,IAAI,CAAC,WAAW,cAAc,CAAC;AACtD,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,WAAW,IAAI,CAAC,GAAG;AACrB,YAAM,IAAI,KAAK,IAAI,CAAC;AACpB,UAAI,KAAK,CAAC,EAAE,WAAW,GAAG,GAAG;AAAE,YAAI,KAAK,CAAC;AAAG;AAAA,MAAK;AACjD;AAAA,IACF;AACA,UAAM,KAAK,EAAE,QAAQ,GAAG;AACxB,QAAI,KAAK,KAAK,WAAW,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG;AAC5C,UAAI,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,eAAe;AACrB,IAAM,kBAAkB;;;AD7BxB,IAAM,UAAN,MAAc;AAAA,EACF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAmB;AAC7B,SAAK,UAAU,KAAK;AACpB,SAAK,MAAM,KAAK;AAChB,SAAK,QAAQ,KAAK;AAClB,SAAK,QAAQ,KAAK;AAClB,SAAK,SAAS,KAAK;AACnB,SAAK,YAAY,KAAK;AACtB,SAAK,UAAU,KAAK;AAAA,EACtB;AAAA,EAEA,MAAM,MAAM,KAAoB,UAAkB,YAAY,OAAsB;AAClF,UAAM,MAAMC,MAAK,KAAK,SAAS,IAAI,GAAG;AAKtC,QAAI,IAAI,SAAS,OAAO;AACtB,YAAM,WAAW,MAAM,eAAe,IAAI,IAAI;AAC9C,UAAI,CAAC,YAAY,CAAC,WAAW;AAC3B,aAAK,IAAI,IAAI,MAAM,eAAU,IAAI,IAAI,mCAA8B,QAAQ;AAC3E,aAAK,mBAAmB,KAAK,QAAQ;AACrC;AAAA,MACF;AAAA,IACF;AAGA,QAAI,IAAI,UAAU;AAChB,YAAM,QAAQ,MAAM,KAAK,YAAY,KAAK,KAAK,QAAQ;AACvD,UAAI,CAAC,OAAO;AACV,aAAK,mBAAmB,KAAK,QAAQ;AACrC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,iBAAiB,GAAG;AAGjC,UAAM,oBAAoB,kBAAkB,IAAI,EAC7C,OAAO,OAAK,CAACC,YAAWC,SAAQ,KAAK,CAAC,CAAC,CAAC;AAC3C,QAAI,kBAAkB,QAAQ;AAC5B,WAAK,IAAI,IAAI,MAAM,+BAA0B,kBAAkB,KAAK,IAAI,CAAC,IAAI,QAAQ;AACrF,WAAK,mBAAmB,KAAK,QAAQ;AACrC;AAAA,IACF;AAEA,UAAM,MAAM,gBAAgB,KAAK,KAAK,GAAG;AACzC,UAAM,OAAOC,OAAM,IAAI,KAAK,MAAM,EAAE,KAAK,KAAK,UAAU,MAAM,OAAO,CAAC,UAAU,QAAQ,MAAM,EAAE,CAAC;AAEjG,UAAM,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI;AACpC,UAAM,QAAsB;AAAA,MAC1B;AAAA,MAAK;AAAA,MAAM,KAAK,KAAK,OAAO;AAAA,MAC5B,QAAQ;AAAA,MAAY,QAAQ;AAAA,MAC5B,QAAQ,MAAM,UAAU;AAAA,MACxB,UAAU,MAAM,YAAY;AAAA,MAC5B,WAAW,KAAK,IAAI;AAAA,MACpB,iBAAiB;AAAA,MACjB;AAAA,IACF;AACA,SAAK,MAAM,IAAI,IAAI,MAAM,KAAK;AAC9B,SAAK,MAAM,IAAI,IAAI;AACnB,SAAK,OAAO,cAAc,IAAI,MAAM,KAAK;AAEzC,SAAK,UAAU,MAAM,KAAK,OAAO,QAAQ;AACzC,SAAK,iBAAiB,MAAM,KAAK,OAAO,QAAQ;AAGhD,QAAI,IAAI,YAAY;AAClB,YAAM,YAAY,KAAK,gBAAgB,KAAK,KAAK,KAAK,QAAQ;AAAA,IAChE;AAEA,SAAK,IAAI,IAAI,MAAM,YAAY,yBAAkB,IAAI,IAAI,MAAM,uBAAgB,IAAI,IAAI,KAAK,QAAQ;AAAA,EACtG;AAAA,EAEQ,UAAU,MAAoB,KAAoB,OAAqB,UAAwB;AACrG,UAAM,aAAa,oBAAoB,IAAI,YAAY;AACvD,UAAM,mBAAmB,CAAC,SAAiB;AACzC,UAAI,CAAC,cAAc,MAAM,WAAW,KAAM;AAC1C,UAAI,WAAW,KAAK,IAAI,GAAG;AACzB,cAAM,SAAS;AACf,YAAI,MAAM,WAAW,WAAY,OAAM,SAAS;AAChD,aAAK,OAAO,cAAc,IAAI,MAAM,KAAK;AAAA,MAC3C;AAAA,IACF;AACA,UAAM,aAAa,oBAAoB,IAAI,YAAY;AACvD,UAAM,gBAAgB,CAAC,SAAiB,aAAa,WAAW,KAAK,IAAI,IAAI;AAE7E,UAAM,YAAY,WAAW,UAAQ;AAAE,uBAAiB,IAAI;AAAG,WAAK,IAAI,IAAI,MAAM,MAAM,QAAQ;AAAA,IAAG,CAAC;AACpG,UAAM,YAAY,WAAW,UAAQ;AACnC,UAAI,cAAc,IAAI,EAAG,OAAM,UAAU;AACzC,uBAAiB,IAAI;AACrB,WAAK,IAAI,IAAI,MAAM,MAAM,QAAQ;AAAA,IACnC,CAAC;AAED,SAAK,QAAQ,GAAG,QAAQ,CAAC,MAAc,UAAU,KAAK,CAAC,CAAC;AACxD,SAAK,QAAQ,GAAG,QAAQ,CAAC,MAAc,UAAU,KAAK,CAAC,CAAC;AACxD,SAAK,QAAQ,GAAG,OAAO,MAAM,UAAU,MAAM,CAAC;AAC9C,SAAK,QAAQ,GAAG,OAAO,MAAM,UAAU,MAAM,CAAC;AAAA,EAChD;AAAA,EAEQ,iBAAiB,MAAoB,KAAoB,OAAqB,UAAwB;AAC5G,SAAK,GAAG,SAAS,UAAQ;AACvB,WAAK,MAAM,OAAO,IAAI;AACtB,WAAK,UAAU,cAAc,KAAK;AAClC,UAAI,MAAM,iBAAiB;AAAE,cAAM,kBAAkB;AAAO;AAAA,MAAQ;AACpE,UAAI,SAAS,GAAG;AACd,cAAM,SAAS;AAAW,cAAM,SAAS;AACzC,aAAK,OAAO,cAAc,IAAI,MAAM,KAAK;AACzC;AAAA,MACF;AACA,YAAM,SAAS;AAAW,YAAM,SAAS;AACzC,WAAK,IAAI,IAAI,MAAM,2BAAsB,IAAI,IAAI,QAAQ;AACzD,WAAK,OAAO,cAAc,IAAI,MAAM,KAAK;AACzC,WAAK,QAAQ,KAAK,OAAO,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH;AAAA,EAEQ,YAAY,KAAoB,KAAa,UAAoC;AACvF,SAAK,IAAI,IAAI,MAAM,uBAAgB,IAAI,QAAQ,IAAI,QAAQ;AAC3D,WAAO,IAAI,QAAQ,SAAO;AACxB,YAAM,QAAQ,QAAQ,aAAa;AACnC,YAAM,QAAQ,QAAQ,YAAY;AAClC,YAAM,YAAY,QAAQ,OAAO;AACjC,YAAM,MAAM,gBAAgB,KAAK,KAAK,GAAG;AACzC,YAAM,QAAQA,OAAM,OAAO,CAAC,WAAW,IAAI,QAAS,GAAG,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,QAAQ,MAAM,EAAE,CAAC;AAEtG,YAAM,SAAS,WAAW,UAAQ,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,IAAI,QAAQ,CAAC;AACjF,YAAM,SAAS,WAAW,UAAQ,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,IAAI,QAAQ,CAAC;AACjF,YAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AACtD,YAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AAEtD,YAAM,GAAG,SAAS,SAAO;AACvB,aAAK,IAAI,IAAI,MAAM,kBAAa,IAAI,OAAO,IAAI,QAAQ;AACvD,YAAI,KAAK;AAAA,MACX,CAAC;AACD,YAAM,GAAG,SAAS,UAAQ;AACxB,eAAO,MAAM;AAAG,eAAO,MAAM;AAC7B,YAAI,SAAS,GAAG;AACd,eAAK,IAAI,IAAI,MAAM,uBAAkB,QAAQ;AAC7C,cAAI,IAAI;AAAA,QACV,OAAO;AACL,eAAK,IAAI,IAAI,MAAM,mCAA8B,IAAI,IAAI,QAAQ;AACjE,cAAI,KAAK;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,gBAAgB,KAAoB,KAAa,KAA6B,UAAgC;AACpH,SAAK,IAAI,IAAI,MAAM,yBAAkB,IAAI,UAAU,IAAI,QAAQ;AAC/D,UAAM,QAAQ,QAAQ,aAAa;AACnC,UAAM,QAAQ,QAAQ,YAAY;AAClC,UAAM,YAAY,QAAQ,OAAO;AACjC,UAAM,QAAQA,OAAM,OAAO,CAAC,WAAW,IAAI,UAAW,GAAG;AAAA,MACvD;AAAA,MAAK;AAAA,MAAK,UAAU;AAAA,MAAM,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,IAC5D,CAAC;AACD,UAAM,SAAS,WAAW,UAAQ,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,IAAI,QAAQ,CAAC;AACjF,UAAM,SAAS,WAAW,UAAQ,KAAK,IAAI,IAAI,MAAM,WAAW,IAAI,IAAI,QAAQ,CAAC;AACjF,UAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AACtD,UAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,OAAO,KAAK,CAAC,CAAC;AACtD,UAAM,GAAG,SAAS,SAAO,KAAK,IAAI,IAAI,MAAM,kBAAa,IAAI,OAAO,IAAI,QAAQ,CAAC;AACjF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAIQ,mBAAmB,KAAoB,UAAwB;AACrE,UAAM,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI;AACpC,SAAK,MAAM,IAAI,IAAI,MAAM;AAAA,MACvB;AAAA,MAAK,MAAM;AAAA,MAAM,KAAK;AAAA,MACtB,QAAQ;AAAA,MAAW,QAAQ;AAAA,MAC3B,QAAQ,MAAM,UAAU;AAAA,MACxB,UAAU,MAAM,YAAY;AAAA,MAC5B,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB;AAAA,IACF,CAAC;AACD,SAAK,OAAO,cAAc,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,IAAI,CAAE;AAAA,EAC/D;AAAA,EAEQ,IAAI,MAAc,MAAc,UAAwB;AAC9D,SAAK,OAAO,MAAM,MAAM,MAAM,QAAQ;AAAA,EACxC;AACF;;;AErMO,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAqB;AAC/B,SAAK,QAAQ,KAAK;AAClB,SAAK,SAAS,KAAK;AACnB,SAAK,UAAU,KAAK;AACpB,SAAK,YAAY,KAAK;AAAA,EACxB;AAAA,EAEA,MAAM,QAAQ,MAA6B;AACzC,UAAM,KAAK,KAAK,MAAM,IAAI,IAAI;AAC9B,QAAI,CAAC,GAAI;AACT,SAAK,UAAU,KAAK,IAAI;AAExB,OAAG,WAAW;AACd,UAAM,QAAQ,GAAG,OAAO,OAAO;AAC/B,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,KAAK,CAAC;AAC3C,UAAM,KAAK,QAAQ,MAAM,GAAG,KAAK,GAAG,UAAU,IAAI;AAClD,SAAK,OAAO,MAAM,MAAM,4BAAqB,GAAG,QAAQ;AAAA,EAC1D;AAAA,EAEA,oBAAoB,KAAoB,OAAqB,UAAwB;AACnF,QAAI,MAAM,YAAY,cAAc;AAClC,WAAK,OAAO,MAAM,IAAI,MAAM,+BAA0B,QAAQ;AAC9D;AAAA,IACF;AACA,UAAM;AACN,UAAM,QAAQ,kBAAkB,KAAK,IAAI,GAAG,MAAM,WAAW,CAAC;AAC9D,SAAK,OAAO,MAAM,IAAI,MAAM,0BAAmB,MAAM,QAAQ,IAAI,YAAY,OAAO,KAAK,SAAS,QAAQ;AAC1G,eAAW,MAAM,KAAK,KAAK,QAAQ,MAAM,KAAK,UAAU,IAAI,GAAG,KAAK;AAAA,EACtE;AACF;;;AC3CO,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EACA;AAAA,EAEjB,YAAY,MAAwB;AAClC,SAAK,QAAQ,KAAK;AAClB,SAAK,SAAS,KAAK;AAAA,EACrB;AAAA,EAEA,MAAM,WAA0B;AAC9B,eAAW,CAAC,MAAM,EAAE,KAAK,KAAK,OAAO;AACnC,UAAI,CAAC,GAAG,OAAO,GAAG,WAAW,QAAQ;AACnC,WAAG,SAAS,GAAG,WAAW,SAAS,SAAS;AAC5C;AAAA,MACF;AAGA,YAAM,iBAAiB,GAAG,IAAI,aAAa,eAAe,KAAK;AAC/D,UAAI,gBAAgB,KAAK,GAAG,aAAa,KAAK,IAAI,IAAI,GAAG,YAAY,eAAe;AAClF;AAAA,MACF;AACA,YAAM,OAAO,MAAM,YAAY,GAAG,IAAI,MAAM,GAAG,IAAI,WAAW;AAC9D,YAAM,OAAO,GAAG;AAChB,SAAG,SAAS,aAAa,MAAM,GAAG,MAAM;AACxC,UAAI,GAAG,WAAW,QAAQ,GAAG,WAAW,WAAY,IAAG,SAAS;AAChE,UAAI,SAAS,GAAG,OAAQ,MAAK,OAAO,cAAc,MAAM,EAAE;AAAA,IAC5D;AAAA,EACF;AACF;;;AC1BO,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAqB;AAC/B,SAAK,QAAQ,KAAK;AAClB,SAAK,QAAQ,KAAK;AAClB,SAAK,WAAW,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,MAAoB;AACvB,UAAM,KAAK,KAAK,MAAM,IAAI,IAAI;AAC9B,QAAI,CAAC,IAAI,QAAQ,CAAC,GAAG,IAAK;AAC1B,OAAG,kBAAkB;AACrB,SAAK,SAAS,SAAS,GAAG,GAAG;AAC7B,SAAK,cAAc,EAAE;AAAA,EACvB;AAAA;AAAA;AAAA,EAIA,cAAc,OAA2B;AACvC,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,CAAC,GAAG,IAAK;AACpB,QAAI;AAAE,WAAK,SAAS,SAAS,GAAG,GAAG;AAAA,IAAG,QAAQ;AAAA,IAAqB;AACnE,UAAM,YAAY;AAAA,EACpB;AAAA;AAAA;AAAA,EAIA,MAAM,QAAQ,OAAmC,CAAC,GAAkB;AAClE,UAAM,QAAQ,KAAK,iBAAiB;AACpC,UAAM,QAAQ,CAAC,GAAG,KAAK,KAAK;AAC5B,QAAI,CAAC,MAAM,OAAQ;AAEnB,eAAW,QAAQ,OAAO;AACxB,YAAM,KAAK,KAAK,gBAAgB,IAAI;AACpC,UAAI,IAAI;AACN,WAAG,kBAAkB;AACrB,aAAK,cAAc,EAAE;AAAA,MACvB;AACA,UAAI,KAAK,IAAK,MAAK,SAAS,SAAS,KAAK,GAAG;AAAA,IAC/C;AAGA,eAAW,MAAM,KAAK,MAAM,OAAO,EAAG,MAAK,cAAc,EAAE;AAE3D,UAAM,QAAQ,MAAM;AAAA,MAAI,OACtB,EAAE,aAAa,QAAQ,EAAE,eAAe,OACpC,QAAQ,QAAQ,IAChB,IAAI,QAAc,CAAAC,aAAW,EAAE,KAAK,SAAS,MAAMA,SAAQ,CAAC,CAAC;AAAA,IACnE;AAEA,QAAI,WAAW;AACf,UAAM,QAAQ,KAAK;AAAA,MACjB,QAAQ,IAAI,KAAK;AAAA,MACjB,IAAI,QAAc,CAAAA,aAAW,WAAW,MAAM;AAAE,mBAAW;AAAM,QAAAA,SAAQ;AAAA,MAAG,GAAG,KAAK,CAAC;AAAA,IACvF,CAAC;AAED,QAAI,UAAU;AACZ,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,OAAO,KAAK,aAAa,QAAQ,KAAK,eAAe,MAAM;AAClE,eAAK,SAAS,SAAS,KAAK,KAAK,SAAS;AAAA,QAC5C;AAAA,MACF;AACA,YAAM,QAAQ,KAAK;AAAA,QACjB,QAAQ,IAAI,KAAK;AAAA,QACjB,IAAI,QAAc,CAAAA,aAAW,WAAWA,UAAS,GAAI,CAAC;AAAA,MACxD,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,gBAAgB,MAA8C;AACpE,eAAW,MAAM,KAAK,MAAM,OAAO,EAAG,KAAI,GAAG,SAAS,KAAM,QAAO;AACnE,WAAO;AAAA,EACT;AACF;;;ANvEO,IAAM,iBAAN,MAAqB;AAAA,EACjB,QAAQ,oBAAI,IAA0B;AAAA,EAC9B,QAAQ,oBAAI,IAAkB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAKT;AACD,SAAK,UAAU,KAAK;AACpB,SAAK,MAAM,KAAK;AAChB,SAAK,SAAS,KAAK;AAEnB,SAAK,YAAY,IAAI,UAAU;AAAA,MAC7B,OAAO,KAAK;AAAA,MAAO,OAAO,KAAK;AAAA,MAAO,UAAU,KAAK;AAAA,IACvD,CAAC;AAID,QAAI,eAAiC;AACrC,SAAK,UAAU,IAAI,QAAQ;AAAA,MACzB,SAAS,KAAK;AAAA,MAAS,KAAK,KAAK;AAAA,MACjC,OAAO,KAAK;AAAA,MAAO,OAAO,KAAK;AAAA,MAC/B,QAAQ,KAAK;AAAA,MAAQ,WAAW,KAAK;AAAA,MACrC,SAAS,CAAC,KAAK,OAAO,aAAa,cAAc,oBAAoB,KAAK,OAAO,QAAQ;AAAA,IAC3F,CAAC;AACD,SAAK,YAAY,IAAI,UAAU;AAAA,MAC7B,OAAO,KAAK;AAAA,MAAO,QAAQ,KAAK;AAAA,MAChC,SAAS,KAAK;AAAA,MAAS,WAAW,KAAK;AAAA,IACzC,CAAC;AACD,mBAAe,KAAK;AAEpB,SAAK,eAAe,IAAI,aAAa;AAAA,MACnC,OAAO,KAAK;AAAA,MAAO,QAAQ,KAAK;AAAA,IAClC,CAAC;AAAA,EACH;AAAA,EAEA,QAAQ,KAAoB,UAAqC;AAC/D,UAAM,MAAMC,MAAK,KAAK,SAAS,IAAI,GAAG;AACtC,UAAM,MAAM,YAAY,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,YAAY;AAC9D,WAAO,eAAe,KAAK,KAAK,KAAK,SAAO,KAAK,OAAO,MAAM,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,EACnF;AAAA,EAEA,MAAM,KAAoB,UAAkB,YAAY,OAAsB;AAC5E,WAAO,KAAK,QAAQ,MAAM,KAAK,UAAU,SAAS;AAAA,EACpD;AAAA,EAEA,KAAK,MAAoB;AACvB,SAAK,UAAU,KAAK,IAAI;AAAA,EAC1B;AAAA,EAEA,QAAQ,MAA6B;AACnC,WAAO,KAAK,UAAU,QAAQ,IAAI;AAAA,EACpC;AAAA,EAEA,iBAAgC;AAC9B,WAAO,KAAK,aAAa,SAAS;AAAA,EACpC;AAAA,EAEA,QAAQ,OAAmC,CAAC,GAAkB;AAC5D,WAAO,KAAK,UAAU,QAAQ,IAAI;AAAA,EACpC;AACF;;;AO1FA,SAAS,cAAAC,aAAY,aAAAC,YAAW,YAAY,yBAA2C;AACvF,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,SAAS,WAAAC,gBAAe;AAajB,IAAM,UAAN,MAAc;AAAA,EACF;AAAA,EACA;AAAA,EACA,UAAU,oBAAI,IAAyB;AAAA,EACvC,OAAO,oBAAI,IAAY;AAAA,EAExC,YAAY,MAAmB;AAC7B,UAAM,OAAO,KAAK,WAAWF,MAAKE,SAAQ,GAAG,UAAU,MAAM;AAC7D,SAAK,MAAMF,MAAK,MAAM,SAAS,KAAK,WAAW,CAAC;AAChD,SAAK,gBAAgB,KAAK,iBAAiB;AAC3C,IAAAD,WAAU,KAAK,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACzC;AAAA;AAAA,EAGA,QAAQ,SAAyB;AAC/B,WAAOC,MAAK,KAAK,KAAK,GAAG,SAAS,OAAO,CAAC,MAAM;AAAA,EAClD;AAAA,EAEA,MAAM,SAAiB,MAAoB;AACzC,UAAM,SAAS,KAAK,UAAU,OAAO;AACrC,WAAO,MAAM,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,IAAI,IAAI;AAAA,CAAI;AAAA,EACtD;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,SAAS,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC,EAAE;AAAA,MACxC,OAAK,IAAI,QAAc,OAAK,EAAE,IAAI,MAAM,EAAE,CAAC,CAAC;AAAA,IAC9C;AACA,SAAK,QAAQ,MAAM;AACnB,SAAK,KAAK,MAAM;AAChB,UAAM,QAAQ,IAAI,MAAM;AAAA,EAC1B;AAAA,EAEQ,UAAU,SAA8B;AAC9C,QAAI,IAAI,KAAK,QAAQ,IAAI,OAAO;AAChC,QAAI,EAAG,QAAO;AACd,UAAM,OAAO,KAAK,QAAQ,OAAO;AACjC,QAAI,KAAK,iBAAiB,CAAC,KAAK,KAAK,IAAI,OAAO,KAAKF,YAAW,IAAI,GAAG;AACrE,UAAI;AACF,QAAAC,WAAUE,SAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,mBAAW,MAAM,OAAO,OAAO;AAAA,MACjC,QAAQ;AAAA,MAAoB;AAAA,IAC9B;AACA,SAAK,KAAK,IAAI,OAAO;AACrB,QAAI,kBAAkB,MAAM,EAAE,OAAO,IAAI,CAAC;AAC1C,MAAE,GAAG,SAAS,MAAM;AAAA,IAA+C,CAAC;AACpE,SAAK,QAAQ,IAAI,SAAS,CAAC;AAC3B,WAAO;AAAA,EACT;AACF;AAEA,SAAS,SAAS,MAAsB;AACtC,SAAO,KAAK,QAAQ,qBAAqB,GAAG,EAAE,QAAQ,YAAY,EAAE,KAAK;AAC3E;;;ACnEO,IAAM,cAAN,MAAqB;AAAA,EACT,OAAO,oBAAI,IAAoB;AAAA,EAEhD,UAAU,IAAgC;AACxC,SAAK,KAAK,IAAI,EAAE;AAChB,WAAO,MAAM,KAAK,KAAK,OAAO,EAAE;AAAA,EAClC;AAAA,EAEA,KAAK,GAAY;AACf,eAAW,MAAM,KAAK,MAAM;AAC1B,UAAI;AAAE,WAAG,CAAC;AAAA,MAAG,QAAQ;AAAA,MAAgD;AAAA,IACvE;AAAA,EACF;AACF;;;ACbA,SAAS,SAAAE,cAAgC;AACzC,SAAS,QAAAC,aAAY;AAKrB,IAAM,0BAA0B;AAwBhC,eAAsB,eACpB,WACA,MAC+B;AAC/B,QAAM,QAAwB,CAAC;AAC/B,QAAM,SAAmB,CAAC;AAE1B,aAAW,OAAO,WAAW;AAC3B,UAAM,OAAO,cAAc,KAAK,IAAI;AACpC,UAAM,KAAK,EAAE,KAAK,MAAM,KAAK,KAAK,OAAO,KAAK,CAAC;AAE/C,QAAI,CAAC,IAAI,aAAa;AACpB,WAAK,QAAQ,IAAI,MAAM,iCAA4B;AACnD;AAAA,IACF;AAEA,QAAI,IAAI,YAAY,SAAS,SAAS,CAAC,IAAI,MAAM;AAC/C,WAAK,QAAQ,IAAI,MAAM,6DAAmD;AAC1E;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,gBAAgB,2BAA2B;AAClE,UAAM,KAAK,MAAM,YAAY,KAAK,SAAS;AAC3C,QAAI,IAAI;AACN,WAAK,QAAQ,IAAI,MAAM,gBAAW;AAAA,IACpC,OAAO;AACL,WAAK,QAAQ,IAAI,MAAM,wCAAmC,YAAY,GAAI,IAAI;AAC9E,aAAO,KAAK,IAAI,IAAI;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,YAAY,OAAO,WAAW,GAAG,OAAO;AAC1D;AAGA,eAAsB,cACpB,OACA,UACA,OAAqG,CAAC,GACvF;AACf,aAAW,EAAE,KAAK,MAAM,IAAI,KAAK,OAAO;AACtC,QAAI;AACF,UAAI,IAAK,UAAS,SAAS,GAAG;AAC9B,UAAI,IAAI,SAAS;AACf,aAAK,QAAQ,IAAI,MAAM,aAAM,IAAI,OAAO,EAAE;AAC1C,cAAM,IAAI,QAAc,CAAAC,aAAW;AACjC,gBAAM,QAAQ,QAAQ,aAAa;AACnC,gBAAM,QAAQ,QAAQ,YAAY;AAClC,gBAAM,OAAO,QAAQ,OAAO;AAC5B,gBAAM,MAAM,IAAI,MAAMC,MAAK,KAAK,SAAS,IAAI,GAAG,IAAI,KAAK;AACzD,gBAAM,MAAM,EAAE,GAAG,KAAK,KAAK,GAAI,IAAI,YAAY,CAAC,EAAG;AACnD,gBAAM,QAAQC,OAAM,OAAO,CAAC,MAAM,IAAI,OAAQ,GAAG,EAAE,KAAK,KAAK,OAAO,SAAS,CAAC;AAC9E,gBAAM,GAAG,SAAS,MAAMF,SAAQ,CAAC;AACjC,gBAAM,GAAG,SAAS,MAAMA,SAAQ,CAAC;AAEjC,qBAAW,MAAMA,SAAQ,GAAG,GAAM;AAAA,QACpC,CAAC;AAAA,MACH;AAAA,IACF,QAAQ;AAAA,IAAoB;AAC5B,SAAK;AAAA,EACP;AACF;AAEA,SAAS,cAAc,KAAsB,MAAwC;AACnF,QAAM,QAAQ,QAAQ,aAAa;AACnC,QAAM,QAAQ,QAAQ,YAAY;AAClC,QAAM,OAAO,QAAQ,OAAO;AAC5B,QAAM,MAAM,IAAI,MAAMC,MAAK,KAAK,SAAS,IAAI,GAAG,IAAI,KAAK;AACzD,QAAM,MAAM,EAAE,GAAG,KAAK,KAAK,GAAI,IAAI,YAAY,CAAC,EAAG;AAEnD,OAAK,QAAQ,IAAI,MAAM,aAAM,IAAI,GAAG,EAAE;AACtC,QAAM,QAAQC,OAAM,OAAO,CAAC,MAAM,IAAI,GAAG,GAAG;AAAA,IAC1C;AAAA,IAAK;AAAA,IAAK,UAAU;AAAA,IAAM,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,EAC5D,CAAC;AACD,QAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,KAAK,QAAQ,IAAI,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACtF,QAAM,QAAQ,GAAG,QAAQ,CAAC,MAAc,KAAK,QAAQ,IAAI,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACtF,QAAM,GAAG,SAAS,SAAO,KAAK,QAAQ,IAAI,MAAM,uBAAkB,IAAI,OAAO,EAAE,CAAC;AAChF,SAAO;AACT;AAEA,eAAe,YAAY,KAAsB,WAAqC;AACpF,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,QAAM,OAAO,IAAI;AACjB,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI,MAAM,YAAY,MAAM,IAAI,WAAW,EAAG,QAAO;AACrD,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;;;ACtHA,OAAOC,UAAS;AAmBT,SAAS,gBAAgB,MAAgC;AAC9D,QAAM,EAAE,YAAY,YAAY,YAAY,eAAe,YAAY,SAAS,MAAM,IAAI;AAC1F,MAAI,YAAkD;AACtD,MAAI,eAAe,KAAK,IAAI;AAC5B,MAAI,WAAW;AACf,MAAI,eAAe;AACnB,MAAI,eAA6B,CAAC;AAClC,QAAM,cAAc,oBAAI,IAAgB;AAExC,WAAS,eAAe;AACtB,mBAAe,KAAK,IAAI;AAAA,EAC1B;AAEA,WAAS,oBAAoB;AAC3B,QAAI,UAAW,cAAa,SAAS;AACrC,QAAI,cAAc,EAAG;AACrB,UAAM,WAAW,aAAa;AAC9B,gBAAY,WAAW,MAAM;AAC3B,YAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,UAAI,YAAY,OAAO,KAAK,UAAU,UAAU;AAE9C,0BAAkB;AAClB;AAAA,MACF;AACA,qBAAe;AACf,cAAQ,kBAAW,UAAU,qBAAgB;AAC7C,iBAAW;AAAA,IACb,GAAG,QAAQ;AAAA,EACb;AAEA,WAAS,aAAa,QAAoB;AACxC,UAAM,SAASC,KAAI,iBAAiB,EAAE,MAAM,YAAY,MAAM,aAAa,eAAe,KAAK,CAAC;AAChG,gBAAY,IAAI,MAAM;AAEtB,UAAM,UAAU,MAAM;AACpB,kBAAY,OAAO,MAAM;AACzB,mBAAa;AAAA,IACf;AAEA,WAAO,GAAG,SAAS,MAAM;AAAE,aAAO,QAAQ;AAAG,cAAQ;AAAA,IAAG,CAAC;AACzD,WAAO,GAAG,SAAS,MAAM;AAAE,aAAO,QAAQ;AAAG,cAAQ;AAAA,IAAG,CAAC;AACzD,WAAO,GAAG,SAAS,OAAO;AAC1B,WAAO,GAAG,SAAS,OAAO;AAE1B,WAAO,GAAG,WAAW,MAAM;AACzB,aAAO,GAAG,QAAQ,CAAC,UAAU;AAAE,qBAAa;AAAG,YAAI,CAAC,OAAO,UAAW,QAAO,MAAM,KAAK;AAAA,MAAG,CAAC;AAC5F,aAAO,GAAG,QAAQ,CAAC,UAAU;AAAE,qBAAa;AAAG,YAAI,CAAC,OAAO,UAAW,QAAO,MAAM,KAAK;AAAA,MAAG,CAAC;AAC5F,aAAO,GAAG,OAAO,MAAM;AAAE,YAAI,CAAC,OAAO,UAAW,QAAO,IAAI;AAAA,MAAG,CAAC;AAC/D,aAAO,GAAG,OAAO,MAAM;AAAE,YAAI,CAAC,OAAO,UAAW,QAAO,IAAI;AAAA,MAAG,CAAC;AAAA,IACjE,CAAC;AAAA,EACH;AAEA,iBAAe,iBAAiB,QAAoB;AAClD,iBAAa;AACb,WAAO,GAAG,SAAS,MAAM;AAAA,IAAC,CAAC;AAE3B,QAAI,gBAAgB,QAAQ,GAAG;AAC7B,mBAAa,MAAM;AACnB;AAAA,IACF;AAEA,iBAAa,KAAK,MAAM;AACxB,WAAO,GAAG,SAAS,MAAM;AAAE,qBAAe,aAAa,OAAO,OAAK,MAAM,MAAM;AAAA,IAAG,CAAC;AAEnF,QAAI,SAAU;AACd,eAAW;AAEX,YAAQ,wBAAmB;AAC3B,QAAI,KAAK;AACT,QAAI;AACF,YAAM,cAAc;AACpB,WAAK,MAAM,YAAY,YAAY,EAAE,SAAS,MAAO,UAAU,IAAI,CAAC;AACpE,UAAI,GAAI,gBAAe;AAAA,UAClB,SAAQ,oCAA+B;AAAA,IAC9C,SAAS,GAAY;AACnB,cAAQ,wBAAoB,EAAY,OAAO,EAAE;AAAA,IACnD;AACA,eAAW;AAEX,UAAM,QAAQ,aAAa,OAAO,CAAC;AACnC,QAAI,CAAC,IAAI;AACP,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,KAAK,UAAW,MAAK,QAAQ;AAAA,MACpC;AACA;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,UAAI,CAAC,KAAK,UAAW,cAAa,IAAI;AAAA,IACxC;AAAA,EACF;AAEA,QAAM,SAASA,KAAI,aAAa,EAAE,eAAe,KAAK,GAAG,YAAU,iBAAiB,MAAM,CAAC;AAC3F,SAAO,OAAO,YAAY,SAAS;AACnC,oBAAkB;AAElB,SAAO;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,SAAS,MAAM;AACb,UAAI,UAAW,cAAa,SAAS;AACrC,mBAAa,QAAQ,OAAK,EAAE,QAAQ,CAAC;AACrC,kBAAY,QAAQ,OAAK,EAAE,QAAQ,CAAC;AACpC,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;;;AC5HA,SAAS,WAAW,mBAA+B;;;ACUnD,IAAM,iBAA0C;AAAA,EAC9C;AAAA,EAAO;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAY;AAAA,EAC7D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAe;AAAA,EAAgB;AAAA,EAAgB;AACzE;AAEA,SAAS,uBAAuB,MAAqB,MAA8B;AACjF,aAAW,KAAK,gBAAgB;AAC9B,QAAI,KAAK,UAAU,KAAK,CAAC,CAAC,MAAM,KAAK,UAAU,KAAK,CAAC,CAAC,EAAG,QAAO;AAAA,EAClE;AACA,SAAO;AACT;AAOO,SAAS,aAAa,MAAuB,MAAoC;AACtF,QAAM,aAAa,IAAI,IAAI,KAAK,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACrD,QAAM,aAAa,IAAI,IAAI,KAAK,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAErD,QAAM,QAAyB,CAAC;AAChC,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAA+D,CAAC;AACtE,QAAM,YAAsB,CAAC;AAE7B,aAAW,CAAC,MAAM,CAAC,KAAK,YAAY;AAClC,QAAI,CAAC,WAAW,IAAI,IAAI,GAAG;AAAE,cAAQ,KAAK,IAAI;AAAG;AAAA,IAAU;AAC3D,UAAM,IAAI,WAAW,IAAI,IAAI;AAC7B,QAAI,uBAAuB,GAAG,CAAC,EAAG,SAAQ,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;AAAA,QAC9D,WAAU,KAAK,IAAI;AAAA,EAC1B;AACA,aAAW,CAAC,MAAM,CAAC,KAAK,YAAY;AAClC,QAAI,CAAC,WAAW,IAAI,IAAI,EAAG,OAAM,KAAK,CAAC;AAAA,EACzC;AACA,SAAO,EAAE,OAAO,SAAS,SAAS,UAAU;AAC9C;AAGO,SAAS,cAAc,GAAwB;AACpD,QAAM,QAAkB,CAAC;AACzB,MAAI,EAAE,MAAM,OAAU,OAAM,KAAK,IAAI,EAAE,MAAM,MAAM,QAAQ;AAC3D,MAAI,EAAE,QAAQ,OAAQ,OAAM,KAAK,IAAI,EAAE,QAAQ,MAAM,UAAU;AAC/D,MAAI,EAAE,QAAQ,OAAQ,OAAM,KAAK,IAAI,EAAE,QAAQ,MAAM,UAAU;AAC/D,MAAI,CAAC,MAAM,OAAW,OAAM,KAAK,YAAY;AAC7C,SAAO,MAAM,KAAK,IAAI;AACxB;;;ADrCA,eAAsB,kBAAkB,MAAsC;AAC5E,QAAM,EAAE,YAAY,SAAS,SAAS,IAAI,IAAI;AAC9C,MAAI;AACF,UAAM,UAAU,MAAM,WAAW,UAAU;AAC3C,UAAM,OAAO,eAAe,SAAS,OAAO;AAC5C,QAAI,KAAK,QAAQ;AACf,UAAI;AAAA,EAA4B,uBAAuB,IAAI,CAAC,EAAE;AAC9D;AAAA,IACF;AACA,UAAM,cAAc,CAAC,GAAG,QAAQ,MAAM,OAAO,CAAC,EAAE,IAAI,OAAK,EAAE,GAAG;AAC9D,UAAM,OAAO,aAAa,aAAa,QAAQ,QAAQ;AACvD,QAAI,CAAC,KAAK,MAAM,UAAU,CAAC,KAAK,QAAQ,UAAU,CAAC,KAAK,QAAQ,OAAQ;AAExE,eAAW,QAAQ,KAAK,SAAS;AAC/B,cAAQ,KAAK,IAAI;AACjB,cAAQ,MAAM,OAAO,IAAI;AAAA,IAC3B;AACA,QAAI,WAAW,YAAY;AAC3B,eAAW,EAAE,KAAK,KAAK,KAAK,SAAS;AACnC,YAAM,OAAO,QAAQ,MAAM,IAAI,KAAK,IAAI;AACxC,YAAM,KAAK,MAAM,YAAY;AAC7B,cAAQ,KAAK,KAAK,IAAI;AAEtB,YAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AACzC,YAAM,QAAQ,QAAQ,MAAM,EAAE;AAC9B,YAAM,QAAQ,MAAM,MAAM,IAAI,IAAI;AAAA,IACpC;AACA,eAAW,QAAQ,KAAK,OAAO;AAC7B,YAAM,KAAK;AACX,YAAM,QAAQ,QAAQ,MAAM,EAAE;AAC9B,YAAM,QAAQ,MAAM,MAAM,EAAE;AAAA,IAC9B;AACA,QAAI,8BAAuB,cAAc,IAAI,CAAC,EAAE;AAAA,EAClD,SAAS,GAAQ;AACf,QAAI,+BAA0B,EAAE,OAAO,EAAE;AAAA,EAC3C;AACF;AAQO,SAAS,YAAY,MAAmC;AAC7D,MAAI,gBAAuC;AAC3C,MAAI,iBAAiB;AACrB,MAAI,cAAc;AAElB,QAAM,UAAU,YAAY;AAC1B,QAAI,gBAAgB;AAAE,oBAAc;AAAM;AAAA,IAAQ;AAClD,qBAAiB;AACjB,QAAI;AACF,YAAM,kBAAkB,IAAI;AAAA,IAC9B,UAAE;AACA,uBAAiB;AACjB,UAAI,aAAa;AAAE,sBAAc;AAAO,aAAK,QAAQ;AAAA,MAAG;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,MAAa,SAAgB;AAE7C,QAAI,KAAK,YAAY,KAAK,WAAW,KAAK,SAAS,KAAK,KAAM;AAC9D,QAAI,cAAe,cAAa,aAAa;AAC7C,oBAAgB,WAAW,MAAM,KAAK,QAAQ,GAAG,GAAG;AAAA,EACtD;AAEA,YAAU,KAAK,YAAY,EAAE,UAAU,IAAI,GAAG,QAAQ;AAEtD,SAAO,MAAM;AACX,QAAI,cAAe,cAAa,aAAa;AAC7C,gBAAY,KAAK,YAAY,QAAQ;AAAA,EACvC;AACF;;;AZnEA,IAAM,OAAO;AACb,IAAMC,YAAW,CAAC,MAAc,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,YAAY,EAAE,KAAK;AAChF,IAAM,WAAW,MAAMC,MAAKC,SAAQ,GAAG,QAAQ;AAExC,SAAS,WAAW,aAA6B;AACtD,SAAOD,MAAK,SAAS,GAAG,GAAGD,UAAS,WAAW,CAAC,MAAM;AACxD;AACO,SAAS,iBAAiB,aAA6B;AAC5D,SAAOC,MAAK,SAAS,GAAG,GAAGD,UAAS,WAAW,CAAC,aAAa;AAC/D;AAEA,SAAS,SAAS,KAAsB;AACtC,MAAI;AAAE,YAAQ,KAAK,KAAK,CAAC;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAO;AACnE;AAIO,SAAS,gBAAgB,aAA6D;AAC3F,QAAM,OAAO,WAAW,WAAW;AACnC,MAAI,CAACG,aAAW,IAAI,EAAG,QAAO,EAAE,KAAK,MAAM,OAAO,MAAM;AACxD,MAAI;AACJ,MAAI;AACF,UAAM,OAAOC,cAAa,MAAM,MAAM,EAAE,KAAK,CAAC;AAC9C,QAAI,CAAC,OAAO,CAAC,OAAO,SAAS,GAAG,EAAG,QAAO,EAAE,KAAK,MAAM,OAAO,KAAK;AAAA,EACrE,QAAQ;AACN,WAAO,EAAE,KAAK,MAAM,OAAO,KAAK;AAAA,EAClC;AACA,SAAO,SAAS,GAAG,IAAI,EAAE,KAAK,OAAO,MAAM,IAAI,EAAE,KAAK,OAAO,KAAK;AACpE;AAkBA,eAAsB,WAAW,MAAiC;AAChE,QAAM,EAAE,QAAQ,UAAU,SAAS,UAAU,KAAK,SAAS,eAAe,UAAU,IAAI;AACxF,QAAM,cAAc,OAAO;AAC3B,QAAM,UAAU,iBAAiB,WAAW;AAC5C,QAAM,UAAU,WAAW,WAAW;AAEtC,EAAAC,WAAU,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACzC,MAAIF,aAAW,OAAO,GAAG;AAAE,QAAI;AAAE,MAAAG,YAAW,OAAO;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EAAE;AAG/E,QAAM,UAAU,IAAI,QAAQ,EAAE,aAAa,SAAS,QAAQ,OAAO,CAAC;AAEpE,QAAM,SAAS,IAAI,YAA2C;AAC9D,QAAM,WAAW,IAAI,YAAmD;AACxE,QAAM,cAAc,oBAAI,IAAuB;AAC/C,QAAM,aAAa,oBAAI,IAA2C;AAClE,MAAI,YAA4B,CAAC;AACjC,MAAI,SAAoC;AACxC,MAAI,cAAqC;AACzC,MAAI,aAAoC;AACxC,MAAI,oBAAyC;AAE7C,QAAM,gBAAgB,CAAC,SAAiB;AACtC,YAAQ,MAAM,SAAS,IAAI;AAC3B,WAAO,KAAK,EAAE,KAAK,SAAS,KAAK,CAAC;AAAA,EACpC;AAEA,QAAM,MAAM,IAAI,eAAe;AAAA,IAC7B;AAAA,IAAS;AAAA,IAAK;AAAA,IACd,QAAQ;AAAA,MACN,OAAO,CAAC,SAAS,SAAS;AACxB,gBAAQ,MAAM,SAAS,IAAI;AAC3B,eAAO,KAAK,EAAE,KAAK,SAAS,KAAK,CAAC;AAAA,MACpC;AAAA,MACA,eAAe,CAAC,MAAM,UAAU,SAAS,KAAK,EAAE,MAAM,MAAM,CAAC;AAAA,IAC/D;AAAA,EACF,CAAC;AAED,QAAM,UAAU,YAA2B;AACzC,QAAI,YAAa,eAAc,WAAW;AAC1C,QAAI,WAAY,eAAc,UAAU;AACxC,QAAI,mBAAmB;AAAE,UAAI;AAAE,0BAAkB;AAAA,MAAG,QAAQ;AAAA,MAAe;AAAA,IAAE;AAC7E,eAAW,KAAK,YAAY,OAAO,EAAG,GAAE,QAAQ;AAChD,QAAI,OAAQ,OAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC/C,UAAM,IAAI,QAAQ,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAClC,QAAI,UAAU,QAAQ;AACpB,YAAM,cAAc,WAAW,UAAU;AAAA,QACvC;AAAA,QAAS;AAAA,QACT,OAAO,CAAC,KAAK,QAAQ,QAAQ,MAAM,OAAO,GAAG,IAAI,GAAG;AAAA,MACtD,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AACA,QAAI,iBAAiB,aAAa,QAAQ,OAAO;AAC/C,UAAI;AAAE,sBAAc,MAAM,SAAS;AAAA,MAAG,QAAQ;AAAA,MAAe;AAAA,IAC/D;AACA,UAAM,QAAQ,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACpC,QAAIH,aAAW,OAAO,GAAG;AAAE,UAAI;AAAE,QAAAG,YAAW,OAAO;AAAA,MAAG,QAAQ;AAAA,MAAe;AAAA,IAAE;AAAA,EACjF;AAEA,MAAI,eAAe;AACnB,QAAM,WAAW,MAAM;AACrB,QAAI,aAAc;AAClB,mBAAe;AACf,YAAQ,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC,GAAG,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,EAC7D;AACA,UAAQ,GAAG,WAAW,QAAQ;AAC9B,UAAQ,GAAG,UAAU,QAAQ;AAE7B,MAAI;AAEF,QAAI,OAAO,UAAU,QAAQ;AAC3B,oBAAc,qBAAgB,OAAO,SAAS,MAAM,GAAG;AACvD,YAAM,SAAS,MAAM,eAAe,OAAO,UAAU;AAAA,QACnD;AAAA,QAAS;AAAA,QAAK;AAAA,QACd,OAAO,CAAC,KAAK,QAAQ;AAAE,kBAAQ,MAAM,OAAO,GAAG,IAAI,GAAG;AAAG,iBAAO,KAAK,EAAE,KAAK,OAAO,GAAG,IAAI,MAAM,IAAI,CAAC;AAAA,QAAG;AAAA,MAC1G,CAAC;AACD,kBAAY,OAAO;AACnB,UAAI,CAAC,OAAO,YAAY;AACtB,cAAM,IAAI,MAAM,qBAAqB,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,MACjE;AAAA,IACF;AAGA,QAAI,QAAQ,QAAQ,OAAO,MAAM;AAC/B,YAAM,SAAS,KAAK,UAAU,OAAO,MAAM,QAAQ,aAAa,WAAW;AAAA,IAC7E,OAAO;AACL,YAAM,WAAW,KAAK,QAAQ;AAAA,IAChC;AAGA,aAAS,MAAM,kBAAkB,aAAa;AAAA,MAC5C,QAAQ,MAAM,IAAI;AAAA,MAClB,SAAS,CAAC,MAAM,IAAI,QAAQ,CAAC;AAAA,MAC7B,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC;AAAA,MACvB,UAAU,OAAO,SAAS,UAAU;AAClC,cAAM,OAAO,QAAQ,QAAQ,OAAO;AACpC,YAAI,CAACH,aAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,eAAO,IAAI,QAAkB,CAACI,UAAS,WAAW;AAChD,gBAAM,MAAgB,CAAC;AACvB,gBAAM,KAAKC,iBAAgB,EAAE,OAAO,iBAAiB,MAAM,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC;AAClF,aAAG,GAAG,QAAQ,OAAK;AAAE,gBAAI,KAAK,CAAC;AAAG,gBAAI,IAAI,SAAS,MAAO,KAAI,MAAM;AAAA,UAAG,CAAC;AACxE,aAAG,GAAG,SAAS,MAAMD,SAAQ,GAAG,CAAC;AACjC,aAAG,GAAG,SAAS,MAAM;AAAA,QACvB,CAAC;AAAA,MACH;AAAA,MACA,WAAW,CAAC,SAAS,WAAW,OAAO,UAAU,CAAC,EAAE,KAAK,KAAK,MAAM;AAClE,YAAI,YAAY,QAAQ,QAAQ,QAAS,QAAO,KAAK,IAAI;AAAA,MAC3D,CAAC;AAAA,MACD,aAAa,CAAC,aAAa,SAAS,UAAU,CAAC,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,KAAK,CAAC;AAAA,MACxF,MAAM,WAAW;AACf,cAAM,OAAiB,CAAC;AACxB,cAAM,YAAY,oBAAI,IAAoB;AAC1C,mBAAW,CAAC,MAAM,EAAE,KAAK,IAAI,OAAO;AAClC,cAAI,GAAG,KAAK;AAAE,iBAAK,KAAK,GAAG,GAAG;AAAG,sBAAU,IAAI,GAAG,KAAK,IAAI;AAAA,UAAG;AAAA,QAChE;AACA,cAAM,MAAM,KAAK,SAAS,MAAM,SAAS,gBAAgB,IAAI,IAAI,oBAAI,IAAI;AACzE,cAAME,YAA2D,CAAC;AAClE,mBAAW,CAAC,IAAI,KAAK,IAAI,OAAO;AAC9B,UAAAA,UAAS,IAAI,IAAI,EAAE,KAAK,GAAG,OAAO,EAAE;AAAA,QACtC;AACA,mBAAW,CAAC,KAAK,IAAI,KAAK,KAAK;AAC7B,gBAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,cAAI,CAAC,KAAM;AACX,gBAAM,OAAO,WAAW,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,EAAE;AAChE,gBAAM,MAAM,eAAe,KAAK,YAAY,KAAK,KAAK,KAAK,IAAI;AAC/D,qBAAW,IAAI,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,KAAK,WAAW,CAAC;AAC/D,UAAAA,UAAS,IAAI,IAAI,EAAE,KAAK,KAAK,MAAM,MAAM,EAAE,IAAI,IAAI,OAAO,KAAK,MAAO,KAAK,MAAM,OAAQ,EAAE,IAAI,GAAG;AAAA,QACpG;AACA,eAAO;AAAA,UACL,UAAAA;AAAA,UACA,QAAQ;AAAA,YACN,YAAY,KAAK,MAAM,SAAS,IAAI,OAAO,IAAI;AAAA,YAC/C,WAAW,KAAK,MAAM,QAAQ,IAAI,OAAO,IAAI;AAAA,YAC7C,UAAU,KAAK,EAAE;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,MACA,eAAe;AACb,YAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,QAAQ,MAAO,QAAO;AAC3D,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,UAAU,cAAc;AAAA,UACxB,QAAQ,UAAU;AAAA,UAClB,KAAK,UAAU;AAAA,UACf,QAAQ,UAAU;AAAA,QACpB;AAAA,MACF;AAAA,MACA,UAAU;AACR,eAAO,EAAE,SAAS,aAAa,UAAU,OAAO,YAAY,CAAC,EAAE;AAAA,MACjE;AAAA,IACF,GAAG,EAAE,OAAO,SAAO,cAAc,GAAG,EAAE,CAAC;AAGvC,kBAAc,YAAY,MAAM;AAAE,WAAK,IAAI,eAAe;AAAA,IAAG,GAAG,GAAI;AAGpE,QAAI,iBAAiB,aAAa,QAAQ,OAAO;AAC/C,UAAI,cAA6B;AACjC,YAAM,OAAO,MAAM;AACjB,cAAM,YAAY,oBAAI,IAA0B;AAChD,mBAAW,CAAC,GAAG,EAAE,KAAK,IAAI,OAAO;AAC/B,oBAAU,IAAI,GAAG,EAAE,MAAM,GAAG,IAAI,MAAM,QAAQ,GAAG,QAAQ,UAAW,GAAG,IAA8B,SAAS,CAAC;AAAA,QACjH;AACA,cAAM,UAAU,cAAc,SAAS,WAAW,SAAS;AAC3D,YAAI,YAAY,YAAa;AAC7B,sBAAc;AACd,YAAI;AAAE,wBAAc,MAAM,SAAS,SAAS;AAAA,QAAG,QAAQ;AAAA,QAA6B;AAAA,MACtF;AACA,WAAK;AACL,mBAAa,YAAY,MAAM,GAAI;AAAA,IACrC;AAGA,QAAI,QAAQ,aAAa;AACvB,UAAI;AACF,cAAM,aAAa,eAAe,SAAS,QAAQ,UAAU;AAC7D,sBAAc,sBAAe,UAAU,EAAE;AACzC,4BAAoB,YAAY;AAAA,UAC9B;AAAA,UAAY;AAAA,UAAS,SAAS;AAAA,UAC9B,KAAK,SAAO,cAAc,GAAG;AAAA,QAC/B,CAAC;AAAA,MACH,SAAS,GAAQ;AACf,sBAAc,iCAA4B,EAAE,WAAW,OAAO,CAAC,CAAC,EAAE;AAAA,MACpE;AAAA,IACF;AAGA,IAAAC,eAAc,SAAS,OAAO,QAAQ,GAAG,CAAC;AAC1C,kBAAc,4BAAuB,QAAQ,GAAG,GAAG;AAAA,EAIrD,SAAS,GAAQ;AACf,QAAI;AAAE,MAAAA,eAAc,SAAS,EAAE,WAAW,OAAO,CAAC,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAe;AAC7E,QAAI;AAAE,oBAAc,uBAAkB,EAAE,WAAW,OAAO,CAAC,CAAC,EAAE;AAAA,IAAG,QAAQ;AAAA,IAAe;AACxF,UAAM,QAAQ,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,eAAe,WAAW,KAAqB,UAA0C;AACvF,QAAM,SAAS,aAAa,QAAQ;AACpC,MAAI,WAAW;AACf,aAAW,OAAO,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG;AACvE,eAAW,OAAO,OAAO,GAAG,GAAI;AAC9B,YAAM,KAAK;AACX,YAAM,IAAI,QAAQ,KAAK,EAAE;AACzB,YAAM,IAAI,MAAM,KAAK,EAAE;AAAA,IACzB;AACA,UAAM,OAAO,OAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK;AACtD,QAAI,KAAK,OAAQ,OAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,YAAY,EAAE,MAAM,EAAE,SAAS,KAAM,CAAC,CAAC,CAAC;AACzF,WAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,OAAK;AACtD,YAAM,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI;AAC/B,UAAI,GAAI,IAAG,SAAS;AAAA,IACtB,CAAC;AAAA,EACH;AACF;AAEA,eAAe,SACb,KACA,UACA,SACA,aACA,aACe;AACf,QAAM,EAAE,UAAU,KAAK,IAAI,iBAAiB,UAAU,OAAO;AAC7D,QAAM,SAAS,aAAa,QAAQ;AACpC,MAAI,WAAW;AACf,aAAW,OAAO,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG;AACvE,eAAW,OAAO,OAAO,GAAG,GAAI;AAC9B,YAAM,KAAK;AACX,YAAM,IAAI,QAAQ,KAAK,EAAE;AACzB,YAAM,IAAI,MAAM,KAAK,EAAE;AAAA,IACzB;AACA,UAAM,OAAO,OAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK;AACtD,QAAI,KAAK,OAAQ,OAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,YAAY,EAAE,MAAM,EAAE,SAAS,KAAM,CAAC,CAAC,CAAC;AACzF,WAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,OAAK;AACtD,YAAM,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI;AAC/B,UAAI,GAAI,IAAG,SAAS;AAAA,IACtB,CAAC;AAAA,EACH;AACA,aAAW,OAAO,MAAM;AACtB,UAAM,KAAK;AACX,UAAM,YAAY,mBAAmB,GAAG;AACxC,QAAI,MAAM,IAAI,IAAI,MAAM;AAAA,MACtB,KAAK;AAAA,MAAW,MAAM;AAAA,MAAM,KAAK;AAAA,MACjC,QAAQ;AAAA,MAAQ,QAAQ;AAAA,MACxB,QAAQ;AAAA,MAAG,UAAU;AAAA,MAAG,WAAW;AAAA,MACnC,iBAAiB;AAAA,MAAO,UAAU;AAAA,IACpC,CAAC;AACD,UAAM,QAAQ,gBAAgB;AAAA,MAC5B,YAAY,IAAI;AAAA,MAAM,YAAY,UAAU;AAAA,MAAU,YAAY;AAAA,MAClE,eAAe,YAAY;AACzB,cAAM,IAAI,QAAQ,WAAW,EAAE;AAC/B,cAAM,IAAI,MAAM,WAAW,EAAE;AAC7B,cAAM,KAAK,MAAM,YAAY,UAAU,UAAU,EAAE,SAAS,KAAM,CAAC;AACnE,cAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,YAAI,IAAI;AAAE,aAAG,SAAS,KAAK,YAAY;AAAW,cAAI,GAAI,IAAG,SAAS;AAAA,QAAM;AAAA,MAC9E;AAAA,MACA,YAAY,MAAM;AAChB,YAAI,KAAK,IAAI,IAAI;AACjB,cAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,YAAI,IAAI;AAAE,aAAG,SAAS;AAAQ,aAAG,SAAS;AAAQ,aAAG,MAAM;AAAM,aAAG,OAAO;AAAM,aAAG,YAAY;AAAA,QAAM;AAAA,MACxG;AAAA,MACA,SAAS,MAAM;AACb,cAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,eAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,KAAK,UAAU,GAAG,WAAW;AAAA,MAC/D;AAAA,IACF,CAAC;AACD,gBAAY,IAAI,IAAI,MAAM,KAAK;AAAA,EACjC;AACF;AAWA,eAAsB,YAAY,MAAqC;AACrE,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,OAAO,MAAM,IAAI,IAAI;AACrE,QAAM,cAAc,KAAK,OAAO;AAEhC,MAAI,QAAQ,aAAa,SAAS;AAChC,QAAI,uGAAkG;AACtG,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,gBAAgB,WAAW;AAC5C,MAAI,SAAS,OAAO,CAAC,SAAS,OAAO;AACnC,QAAI,sCAAiC,WAAW,UAAU,SAAS,GAAG,mCAAmC;AACzG,WAAO;AAAA,EACT;AACA,MAAI,SAAS,OAAO;AAClB,QAAI,uCAAkC,WAAW,GAAG;AACpD,QAAI;AAAE,MAAAJ,YAAW,WAAW,WAAW,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EACpE;AAEA,EAAAD,WAAU,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACzC,QAAM,UAAU,iBAAiB,WAAW;AAC5C,QAAM,UAAU,WAAW,WAAW;AACtC,MAAIF,aAAW,OAAO,GAAG;AAAE,QAAI;AAAE,MAAAG,YAAW,OAAO;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EAAE;AAG/E,QAAM,eAAe,QAAQ,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,KAAK,MAAM;AAC5D,QAAI,MAAM,KAAK,QAAQ,KAAM,QAAO;AACpC,QAAI,QAAQ,QAAQ,QAAQ,WAAY,QAAO;AAC/C,WAAO;AAAA,EACT,CAAC;AAED,MAAI,+CAA0C,WAAW,MAAM;AAG/D,QAAM,QAAQK,OAAM,QAAQ,UAAU,CAAC,GAAG,QAAQ,UAAU,QAAQ,KAAK,CAAC,GAAI,GAAG,YAAY,GAAG;AAAA,IAC9F,UAAU;AAAA,IACV,OAAO;AAAA,IACP,KAAK,EAAE,GAAG,QAAQ,KAAK,oBAAoB,IAAI;AAAA,IAC/C,KAAK,KAAK;AAAA,EACZ,CAAC;AACD,QAAM,MAAM;AAGZ,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAIR,aAAW,OAAO,GAAG;AACvB,YAAM,MAAM,OAAOC,cAAa,SAAS,MAAM,EAAE,KAAK,CAAC;AACvD,UAAI,EAAE;AACN,UAAI,iCAA0B,GAAG,GAAG;AACpC,UAAI,+BAA+B;AACnC,UAAI,4CAA4C;AAChD,UAAI,yBAAyB;AAC7B,aAAO;AAAA,IACT;AACA,QAAID,aAAW,OAAO,GAAG;AACvB,YAAM,MAAMC,cAAa,SAAS,MAAM,EAAE,KAAK;AAC/C,UAAI,8BAAyB,GAAG,EAAE;AAClC,UAAI;AAAE,QAAAE,YAAW,OAAO;AAAA,MAAG,QAAQ;AAAA,MAAe;AAClD,aAAO;AAAA,IACT;AACA,UAAM,MAAM,GAAG;AAAA,EACjB;AAEA,MAAI,qEAAgE,MAAM,GAAG,IAAI;AACjF,MAAI,MAAM,KAAK;AAAE,QAAI;AAAE,cAAQ,KAAK,MAAM,KAAK,SAAS;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EAAE;AACpF,SAAO;AACT;AAIA,eAAsB,WACpB,aACA,OAAiE,CAAC,GACjD;AACjB,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,OAAO,MAAM,IAAI,IAAI;AACrE,QAAM,QAAQ,KAAK,iBAAiB;AACpC,QAAM,SAAS,gBAAgB,WAAW;AAE1C,MAAI,CAAC,OAAO,KAAK;AACf,QAAI,iCAA4B,WAAW,IAAI;AAC/C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,OAAO;AAChB,QAAI,8BAAyB,WAAW,UAAU,OAAO,GAAG,wBAAwB;AACpF,QAAI;AAAE,MAAAA,YAAW,WAAW,WAAW,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAe;AAClE,WAAO;AAAA,EACT;AAEA,MAAI,+BAA0B,OAAO,GAAG,MAAM;AAC9C,MAAI;AACF,YAAQ,KAAK,OAAO,KAAK,SAAS;AAAA,EACpC,SAAS,GAAQ;AACf,QAAI,4BAAuB,OAAO,GAAG,KAAK,EAAE,OAAO,EAAE;AACrD,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI,CAAC,SAAS,OAAO,GAAG,GAAG;AACzB,UAAI,8BAAyB,OAAO,GAAG,GAAG;AAC1C,YAAMM,KAAI,WAAW,WAAW;AAChC,UAAIT,aAAWS,EAAC,GAAG;AAAE,YAAI;AAAE,UAAAN,YAAWM,EAAC;AAAA,QAAG,QAAQ;AAAA,QAAe;AAAA,MAAE;AACnE,aAAO;AAAA,IACT;AACA,UAAM,MAAM,GAAG;AAAA,EACjB;AAEA,MAAI,sCAAiC,QAAQ,KAAM,QAAQ,CAAC,CAAC,qBAAqB;AAClF,MAAI;AAAE,YAAQ,KAAK,OAAO,KAAK,SAAS;AAAA,EAAG,QAAQ;AAAA,EAAe;AAClE,QAAM,IAAI,WAAW,WAAW;AAChC,MAAIT,aAAW,CAAC,GAAG;AAAE,QAAI;AAAE,MAAAG,YAAW,CAAC;AAAA,IAAG,QAAQ;AAAA,IAAe;AAAA,EAAE;AACnE,SAAO;AACT;;;AbncA,IAAM,QAAQ,oBAAI,IAAI,CAAC,QAAQ,WAAW,UAAU,QAAQ,OAAO,MAAM,MAAM,CAAC;AAGzE,SAAS,iBAAiB,MAA+B;AAC9D,QAAM,QAAQ,KAAK,CAAC;AACpB,SAAO,SAAS,MAAM,IAAI,KAAK,IAAI,QAAQ;AAC7C;AAUA,SAAS,QAAQ,QAAwB,UAA2B;AAClE,QAAM,OAAO,YAAYO,MAAKC,SAAQ,GAAG,UAAU,MAAM;AACzD,SAAOD,MAAK,MAAME,UAAS,OAAO,IAAI,CAAC;AACzC;AAEA,SAASA,UAAS,MAAsB;AACtC,SAAO,KAAK,QAAQ,qBAAqB,GAAG,EAAE,QAAQ,YAAY,EAAE,KAAK;AAC3E;AAIA,eAAsB,QAAQ,MAAgB,MAAgC;AAC5E,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,QAAM,SAAS,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,IAAI;AAC9D,QAAM,SAAS,KAAK,KAAK,OAAK,CAAC,EAAE,WAAW,GAAG,CAAC;AAChD,MAAI,CAAC,QAAQ;AACX,QAAI,wCAAwC;AAC5C,WAAO;AAAA,EACT;AACA,QAAM,YAAY,KAAK,OAAO,SAAS,IAAI,OAAK,EAAE,IAAI;AACtD,MAAI,CAAC,UAAU,SAAS,MAAM,GAAG;AAC/B,QAAI,oBAAoB,MAAM,aAAa,UAAU,KAAK,IAAI,CAAC,EAAE;AACjE,WAAO;AAAA,EACT;AACA,QAAM,OAAOF,MAAK,QAAQ,KAAK,QAAQ,KAAK,MAAM,GAAG,GAAGE,UAAS,MAAM,CAAC,MAAM;AAC9E,MAAI,CAACC,aAAW,IAAI,GAAG;AACrB,QAAI,wBAAwB,MAAM,MAAM,IAAI,GAAG;AAC/C,WAAO,SAAS,MAAM,WAAW,MAAM,GAAG,IAAI;AAAA,EAChD;AACA,QAAM,WAAW,MAAM,GAAG;AAC1B,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,MAAM,WAAW,MAAM,KAAKC,UAAS,IAAI,EAAE,IAAI;AACxD;AAEA,eAAe,WAAW,MAAc,KAAyC;AAC/E,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAM,KAAKC,iBAAgB,EAAE,OAAOC,kBAAiB,MAAM,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC;AAClF,OAAG,GAAG,QAAQ,OAAK,IAAI,CAAC,CAAC;AACzB,OAAG,GAAG,SAAS,MAAMF,SAAQ,CAAC;AAC9B,OAAG,GAAG,SAAS,MAAM;AAAA,EACvB,CAAC;AACH;AAEA,eAAe,WAAW,MAAc,KAA0B,UAAU,GAAoB;AAC9F,MAAI,MAAM;AAEV,SAAO,CAACF,aAAW,IAAI,EAAG,OAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AACnE,SAAO,IAAI,QAAQ,CAAAE,aAAW;AAC5B,UAAM,OAAO,YAAY;AACvB,YAAM,OAAOD,UAAS,IAAI,EAAE;AAC5B,UAAI,OAAO,KAAK;AACd,cAAM,IAAI,QAAc,SAAO;AAC7B,gBAAM,KAAKE,iBAAgB,EAAE,OAAOC,kBAAiB,MAAM,EAAE,UAAU,QAAQ,OAAO,KAAK,KAAK,OAAO,EAAE,CAAC,EAAE,CAAC;AAC7G,aAAG,GAAG,QAAQ,OAAK,IAAI,CAAC,CAAC;AACzB,aAAG,GAAG,SAAS,MAAM;AAAE,kBAAM;AAAM,gBAAI;AAAA,UAAG,CAAC;AAAA,QAC7C,CAAC;AAAA,MACH,WAAW,OAAO,KAAK;AAErB,cAAM;AAAA,MACR;AAAA,IACF;AACA,IAAAC,WAAU,MAAM,EAAE,UAAU,IAAI,GAAG,MAAM;AAAE,WAAK,KAAK;AAAA,IAAG,CAAC;AACzD,YAAQ,KAAK,UAAU,MAAM;AAAE,MAAAC,aAAY,IAAI;AAAG,MAAAJ,SAAQ,CAAC;AAAA,IAAG,CAAC;AAAA,EACjE,CAAC;AACH;AAIA,eAAsB,WAAW,MAA2D;AAC1F,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,QAAM,cAAc,KAAK,eAAe;AACxC,QAAM,QAAQ,KAAK,OAAO,SAAS,IAAI,QAAM,EAAE,MAAM,EAAE,MAAM,KAAKL,MAAK,KAAK,SAAS,EAAE,GAAG,EAAE,EAAE;AAC9F,QAAM,QAAQ,CAAC,GAAG,KAAK;AACvB,QAAM,SAAmB,CAAC;AAC1B,MAAI,WAAW;AAEf,QAAM,IAAI,QAAc,CAAAK,aAAW;AACjC,UAAM,OAAO,MAAM;AACjB,aAAO,WAAW,eAAe,MAAM,QAAQ;AAC7C,cAAM,OAAO,MAAM,MAAM;AACzB;AACA,mBAAW,KAAK,KAAK,KAAK,GAAG,EAAE,KAAK,QAAM;AACxC;AACA,cAAI,GAAI,KAAI,UAAK,KAAK,IAAI,EAAE;AAAA,eACvB;AAAE,mBAAO,KAAK,KAAK,IAAI;AAAG,gBAAI,UAAK,KAAK,IAAI,EAAE;AAAA,UAAG;AACtD,cAAI,MAAM,WAAW,KAAK,aAAa,EAAG,CAAAA,SAAQ;AAAA,cAC7C,MAAK;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AACA,SAAK;AAAA,EACP,CAAC;AAED,MAAI,OAAO,QAAQ;AACjB,QAAI;AAAA,UAAa,OAAO,KAAK,IAAI,CAAC,EAAE;AACpC,WAAO;AAAA,EACT;AACA,MAAI;AAAA,EAAK,MAAM,MAAM,sBAAsB;AAC3C,SAAO;AACT;AAEA,SAAS,WAAW,KAAa,KAA+C;AAC9E,MAAI,CAACF,aAAW,GAAG,EAAG,QAAO,QAAQ,QAAQ,KAAK;AAClD,MAAI,CAAC,aAAa,GAAG,EAAG,QAAO,QAAQ,QAAQ,IAAI;AACnD,SAAO,IAAI,QAAQ,CAAAE,aAAW;AAC5B,UAAM,UAAU,QAAQ,aAAa,UAAU,YAAY;AAC3D,UAAM,OAAOK,OAAM,SAAS,CAAC,SAAS,GAAG,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,UAAU,MAAM,EAAE,CAAC;AAC1F,SAAK,GAAG,SAAS,UAAQ;AACvB,UAAI,SAAS,GAAG;AAAE,0BAAkB,GAAG;AAAG,QAAAL,SAAQ,IAAI;AAAA,MAAG,MAAO,CAAAA,SAAQ,KAAK;AAAA,IAC/E,CAAC;AACD,SAAK,GAAG,SAAS,MAAMA,SAAQ,KAAK,CAAC;AAAA,EACvC,CAAC;AACH;AAIA,eAAsB,UAAU,MAAgC;AAC9D,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,MAAI,GAAG,KAAK,OAAO,QAAQ,WAAI,IAAI,KAAK,OAAO,IAAI,WAAM,KAAK,OAAO,SAAS,MAAM,WAAW;AAC/F,MAAI,EAAE;AAEN,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,OAAO,SAAS,IAAI,OAAK,EAAE,KAAK,MAAM,GAAG,EAAE;AAC3E,MAAI,GAAG,UAAU,OAAO,MAAM,CAAC,KAAK,OAAO,SAAS,CAAC,CAAC,KAAK,OAAO,OAAO,CAAC,CAAC,UAAU;AACrF,MAAI,IAAI,OAAO,SAAS,EAAE,CAAC;AAE3B,aAAW,OAAO,KAAK,OAAO,UAAU;AACtC,UAAM,KAAK,MAAM,YAAY,IAAI,MAAM,IAAI,WAAW;AACtD,UAAM,SAAS,KAAK,cAAS;AAC7B,QAAI,GAAG,IAAI,KAAK,OAAO,MAAM,CAAC,KAAK,OAAO,IAAI,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,KAAK,OAAO,CAAC,CAAC,KAAK,MAAM,EAAE;AAAA,EACrG;AACA,SAAO;AACT;AAgBA,SAAS,UAAU,MAAoB,KAAgC;AACrE,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,OAAK,EAAE,KAAK,MAAM,GAAG,CAAC;AAC1D,aAAW,KAAK,MAAM;AACpB,UAAM,MAAM,EAAE,OAAO,OAAO,OAAO,EAAE,GAAG,KAAK;AAC7C,UAAM,OAAO,EAAE,KAAK,OAAO,MAAM;AACjC,UAAM,OAAO,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC;AACpC,UAAM,SAAS,EAAE,OAAO,OAAO,CAAC;AAChC,UAAM,SAAS,EAAE,OAAO,OAAO,CAAC;AAChC,QAAI,GAAG,IAAI,KAAK,IAAI,KAAK,MAAM,KAAK,MAAM,KAAK,GAAG,YAAY,EAAE,MAAM,cAAc,EAAE,QAAQ,EAAE;AAAA,EAClG;AACF;AAEA,eAAsB,OAAO,MAAgB,MAAgC;AAC3E,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,OAAO,MAAM,IAAI,IAAI;AACrE,QAAM,SAAS,KAAK,CAAC;AACrB,QAAM,SAAS,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,IAAI;AAC9D,QAAM,aAAa,cAAc,KAAK,OAAO,MAAM,KAAK,UAAU;AAElE,MAAI,CAAC,UAAU,WAAW,QAAQ;AAChC,QAAI,6CAA6C;AACjD,QAAI,0DAA0D;AAC9D,QAAI,kEAAkE;AACtE,QAAI,4EAA4E;AAChF,QAAI,kDAAkD;AACtD,QAAI,+CAA+C;AACnD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,uBAAmB,YAAY,KAAK,OAAO,IAAI;AAAA,EACjD,SAAS,GAAQ;AACf,QAAI,EAAE,OAAO;AACb,WAAO;AAAA,EACT;AAEA,MAAI;AACF,QAAI,WAAW,QAAQ;AACrB,YAAM,MAAM,MAAM,QAAQ,YAAY,MAAM;AAC5C,UAAI,YAAY,IAAI,EAAE,EAAE;AACxB,aAAO;AAAA,IACT;AAEA,QAAI,WAAW,YAAY,CAAC,QAAQ;AAClC,YAAM,MAAM,MAAM,QAAQ,YAAY,QAAQ;AAC9C,UAAI,CAAC,IAAI,SAAS,QAAQ;AAAE,YAAI,eAAe;AAAG,eAAO;AAAA,MAAG;AAC5D,gBAAU,IAAI,UAAU,GAAG;AAC3B,aAAO;AAAA,IACT;AAEA,QAAI,WAAW,YAAY,QAAQ;AACjC,aAAO,MAAM,IAAI,QAAgB,CAAAA,aAAW;AAC1C,cAAM,QAAQ,WAAW,YAAY,iBAAiB,CAAC,GAAG,WAAS;AACjE,gBAAM,OAAO,MAAM;AACnB,gBAAM,MAAK,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,IAAI,EAAE;AAChD,qBAAW,KAAK,MAAM;AACpB,gBAAI,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,MAAM,EAAE;AAAA,UAC7D;AAAA,QACF,GAAG,SAAO;AAAE,cAAI,UAAU,IAAI,OAAO,EAAE;AAAG,UAAAA,SAAQ,CAAC;AAAA,QAAG,CAAC;AACvD,gBAAQ,KAAK,UAAU,MAAM;AAAE,gBAAM;AAAG,UAAAA,SAAQ,CAAC;AAAA,QAAG,CAAC;AAAA,MACvD,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,QAAQ;AACrB,YAAM,MAAM,KAAK,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,EAAE,WAAW,GAAG,CAAC;AAC3D,UAAI,CAAC,KAAK;AAAE,YAAI,4CAA4C;AAAG,eAAO;AAAA,MAAG;AAEzE,UAAI,CAAC,QAAQ;AACX,cAAM,MAAM,MAAM,QAAQ,YAAY,aAAa,EAAE,KAAK,OAAO,IAAI,CAAC;AACtE,mBAAW,KAAK,IAAI,MAAO,KAAI,CAAC;AAChC,eAAO;AAAA,MACT;AAEA,aAAO,MAAM,IAAI,QAAgB,CAAAA,aAAW;AAC1C,cAAM,QAAQ,WAAW,YAAY,eAAe,EAAE,KAAK,MAAM,IAAI,GAAG,WAAS;AAC/E,cAAI,MAAM,IAAc;AAAA,QAC1B,GAAG,SAAO;AAAE,cAAI,UAAU,IAAI,OAAO,EAAE;AAAG,UAAAA,SAAQ,CAAC;AAAA,QAAG,CAAC;AACvD,gBAAQ,KAAK,UAAU,MAAM;AAAE,gBAAM;AAAG,UAAAA,SAAQ,CAAC;AAAA,QAAG,CAAC;AAAA,MACvD,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,WAAW;AACxB,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,CAAC,KAAK;AAAE,YAAI,oCAAoC;AAAG,eAAO;AAAA,MAAG;AACjE,YAAM,QAAQ,YAAY,WAAW,EAAE,IAAI,CAAC;AAC5C,UAAI,0BAAqB,GAAG,EAAE;AAC9B,aAAO;AAAA,IACT;AAEA,QAAI,WAAW,QAAQ;AACrB,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,CAAC,KAAK;AAAE,YAAI,iCAAiC;AAAG,eAAO;AAAA,MAAG;AAC9D,YAAM,QAAQ,YAAY,QAAQ,EAAE,IAAI,CAAC;AACzC,UAAI,uBAAkB,GAAG,EAAE;AAC3B,aAAO;AAAA,IACT;AAEA,QAAI,uBAAuB,MAAM,qCAAqC;AACtE,WAAO;AAAA,EACT,SAAS,GAAQ;AACf,QAAI,UAAU,EAAE,OAAO,EAAE;AACzB,WAAO;AAAA,EACT;AACF;AAIA,eAAsB,QAAQ,MAAgC;AAC5D,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,OAAO,MAAM,IAAI,IAAI;AACrE,SAAO,WAAW,KAAK,OAAO,MAAM,EAAE,IAAI,CAAC;AAC7C;AAIO,SAAS,QAAQ,MAAgB,OAAsC,CAAC,GAAW;AACxF,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,QAAQ,QAAQ;AAClB,QAAI,2CAA2C;AAC/C,QAAI,6EAA6E;AACjF,QAAI,kDAAkD;AACtD,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW;AACrB,QAAI,sBAAsB;AAC1B,QAAI,6EAA6E;AACjF,QAAI,kEAAkE;AACtE,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,UAAU;AACpB,QAAI,qBAAqB;AACzB,QAAI,0EAA0E;AAC9E,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,OAAO;AACjB,QAAI,6CAA6C;AACjD,QAAI,0EAA0E;AAC9E,QAAI,EAAE;AACN,QAAI,0DAA0D;AAC9D,QAAI,8EAA8E;AAClF,QAAI,+EAA+E;AACnF,QAAI,0DAA0D;AAC9D,QAAI,uDAAuD;AAC3D,QAAI,EAAE;AACN,QAAI,wDAAwD;AAC5D,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,MAAM;AAChB,QAAI,oBAAoB;AACxB,QAAI,yEAAyE;AAC7E,QAAI,yEAAyE;AAC7E,QAAI,0EAA0E;AAC9E,QAAI,kEAA6D;AACjE,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,QAAQ;AAClB,QAAI,mBAAmB;AACvB,QAAI,oEAAoE;AACxE,QAAI,oEAAoE;AACxE,WAAO;AAAA,EACT;AACA,MAAI,cAAc;AAClB,MAAI,iEAAiE;AACrE,MAAI,4EAA4E;AAChF,MAAI,0EAA0E;AAC9E,MAAI,4EAA4E;AAChF,MAAI,6DAA6D;AACjE,MAAI,qFAAqF;AACzF,MAAI,yEAAyE;AAC7E,MAAI,EAAE;AACN,MAAI,kDAA6C;AACjD,SAAO;AACT;;;A2B9UA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,cAAcM,cAAa;AAIpC,IAAM,YAAY,UAAU,IAAI;AAahC,IAAM,SAAS,QAAQ,aAAa,WAAW,QAAQ,aAAa;AAIpE,eAAsB,eAAe,MAA0C;AAC7E,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI;AAKF,UAAM,EAAE,OAAO,IAAI,MAAM,UAAU,kBAAkB,IAAI,sBAAsB;AAC/E,WAAO,UAAU,MAAM;AAAA,EACzB,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,QAAmC;AAGpD,MAAI,MAAqB;AACzB,MAAI,MAAM;AACV,aAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,QAAI,CAAC,KAAM;AACX,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,QAAI,QAAQ,KAAK;AAEf,UAAI,OAAO,KAAM,QAAO,EAAE,KAAK,SAAS,OAAO,UAAU;AACzD,YAAM,OAAO,KAAK;AAAA,IACpB,WAAW,QAAQ,KAAK;AACtB,YAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,OAAO,KAAM,QAAO,EAAE,KAAK,SAAS,OAAO,UAAU;AACzD,SAAO;AACT;AAOA,eAAsB,kBAAkB,UAAoD;AAC1F,QAAM,YAA4B,CAAC;AACnC,aAAW,OAAO,UAAU;AAC1B,UAAM,WAAW,MAAM,eAAe,IAAI,IAAI;AAC9C,QAAI,SAAU;AACd,UAAM,SAAS,MAAM,eAAe,IAAI,IAAI;AAC5C,cAAU,KAAK,EAAE,SAAS,IAAI,MAAM,MAAM,IAAI,MAAM,OAAO,CAAC;AAAA,EAC9D;AACA,SAAO;AACT;AAGA,eAAsB,WAAW,KAAa,UAAU,KAAwB;AAC9E,MAAI;AAAE,YAAQ,KAAK,KAAK,SAAS;AAAA,EAAG,QAAQ;AAAE,WAAO;AAAA,EAAO;AAC5D,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI,CAACC,UAAS,GAAG,EAAG,QAAO;AAC3B,UAAMC,OAAM,GAAG;AAAA,EACjB;AACA,MAAI;AAAE,YAAQ,KAAK,KAAK,SAAS;AAAA,EAAG,QAAQ;AAAA,EAAqB;AAEjE,QAAMA,OAAM,GAAG;AACf,SAAO,CAACD,UAAS,GAAG;AACtB;AAEA,SAASA,UAAS,KAAsB;AACtC,MAAI;AAAE,YAAQ,KAAK,KAAK,CAAC;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAO;AACnE;AAeA,eAAsB,qBACpB,WACA,MACkB;AAClB,MAAI,CAAC,UAAU,OAAQ,QAAO;AAE9B,QAAM,EAAE,UAAU,KAAK,QAAQ,gBAAgB,QAAQ,MAAM,SAAS,MAAM,IAAI;AAGhF,MAAI,2DAAsD;AAC1D,MAAI,EAAE;AACN,QAAM,UAAU,KAAK,IAAI,GAAG,UAAU,IAAI,OAAK,EAAE,QAAQ,MAAM,GAAG,CAAC;AACnE,aAAW,KAAK,WAAW;AACzB,UAAM,SAAS,EAAE,SACb,OAAO,EAAE,OAAO,GAAG,aAAa,EAAE,OAAO,OAAO,KAChD,6BAA6B,SAAS,KAAK,+BAA0B;AACzE,QAAI,MAAM,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,QAAQ,OAAO,OAAO,CAAC,KAAK,MAAM,EAAE;AAAA,EAC9E;AACA,MAAI,EAAE;AAEN,MAAI,UAAU;AACZ,WAAO,MAAM,QAAQ,WAAW,GAAG;AAAA,EACrC;AAEA,MAAI,CAAC,iBAAiB,CAAC,QAAQ;AAC7B,QAAI,6EAA6E;AACjF,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM,OAAO;AAC/B,MAAI,CAAC,WAAW;AACd,QAAI,qCAAgC;AACpC,WAAO;AAAA,EACT;AACA,SAAO,MAAM,QAAQ,WAAW,GAAG;AACrC;AAEA,eAAe,QAAQ,WAA2B,KAA4C;AAC5F,MAAI,QAAQ;AACZ,aAAW,KAAK,WAAW;AACzB,QAAI,CAAC,EAAE,QAAQ;AACb,UAAI,WAAM,EAAE,IAAI,IAAI,EAAE,OAAO,8CAAyC;AACtE,cAAQ;AACR;AAAA,IACF;AACA,UAAM,KAAK,MAAM,WAAW,EAAE,OAAO,GAAG;AACxC,QAAI,IAAI;AACN,UAAI,WAAM,EAAE,IAAI,IAAI,EAAE,OAAO,gBAAgB,EAAE,OAAO,GAAG,EAAE;AAAA,IAC7D,OAAO;AACL,UAAI,WAAM,EAAE,IAAI,IAAI,EAAE,OAAO,SAAS,EAAE,OAAO,GAAG,mBAAmB;AACrE,cAAQ;AAAA,IACV;AAAA,EACF;AACA,SAAO;AACT;;;AC3KA,eAAsB,iBAAoC;AACxD,UAAQ,QAAQ,UAAU;AAAA,IACxB,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,aAAO,IAAI,cAAc;AAAA,IAC3B;AAAA,IACA,KAAK,UAAU;AACb,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,sBAAa;AACrD,aAAO,IAAI,eAAe;AAAA,IAC5B;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,aAAO,IAAI,cAAc;AAAA,IAC3B;AAAA,IACA;AACE,YAAM,IAAI,MAAM,yBAAyB,QAAQ,QAAQ,EAAE;AAAA,EAC/D;AACF;;;ACnBA,SAAS,cAAAE,cAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,WAAAC,gBAAe;AAGxB,IAAM,eAAe;AAEd,IAAM,kBAAN,MAAqD;AAAA,EACjD,OAAO;AAAA,EAEhB,SAAS,UAAqC,MAAyB;AACrE,UAAM,UAAoB,CAAC;AAC3B,UAAM,OAAiB,CAAC;AAExB,eAAW,CAAC,MAAM,EAAE,KAAK,UAAU;AACjC,UAAI,GAAG,WAAW,KAAM;AACxB,YAAM,MAAM,KAAK,OAAO,IAAI;AAC5B,UAAI,QAAQ,OAAW;AAEvB,YAAM,OAAO,MAAM,UAAU,GAAG,IAAI,KAAK,MAAM,QAAQ,UAAU,KAAK,MAAM;AAC5E,YAAM,OAAO,KAAK,QAAQ,eAAe,GAAG;AAC5C,YAAM,OAAO,GAAG,YAAY,GAAG;AAE/B,UAAI,SAAS,OAAO,IAAI;AAAA,eAAmB,IAAI;AAAA,iBAAqB,IAAI;AAAA;AAAA,YAAmC,KAAK,UAAU;AAC1H,UAAI,KAAK,IAAK,WAAU;AAAA;AAAA;AACxB,cAAQ,KAAK,MAAM;AAEnB,WAAK,KAAK,OAAO,IAAI;AAAA;AAAA;AAAA,2BAAsE,KAAK,IAAI,IAAI,IAAI,GAAG;AAAA,IACjH;AAEA,QAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,WAAO;AAAA;AAAA,EAAsB,QAAQ,KAAK,IAAI,CAAC;AAAA;AAAA,EAAkB,KAAK,KAAK,IAAI,CAAC;AAAA;AAAA,EAClF;AAAA,EAEA,MAAM,SAAiB,MAAuB;AAC5C,UAAM,MAAMA,SAAQ,KAAK,QAAQ;AACjC,QAAI,CAACH,aAAW,GAAG,EAAG,CAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,IAAAC,eAAc,KAAK,UAAU,OAAO;AAAA,EACtC;AAAA,EAEA,MAAM,MAAuB;AAC3B,SAAK,MAAM,cAAc,IAAI;AAAA,EAC/B;AACF;;;AC1CA,SAAS,cAAAE,cAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,WAAAC,gBAAe;AAGxB,IAAMC,gBAAe;AAId,IAAM,gBAAN,MAAmD;AAAA,EAC/C,OAAO;AAAA,EAEhB,SAAS,UAAqC,MAAyB;AACrE,UAAM,SAAmB,CAAC;AAE1B,eAAW,CAAC,MAAM,EAAE,KAAK,UAAU;AACjC,UAAI,GAAG,WAAW,KAAM;AACxB,YAAM,MAAM,KAAK,OAAO,IAAI;AAC5B,UAAI,QAAQ,OAAW;AAEvB,YAAM,aAAa,MAAM,GAAG,GAAG,IAAI,KAAK,MAAM,KAAK,KAAK;AACxD,YAAM,OAAO,GAAG,YAAY,GAAG;AAC/B,YAAM,SAAS,KAAK,MAAM,YAAY;AAEtC,YAAM,WAAW,KAAK,MAClB,4CAA4C,UAAU;AAAA,2CACV,UAAU;AAAA,IACtD;AAEJ,aAAO;AAAA,QACL;AAAA,aACc,MAAM;AAAA,kBACD,UAAU;AAAA,IAC7B,WACA;AAAA,4BAC6B,KAAK,IAAI,IAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUhD;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,OAAQ,QAAOA;AAC3B,WAAO,OAAO,KAAK,MAAM,IAAI;AAAA,EAC/B;AAAA,EAEA,MAAM,SAAiB,MAAuB;AAC5C,UAAM,MAAMD,SAAQ,KAAK,QAAQ;AACjC,QAAI,CAACH,aAAW,GAAG,EAAG,CAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,IAAAC,eAAc,KAAK,UAAU,OAAO;AAAA,EACtC;AAAA,EAEA,MAAM,MAAuB;AAC3B,SAAK,MAAME,eAAc,IAAI;AAAA,EAC/B;AACF;;;AC5DA,SAAS,cAAAC,cAAY,aAAAC,YAAW,iBAAAC,sBAAqB;AACrD,SAAS,WAAAC,gBAAe;AAGxB,IAAMC,gBAAe;AAId,IAAM,gBAAN,MAAmD;AAAA,EAC/C,OAAO;AAAA,EAEhB,SAAS,UAAqC,MAAyB;AACrE,UAAM,SAAmB,CAAC;AAE1B,eAAW,CAAC,MAAM,EAAE,KAAK,UAAU;AACjC,UAAI,GAAG,WAAW,KAAM;AACxB,YAAM,MAAM,KAAK,OAAO,IAAI;AAC5B,UAAI,QAAQ,OAAW;AAEvB,YAAM,OAAO,MAAM,GAAG,GAAG,IAAI,KAAK,MAAM,KAAK,KAAK;AAClD,YAAM,OAAO,GAAG,YAAY,GAAG;AAC/B,YAAM,WAAW,KAAK,MAAM,OAAO,UAAU,IAAI;AAEjD,aAAO;AAAA,QACL,GAAG,QAAQ;AAAA,oBACU,KAAK,IAAI,IAAI,IAAI;AAAA;AAAA,MAExC;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,OAAQ,QAAOA;AAC3B,WAAO,OAAO,KAAK,MAAM,IAAI;AAAA,EAC/B;AAAA,EAEA,MAAM,SAAiB,MAAuB;AAC5C,UAAM,MAAMD,SAAQ,KAAK,QAAQ;AACjC,QAAI,CAACH,aAAW,GAAG,EAAG,CAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,IAAAC,eAAc,KAAK,UAAU,OAAO;AAAA,EACtC;AAAA,EAEA,MAAM,MAAuB;AAC3B,SAAK,MAAME,eAAc,IAAI;AAAA,EAC/B;AACF;;;ACtCA,IAAM,YAAuD;AAAA,EAC3D,SAAS,MAAM,IAAI,gBAAgB;AAAA,EACnC,OAAO,MAAM,IAAI,cAAc;AAAA,EAC/B,OAAO,MAAM,IAAI,cAAc;AACjC;AAEO,SAAS,oBAAoB,MAAmC;AACrE,QAAM,UAAU,UAAU,IAAI;AAC9B,MAAI,CAAC,SAAS;AACZ,UAAM,YAAY,OAAO,KAAK,SAAS,EAAE,KAAK,IAAI;AAClD,UAAM,IAAI,MAAM,4BAA4B,IAAI,iBAAiB,SAAS,EAAE;AAAA,EAC9E;AACA,SAAO,QAAQ;AACjB;;;AClBA,SAAgB,eAAAC,cAAa,UAAAC,eAAc;AAC3C,SAAS,OAAAC,MAAK,QAAAC,aAAY;;;ACD1B,SAAS,UAAU,WAAW,QAAQ,mBAAmB;AAsBlD,SAAS,kBACd,UACA,SACA,KACA,UAA0B,MAC1B;AACA,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAoC,oBAAI,IAAI,CAAC;AACzE,QAAM,CAAC,MAAM,OAAO,IAAI,SAAqB,CAAC,CAAC;AAC/C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoC,oBAAI,IAAI,CAAC;AACvE,QAAM,SAAS,OAA8B,IAAI;AACjD,QAAM,UAAU,OAAmD,oBAAI,IAAI,CAAC;AAC5E,QAAM,YAAY,OAAO,KAAK;AAC9B,QAAM,iBAAiB,OAAmB,CAAC,CAAC;AAC5C,QAAM,UAAU,OAAuB,OAAO;AAC9C,UAAQ,UAAU;AAGlB,QAAM,SAAS,OAAO,IAAI,YAA2C,CAAC;AACtE,QAAM,WAAW,OAAO,IAAI,YAAmD,CAAC;AAEhF,YAAU,MAAM;AACd,UAAMC,OAAM,IAAI,eAAe;AAAA,MAC7B;AAAA,MAAS;AAAA,MAAK;AAAA,MACd,QAAQ;AAAA,QACN,OAAO,CAAC,SAAS,MAAM,aAAa;AAClC,kBAAQ,SAAS,MAAM,SAAS,IAAI;AACpC,iBAAO,QAAQ,KAAK,EAAE,KAAK,SAAS,KAAK,CAAC;AAC1C,gBAAM,QAAkB,EAAE,SAAS,MAAM,UAAU,IAAI,KAAK,IAAI,GAAG,OAAO,eAAe,IAAI,EAAE;AAC/F,cAAI,UAAU,SAAS;AACrB,2BAAe,QAAQ,KAAK,KAAK;AACjC,gBAAI,eAAe,QAAQ,SAAS,KAAM;AACxC,6BAAe,UAAU,eAAe,QAAQ,MAAM,IAAK;AAAA,YAC7D;AACA;AAAA,UACF;AACA,kBAAQ,UAAQ;AACd,kBAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,mBAAO,KAAK,SAAS,MAAO,KAAK,MAAM,IAAK,IAAI;AAAA,UAClD,CAAC;AAAA,QACH;AAAA,QACA,eAAe,CAAC,MAAM,UAAU;AAC9B,mBAAS,QAAQ,KAAK,EAAE,MAAM,MAAM,CAAC;AACrC,oBAAU,IAAI,IAAIA,KAAI,KAAK,CAAC;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,CAAC;AACD,WAAO,UAAUA;AACjB,WAAO,MAAM;AAAE,MAAAA,KAAI,QAAQ;AAAA,IAAG;AAAA,EAChC,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC;AAG3B,YAAU,MAAM;AACd,UAAM,KAAK,YAAY,YAAY;AACjC,YAAMA,OAAM,OAAO;AACnB,UAAI,CAACA,KAAK;AACV,YAAMA,KAAI,eAAe;AACzB,gBAAU,IAAI,IAAIA,KAAI,KAAK,CAAC;AAE5B,YAAM,OAAiB,CAAC;AACxB,YAAM,SAAS,oBAAI,IAAoB;AACvC,iBAAW,CAAC,MAAM,EAAE,KAAKA,KAAI,OAAO;AAClC,YAAI,GAAG,KAAK;AAAE,eAAK,KAAK,GAAG,GAAG;AAAG,iBAAO,IAAI,GAAG,KAAK,IAAI;AAAA,QAAG;AAAA,MAC7D;AACA,UAAI,KAAK,QAAQ;AACf,cAAM,MAAM,MAAM,SAAS,gBAAgB,IAAI;AAC/C,cAAM,OAAO,oBAAI,IAA0B;AAC3C,mBAAW,CAAC,KAAK,IAAI,KAAK,KAAK;AAC7B,gBAAM,OAAO,OAAO,IAAI,GAAG;AAC3B,cAAI,CAAC,KAAM;AACX,gBAAM,OAAO,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,EAAE;AACrE,gBAAM,SAAS,eAAe,KAAK,YAAY,KAAK,KAAK,KAAK,IAAI;AAClE,kBAAQ,QAAQ,IAAI,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,KAAK,WAAW,CAAC;AACpE,eAAK,IAAI,MAAM,EAAE,KAAK,OAAO,QAAQ,CAAC,IAAI,KAAK,MAAM,KAAK,MAAM,MAAM,QAAQ,CAAC,IAAI,MAAM,CAAC;AAAA,QAC5F;AACA,iBAAS,IAAI;AAAA,MACf;AAAA,IACF,GAAG,GAAI;AACP,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,MAAM,OAAO;AAEnB,QAAM,YAAY,YAAY,MAAM;AAAE,mBAAe,UAAU,CAAC;AAAG,YAAQ,CAAC,CAAC;AAAA,EAAG,GAAG,CAAC,CAAC;AAGrF,QAAM,UAAU,YAAY,CAAC,SAAiB,MAAc,WAAW,MAAM;AAC3E,YAAQ,SAAS,MAAM,SAAS,IAAI;AACpC,WAAO,QAAQ,KAAK,EAAE,KAAK,SAAS,KAAK,CAAC;AAC1C,UAAM,QAAkB,EAAE,SAAS,MAAM,UAAU,IAAI,KAAK,IAAI,GAAG,OAAO,eAAe,IAAI,EAAE;AAC/F,QAAI,UAAU,SAAS;AACrB,qBAAe,QAAQ,KAAK,KAAK;AACjC,UAAI,eAAe,QAAQ,SAAS,KAAM;AACxC,uBAAe,UAAU,eAAe,QAAQ,MAAM,IAAK;AAAA,MAC7D;AACA;AAAA,IACF;AACA,YAAQ,UAAQ;AACd,YAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,aAAO,KAAK,SAAS,MAAO,KAAK,MAAM,IAAK,IAAI;AAAA,IAClD,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,YAAY,YAAY,CAAC,WAAoB;AACjD,cAAU,UAAU;AACpB,QAAI,CAAC,UAAU,eAAe,QAAQ,QAAQ;AAC5C,YAAM,QAAQ,eAAe;AAC7B,qBAAe,UAAU,CAAC;AAC1B,cAAQ,UAAQ;AACd,cAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,eAAO,KAAK,SAAS,MAAO,KAAK,MAAM,IAAK,IAAI;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IAAQ;AAAA,IAAM;AAAA,IACd,OAAO,YAAY,CAAC,KAAoB,aAAqB,KAAK,MAAM,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC;AAAA,IAC7F,MAAM,YAAY,CAAC,SAAiB,KAAK,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AAAA,IAC1D,SAAS,YAAY,CAAC,SAAiB,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC;AAAA,IAChE,SAAS,YAAY,CAAC,KAAoB,aAAqB,KAAK,QAAQ,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC;AAAA,IACjG,SAAS,YAAY,MAAM,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,QAAQ,OAAO;AAAA,IACf,UAAU,SAAS;AAAA,EACrB;AACF;;;ACtJA,SAAS,gBAAgB;AACzB,SAAgB,YAAAC,WAAU,eAAAC,oBAAmB;AAsB7C,IAAM,aAAa,CAAC,QAAQ,OAAO,QAAQ;AAI3C,SAAS,SAAS,UAA0D,OAAe;AACzF,WAAS,OAAK;AACZ,QAAI,EAAE,UAAU,QAAQ;AAEtB,YAAMC,QAAO,EAAE,mBAAmB;AAClC,aAAO,EAAE,GAAG,GAAG,kBAAkB,KAAK,IAAI,GAAGA,KAAI,EAAE;AAAA,IACrD;AACA,UAAM,OAAO,EAAE,oBAAoB;AACnC,WAAO,EAAE,GAAG,GAAG,mBAAmB,KAAK,IAAI,GAAG,IAAI,EAAE;AAAA,EACtD,CAAC;AACH;AAEA,SAAS,SAAS,UAA0D,QAA0B;AACpG,WAAS,OAAK;AACZ,QAAI,EAAE,UAAU,QAAQ;AAEtB,aAAO,EAAE,GAAG,GAAG,kBAAkB,WAAW,QAAQ,OAAO,mBAAmB,EAAE;AAAA,IAClF;AACA,WAAO,EAAE,GAAG,GAAG,mBAAmB,WAAW,QAAQ,IAAI,OAAO,iBAAiB;AAAA,EACnF,CAAC;AACH;AAEO,SAAS,eAAe,MAI5B;AACD,QAAM,CAAC,OAAO,QAAQ,IAAIF,UAAmB;AAAA,IAC3C,OAAO;AAAA,IAAQ,OAAO;AAAA,IAAQ,WAAW;AAAA,IAAM,YAAY;AAAA,IAC3D,YAAY;AAAA,IAAO,gBAAgB;AAAA,IAAO,SAAS;AAAA,IAAG,cAAc;AAAA,IACpE,kBAAkB;AAAA,IAAG,mBAAmB;AAAA,IAAG,aAAa;AAAA,IAAO,cAAc;AAAA,EAC/E,CAAC;AAED,QAAM,cAA6B,CAAC,OAAO,SAAS,MAAM;AAE1D,QAAM,WAAWC,aAAY,CAAC,UAAiB,SAAS,QAAM,EAAE,GAAG,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;AACnF,QAAM,YAAYA,aAAY,CAAC,MAAqB,SAAS,QAAM,EAAE,GAAG,GAAG,WAAW,GAAG,OAAO,OAAO,EAAE,GAAG,CAAC,CAAC;AAC9G,QAAM,YAAYA,aAAY,CAAC,MAAqB,SAAS,QAAM,EAAE,GAAG,GAAG,YAAY,GAAG,OAAO,OAAO,EAAE,GAAG,CAAC,CAAC;AAE/G,QAAM,WAAW,QAAQ,MAAM,SAAS;AAExC,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,MAAM,UAAU,OAAQ;AAE5B,QAAI,UAAU,OAAQ,IAAI,QAAQ,UAAU,IAAM,MAAK,OAAO;AAAA,aAErD,IAAI,QAAQ,UAAU,IAAK,UAAS,UAAU,KAAK;AAAA,aACnD,IAAI,QAAQ,UAAU,IAAK,UAAS,UAAU,QAAQ;AAAA,aACtD,IAAI,QAAQ,UAAU,IAAK,UAAS,UAAU,GAAG;AAAA,aACjD,IAAI,QAAQ,UAAU,IAAK,UAAS,UAAU,EAAG;AAAA,aACjD,IAAI,QAAuB,UAAS,UAAU,EAAE;AAAA,aAChD,IAAI,UAAuB,UAAS,UAAU,CAAE;AAAA,aAChD,UAAU,IAAiB,UAAS,UAAU,GAAG;AAAA,aACjD,UAAU,IAAiB,UAAS,UAAU,EAAG;AAAA,aAEjD,UAAU,IAAK,MAAK,YAAY;AAAA,aAChC,IAAI,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,OAAO,EAAE,UAAU,SAAS,UAAU,OAAO,EAAE;AAAA,aAC/E,UAAU,IAAK,UAAS,QAAQ;AAAA,aAChC,UAAU,IAAK,UAAS,SAAS;AAAA,aACjC,UAAU,IAAK,UAAS,MAAM;AAAA,aAC9B,UAAU,IAAK,UAAS,QAAQ;AAAA,aAChC,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,WAAW,MAAM,YAAY,MAAM,aAAa,MAAM,EAAE;AAAA,aAC9F,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,YAAY,CAAC,EAAE,WAAW,EAAE;AAAA,aAClE,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,gBAAgB,CAAC,EAAE,eAAe,EAAE;AAAA,aAC1E,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,UAAU,EAAE,UAAU,KAAK,WAAW,OAAO,EAAE;AAAA,aACrF,UAAU,KAAK;AAAE,WAAK,cAAc;AAAG,eAAS,QAAM,EAAE,GAAG,GAAG,cAAc,CAAC,EAAE,aAAa,EAAE;AAAA,IAAG,WACjG,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,aAAa,aAAa,YAAY,QAAQ,EAAE,WAAW,IAAI,KAAK,YAAY,MAAM,EAAG,EAAE;AAAA,aACjI,UAAU,IAAK,UAAS,QAAM,EAAE,GAAG,GAAG,cAAc,CAAC,EAAE,aAAa,EAAE;AAAA,EACjF,GAAG,EAAE,SAAS,CAAC;AAEf,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,WAAW,MAAM,OAAO;AAAA;AAAA,IAElC,iBAAiBA,aAAY,MAAM,SAAS,QAAM,EAAE,GAAG,GAAG,kBAAkB,EAAE,EAAE,GAAG,CAAC,CAAC;AAAA,IACrF,kBAAkBA,aAAY,MAAM,SAAS,QAAM,EAAE,GAAG,GAAG,mBAAmB,EAAE,EAAE,GAAG,CAAC,CAAC;AAAA,EACzF;AACF;;;AC3GA,SAAS,aAAAE,YAAW,UAAAC,eAAc;AAI3B,SAAS,aACd,UACA,MACA,QACA,SACA;AACA,QAAM,YAAYA,QAAO,MAAM;AAC/B,QAAM,iBAAiBA,QAAsB,IAAI;AACjD,YAAU,UAAU;AAEpB,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAS;AAEpC,UAAM,OAAO,MAAM;AACjB,YAAM,YAAY,oBAAI,IAA0B;AAChD,iBAAW,CAAC,MAAM,EAAE,KAAK,UAAU,SAAS;AAC1C,kBAAU,IAAI,MAAM,EAAE,MAAM,GAAG,IAAI,MAAM,QAAQ,GAAG,QAAQ,UAAW,GAAG,IAAY,SAAS,CAAC;AAAA,MAClG;AACA,YAAM,UAAU,SAAS,SAAS,WAAW,IAAI;AACjD,UAAI,YAAY,eAAe,QAAS;AACxC,qBAAe,UAAU;AACzB,eAAS,MAAM,SAAS,IAAI;AAAA,IAC9B;AAEA,SAAK;AACL,UAAM,KAAK,YAAY,MAAM,GAAI;AACjC,WAAO,MAAM;AACX,oBAAc,EAAE;AAChB,qBAAe,UAAU;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,UAAU,MAAM,OAAO,CAAC;AAC9B;;;ACnCA,SAAS,aAAAE,YAAW,YAAAC,iBAAgB;AACpC,SAAS,iBAAiB;AAInB,SAAS,kBAA0B;AACxC,QAAM,EAAE,OAAO,IAAI,UAAU;AAC7B,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,QAAQ,QAAQ,EAAE;AACnD,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,WAAW,MAAM,QAAQ,OAAO,QAAQ,EAAE;AAChD,WAAO,GAAG,UAAU,QAAQ;AAC5B,WAAO,MAAM;AAAE,aAAO,IAAI,UAAU,QAAQ;AAAA,IAAG;AAAA,EACjD,GAAG,CAAC,MAAM,CAAC;AACX,SAAO;AACT;;;ACfA,SAAS,aAAAE,kBAAiB;AAInB,SAAS,aACd,WACA,YACA,kBACM;AACN,EAAAA,WAAU,MAAM;AACd,cAAU,cAAc,mBAAmB,CAAC;AAAA,EAC9C,GAAG,CAAC,YAAY,kBAAkB,SAAS,CAAC;AAC9C;;;ACZA,SAAS,aAAAC,YAAW,UAAAC,eAAc;AAClC,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,oBAAAC,mBAAkB,cAAAC,oBAAkB;AAC7C,SAAS,YAAAC,WAAU,WAAAC,UAAS,QAAAC,aAAY;AAejC,SAAS,gBACd,SACA,aACA,SACA,SACA,QACA,UACA,UACA,OACA,UAC4C;AAC5C,QAAM,YAAYC,QAAkC,IAAI;AACxD,QAAM,aAAaA,QAAO,oBAAI,IAA2C,CAAC;AAE1E,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,QAAS;AACd,QAAI,SAAoC;AACxC,KAAC,YAAY;AACX,UAAI;AACF,iBAAS,MAAM,kBAAkB,aAAa;AAAA,UAC5C,QAAQ,MAAM,QAAQ;AAAA,UACtB,SAAS,CAAC,SAAS,QAAQ,QAAQ,IAAI;AAAA,UACvC,MAAM,CAAC,SAAS,QAAQ,KAAK,IAAI;AAAA,UACjC,UAAU,OAAO,SAAS,UAAU;AAClC,gBAAI,CAAC,QAAS,QAAO,CAAC;AACtB,kBAAM,OAAO,QAAQ,QAAQ,OAAO;AACpC,gBAAI,CAACC,aAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,mBAAO,IAAI,QAAkB,CAACC,UAAS,WAAW;AAChD,oBAAM,MAAgB,CAAC;AACvB,oBAAM,KAAKC,iBAAgB,EAAE,OAAOC,kBAAiB,MAAM,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC;AAClF,iBAAG,GAAG,QAAQ,OAAK;AAAE,oBAAI,KAAK,CAAC;AAAG,oBAAI,IAAI,SAAS,MAAO,KAAI,MAAM;AAAA,cAAG,CAAC;AACxE,iBAAG,GAAG,SAAS,MAAMF,SAAQ,GAAG,CAAC;AACjC,iBAAG,GAAG,SAAS,MAAM;AAAA,YACvB,CAAC;AAAA,UACH;AAAA,UACA,WAAW,CAAC,SAAS,WAAW;AAC9B,mBAAO,OAAO,UAAU,CAAC,EAAE,KAAK,KAAK,MAAM;AACzC,kBAAI,YAAY,QAAQ,QAAQ,QAAS,QAAO,KAAK,IAAI;AAAA,YAC3D,CAAC;AAAA,UACH;AAAA,UACA,aAAa,CAAC,aAAa;AACzB,mBAAO,SAAS,UAAU,CAAC,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,KAAK,CAAC;AAAA,UACtE;AAAA,UACA,MAAM,WAAW;AACf,kBAAM,OAAiB,CAAC;AACxB,kBAAM,YAAY,oBAAI,IAAoB;AAC1C,uBAAW,CAAC,MAAM,EAAE,KAAK,QAAQ,OAAO;AACtC,kBAAI,GAAG,KAAK;AAAE,qBAAK,KAAK,GAAG,GAAG;AAAG,0BAAU,IAAI,GAAG,KAAK,IAAI;AAAA,cAAG;AAAA,YAChE;AACA,kBAAM,MAAM,KAAK,SAAS,MAAM,SAAS,gBAAgB,IAAI,IAAI,oBAAI,IAAI;AACzE,kBAAM,WAA2D,CAAC;AAClE,uBAAW,CAAC,IAAI,KAAK,QAAQ,OAAO;AAClC,uBAAS,IAAI,IAAI,EAAE,KAAK,GAAG,OAAO,EAAE;AAAA,YACtC;AACA,uBAAW,CAAC,KAAK,IAAI,KAAK,KAAK;AAC7B,oBAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,kBAAI,CAAC,KAAM;AACX,oBAAM,OAAO,WAAW,QAAQ,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,EAAE;AACxE,oBAAM,MAAM,eAAe,KAAK,YAAY,KAAK,KAAK,KAAK,IAAI;AAC/D,yBAAW,QAAQ,IAAI,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,KAAK,WAAW,CAAC;AACvE,uBAAS,IAAI,IAAI,EAAE,KAAK,KAAK,MAAM,MAAM,EAAE,IAAI,IAAI,OAAO,KAAK,MAAO,KAAK,MAAM,OAAQ,EAAE,IAAI,GAAG;AAAA,YACpG;AACA,mBAAO;AAAA,cACL;AAAA,cACA,QAAQ;AAAA,gBACN,YAAY,KAAK,MAAMG,UAAS,IAAI,OAAO,IAAI;AAAA,gBAC/C,WAAW,KAAK,MAAMC,SAAQ,IAAI,OAAO,IAAI;AAAA,gBAC7C,UAAUC,MAAK,EAAE;AAAA,cACnB;AAAA,YACF;AAAA,UACF;AAAA,UACA,eAAe;AACb,gBAAI,CAAC,MAAO,QAAO;AACnB,mBAAO;AAAA,cACL,QAAQ;AAAA,cACR,UAAU,MAAM,SAAS;AAAA,cACzB,QAAQ,MAAM,KAAK;AAAA,cACnB,KAAK,MAAM,KAAK;AAAA,cAChB,QAAQ,MAAM,KAAK;AAAA,YACrB;AAAA,UACF;AAAA,UACA,UAAU;AACR,mBAAO,EAAE,SAAS,aAAa,SAAS;AAAA,UAC1C;AAAA,QACF,GAAG,EAAE,OAAO,SAAO,QAAQ,SAAS,KAAK,EAAE,EAAE,CAAC;AAC9C,kBAAU,UAAU;AAAA,MACtB,SAAS,GAAQ;AACf,gBAAQ,SAAS,kCAA6B,EAAE,OAAO,IAAI,CAAC;AAAA,MAC9D;AAAA,IACF,GAAG;AACH,WAAO,MAAM;AAAE,WAAK,QAAQ,MAAM;AAAG,gBAAU,UAAU;AAAA,IAAM;AAAA,EACjE,GAAG,CAAC,SAAS,aAAa,SAAS,SAAS,QAAQ,UAAU,UAAU,OAAO,QAAQ,CAAC;AACxF,SAAO;AACT;;;AC/GA,SAAS,aAAAC,kBAAiB;AAQnB,SAAS,aACd,SACA,SACA,SACA,SACM;AACN,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,QAAQ,eAAe,CAAC,QAAS;AACtC,QAAI;AACJ,QAAI;AACF,mBAAa,eAAe,SAAS,QAAQ,UAAU;AAAA,IACzD,SAAS,GAAQ;AACf,cAAQ,SAAS,iCAA4B,EAAE,OAAO,IAAI,CAAC;AAC3D;AAAA,IACF;AACA,YAAQ,SAAS,sBAAe,UAAU,IAAI,EAAE;AAChD,WAAO,YAAY;AAAA,MACjB;AAAA,MAAY;AAAA,MAAS;AAAA,MACrB,KAAK,SAAO,QAAQ,SAAS,KAAK,IAAI,WAAW,QAAG,IAAI,IAAI,EAAE;AAAA,IAChE,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,aAAa,QAAQ,YAAY,SAAS,SAAS,OAAO,CAAC;AACzE;;;AC7BA,SAAS,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;;;ACkBrC,SAAS,QAAQ,OAA6B;AAEnD,MAAI,MAAM,mBAAmB,KAAK,CAAC,MAAM,MAAM,IAAI,SAAS,GAAG;AAC7D,WAAO,EAAE,IAAI,WAAW,SAAS,mEAAmE;AAAA,EACtG;AACA,MAAI,MAAM,YAAY,OAAQ,CAAC,MAAM,aAAa,CAAC,MAAM,MAAM,IAAI,QAAQ,GAAG;AAC5E,WAAO,EAAE,IAAI,UAAU,SAAS,iCAAiC;AAAA,EACnE;AACA,MAAI,MAAM,YAAY,OAAO,CAAC,MAAM,aAAa,CAAC,MAAM,MAAM,IAAI,QAAQ,GAAG;AAC3E,WAAO,EAAE,IAAI,UAAU,SAAS,yCAAyC;AAAA,EAC3E;AACA,SAAO;AACT;;;AC9BA,SAAgB,aAAAC,YAAW,YAAAC,iBAAgB;AAC3C,SAAS,KAAK,YAAY;AAI1B,OAAO,QAAQ;AA6BT,cASA,YATA;AAfN,IAAM,IAAkD;AAAA,EACtD,IAAI,EAAE,GAAG,UAAK,OAAO,QAAQ;AAAA,EAAG,MAAM,EAAE,GAAG,UAAK,OAAO,SAAS;AAAA,EAChE,MAAM,EAAE,GAAG,UAAK,OAAO,MAAM;AAAA,EAAG,MAAM,EAAE,GAAG,UAAK,OAAO,OAAO;AAChE;AAGO,IAAMC,gBAAe;AAErB,SAAS,cAAc,IAA2B;AACvD,SAAO,GAAG,WAAW,aAAa,GAAG,YAAYA;AACnD;AAEA,SAAS,IAAI,EAAE,MAAM,IAAI,MAAM,IAAI,QAAQ,GAA2F;AACpI,QAAM,SAAS,cAAc,EAAE;AAC/B,QAAM,YAAY,SACd,oBAAC,QAAK,OAAM,OAAM,MAAI,MAAC,oBAAC,IACxB,oBAAC,QAAK,QAAQ,EAAE,GAAG,MAAM,KAAK,EAAE,MAAM,GAAI,OAAS,aAAE,GAAG,MAAM,KAAK,EAAE,MAAM,GAAI,GAAE;AACrF,QAAM,QAAQ,UAAU,GAAG,WAAW,UAAU,MAAM;AACtD,QAAM,KAAK,SAAS,QAAQ,GAAG,WAAW,YAAY,UAAU,GAAG,WAAW,aAAa,WAAW,GAAG,WAAW,SAAS,SAAS;AACtI,QAAM,cAAc,SAAS,YAAY,GAAG;AAC5C,QAAM,KAAK,GAAG,YAAY,UAAU,KAAK,IAAI,IAAI,GAAG,SAAS,IAAI;AAEjE,MAAI,CAAC,SAAS;AACZ,WACE,qBAAC,QACE;AAAA;AAAA,MAAU;AAAA,MAAC,oBAAC,QAAK,OAAe,eAAK,OAAO,EAAE,GAAE;AAAA,MAAO;AAAA,MAAE,OAAO,GAAG,IAAI,IAAI,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAC,oBAAC,QAAK,OAAO,IAAI,MAAM,QAAS,sBAAY,OAAO,CAAC,GAAE;AAAA,MAAO;AAAA,OAAG,MAAM,OAAO,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,OAAG,MAAM,OAAO,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,OAAO,GAAG,MAAM,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,OAAO,GAAG,QAAQ,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,GAAG,SAAS,CAAC;AAAA,OAC7S;AAAA,EAEJ;AAGA,QAAM,eAAe,iBAAiB,GAAG,GAAG,EAAE,KAAK,GAAG;AACtD,QAAM,MAAM,cAAc,GAAG,IAAI,QAAQ;AACzC,QAAM,SAAS,OAAO,QAAQ,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG;AACxE,SACE,qBAAC,OAAI,eAAc,UACjB;AAAA,yBAAC,QACE;AAAA;AAAA,MAAU;AAAA,MAAC,oBAAC,QAAK,OAAe,eAAK,OAAO,EAAE,GAAE;AAAA,MAAO;AAAA,MAAE,OAAO,GAAG,IAAI,IAAI,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAC,oBAAC,QAAK,OAAO,IAAI,MAAM,QAAS,sBAAY,OAAO,CAAC,GAAE;AAAA,MAAO;AAAA,OAAG,MAAM,OAAO,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,OAAG,MAAM,OAAO,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,OAAO,GAAG,MAAM,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,OAAO,GAAG,QAAQ,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAE,GAAG,SAAS,CAAC;AAAA,OAC7S;AAAA,IACA,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,MAAS,GAAG,IAAI;AAAA,MAAI;AAAA,MAAE;AAAA,OAAa;AAAA,IACjD,UAAU,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,MAAS;AAAA,OAAO;AAAA,KAC5C;AAEJ;AAEA,SAAS,UAAU,EAAE,GAAG,GAAmB;AACzC,SAAO,qBAAC,QAAK,MAAI,MAAC;AAAA;AAAA,IAAG,UAAU,OAAO,EAAE;AAAA,IAAE;AAAA,IAAE,OAAO,SAAS,CAAC;AAAA,IAAE;AAAA,IAAE,SAAS,OAAO,CAAC;AAAA,IAAE;AAAA,IAAE,MAAM,SAAS,CAAC;AAAA,IAAE;AAAA,IAAE,MAAM,SAAS,CAAC;AAAA,IAAE;AAAA,IAAU,KAAK,SAAS,CAAC;AAAA,KAAE;AACzJ;AAEO,SAAS,WAAW,EAAE,QAAQ,OAAO,UAAU,YAAY,QAAQ,SAAS,cAAc,aAAa,UAAU,MAAM,GAAU;AACtI,QAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,CAAC;AAC/B,QAAM,QAAQ,OAAO,YAAY,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AACvF,QAAM,WAAW,OAAO,YAAY,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAEtE,QAAM,OAAO,iBAAiB,MAAM,OAAO,OAAK,OAAO,IAAI,CAAC,EAAG,IAAI,SAAS,KAAK,GAAG,UAAU,UAAU,KAAK;AAC7G,QAAM,OAAO,iBAAiB,MAAM,OAAO,OAAK,OAAO,IAAI,CAAC,EAAG,IAAI,SAAS,KAAK,GAAG,UAAU,UAAU,KAAK;AAG7G,QAAMC,QAAO,GAAG,KAAK,EAAE;AACvB,QAAM,WAAW,GAAG,SAAS,IAAI,OAAO,OAAO,MAAM,QAAQ,CAAC;AAC9D,QAAM,UAAU,WAAW,OAAO,IAAI,GAAG,QAAQ,IAAI,OAAO,OAAO,MAAM,QAAQ,CAAC;AAClF,QAAM,OAAO,GAAG,QAAQ,EAAE,CAAC,EAAG,QAAQ,CAAC;AAGvC,MAAI,WAAW,GAAG,aAAa,GAAG,cAAc,GAAG,gBAAgB;AACnE,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,MAAM,IAAI,IAAI;AACxB,QAAI,GAAG;AACL,YAAM,IAAI,WAAW,EAAE,GAAG;AAAG,UAAI,CAAC,MAAM,CAAC,EAAG,aAAY;AACxD,YAAM,IAAI,WAAW,EAAE,GAAG;AAAG,UAAI,CAAC,MAAM,CAAC,EAAG,eAAc;AAAA,IAC5D;AACA,mBAAe,OAAO,IAAI,IAAI,GAAG,UAAU;AAC3C,qBAAiB,OAAO,IAAI,IAAI,GAAG,YAAY;AAAA,EACjD;AACA,QAAM,WAAW,cAAc,QAAQ,aAAa,MAAM,QAAQ,CAAC,IAAI,QAAQ,WAAW,QAAQ,CAAC,IAAI;AAEvG,QAAM,KAAK;AACX,QAAM,gBAAgB,KAAK,IAAI,GAAG,SAAS,CAAC;AAC5C,QAAM,aAAa,KAAK,IAAI,GAAG,gBAAgB,CAAC;AAGhD,QAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,KAAK,MAAM,IAAI,UAAU;AAC3E,QAAM,kBAAkB,iBAAiB,OAAO,mBAC5C,UACA,KAAK,IAAI,cAAc,OAAO;AAClC,QAAM,gBAAgB,KAAK,IAAI,iBAAiB,KAAK,IAAI,GAAG,KAAK,SAAS,UAAU,CAAC;AACrF,QAAM,gBAAgB,KAAK,IAAI,iBAAiB,KAAK,IAAI,GAAG,KAAK,SAAS,UAAU,CAAC;AAErF,QAAM,cAAc,KAAK,MAAM,eAAe,gBAAgB,UAAU;AACxE,QAAM,cAAc,KAAK,MAAM,eAAe,gBAAgB,UAAU;AAGxE,EAAAC,WAAU,MAAM;AACd,gBAAY;AAAA,EACd,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,QAAM,gBAAgB,KAAK,IAAI,KAAK,QAAQ,KAAK,MAAM;AACvD,QAAM,eAAe,WAAW,gBAAgB,IAC5C,IAAI,kBAAkB,CAAC,IAAI,KAAK,IAAI,kBAAkB,YAAY,aAAa,CAAC,IAAI,aAAa,MACjG;AACJ,QAAM,WAAW,kBAAkB;AACnC,QAAM,cAAc,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,OAAO,aAAa,EAAE;AAG/D,QAAM,SAAU,WAAW,MAAM,IAAI,WAAW,OAAO,IAAK;AAC5D,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAS,KAAK;AAChD,EAAAD,WAAU,MAAM;AACd,iBAAa,UAAQ,wBAAwB,QAAQ,IAAI,CAAC;AAAA,EAC5D,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,eAAe,YACjB,CAAC,GAAG,MAAM,QAAQ,CAAC,EAChB,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,EACzD,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE,EAC1B,MAAM,GAAG,CAAC,IACb,CAAC;AAEL,SACE,qBAAC,OAAI,eAAc,UAAS,aAAY,SAAQ,aAAa,UAAU,UAAU,QAAQ,QACvF;AAAA,yBAAC,OACC;AAAA,2BAAC,QAAK,MAAI,MAAC,OAAM,SAAQ;AAAA;AAAA,QAAQ;AAAA,SAAa;AAAA,MAC7C,YAAY,oBAAC,QAAK,OAAM,UAAS,uBAAS;AAAA,MAC1C,cAAc,KAAK,qBAAC,QAAK,OAAM,OAAM,MAAI,MAAC;AAAA;AAAA,QAAI;AAAA,QAAY;AAAA,SAAe;AAAA,MAC1E,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAUD;AAAA,QAAK;AAAA,QAAQ;AAAA,QAAK;AAAA,QAAM;AAAA,QAAO;AAAA,QAAE;AAAA,QAAQ;AAAA,SAAE;AAAA,MACpE,oBAAC,QAAK,UAAQ,MAAC,sBAAG;AAAA,MAClB,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAY,SAAS,QAAQ,CAAC;AAAA,QAAE;AAAA,QAAO;AAAA,QAAS;AAAA,QAAM;AAAA,QAAY;AAAA,QAAM;AAAA,QAAc;AAAA,QAAO,MAAM;AAAA,SAAO;AAAA,MACxH,aAAa,UAAU,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAU;AAAA,SAAS;AAAA,OAC5D;AAAA,IACC,aACC,qBAAC,OACC;AAAA,2BAAC,QAAK,OAAM,UAAS,MAAI,MAAC;AAAA;AAAA,QAAQ,OAAO,QAAQ,CAAC;AAAA,QAAE;AAAA,SAAS;AAAA,MAC7D,oBAAC,QAAK,OAAM,UAAU,uBAAa,IAAI,OAAK,GAAG,EAAE,IAAI,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,GAAE;AAAA,OAC3F;AAAA,IAEF,qBAAC,OAAI,UAAU,GAEb;AAAA,2BAAC,OAAI,eAAc,UAAS,UAAU,GAAG,WAAW,GAClD;AAAA,6BAAC,QAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,UAAQ,KAAK;AAAA,UAAO;AAAA,WAAC;AAAA,QAC7C,oBAAC,aAAU,IAAQ;AAAA,QAClB,YAAY,IAAI,OACf,oBAAC,OAAY,MAAM,GAAG,IAAI,OAAO,IAAI,CAAC,GAAI,MAAM,MAAM,IAAI,CAAC,GAAG,IAAQ,WAA5D,CAA8E,CACzF;AAAA,SACH;AAAA,MAEA,oBAAC,OAAI,eAAc,UAAS,OAAO,GAChC,gBAAM,KAAK,EAAE,QAAQ,cAAc,GAAG,CAAC,GAAG,MAAM,oBAAC,QAAa,UAAQ,MAAC,sBAAZ,CAAa,CAAO,GAClF;AAAA,MAEA,qBAAC,OAAI,eAAc,UAAS,UAAU,GAAG,WAAW,GAClD;AAAA,6BAAC,QAAK,MAAI,MAAC,OAAM,WAAU;AAAA;AAAA,UAAQ,KAAK;AAAA,UAAO;AAAA,WAAC;AAAA,QAChD,oBAAC,aAAU,IAAQ;AAAA,QAClB,YAAY,IAAI,OACf,oBAAC,OAAY,MAAM,GAAG,IAAI,OAAO,IAAI,CAAC,GAAI,MAAM,MAAM,IAAI,CAAC,GAAG,IAAQ,WAA5D,CAA8E,CACzF;AAAA,SACH;AAAA,OACF;AAAA,KACF;AAEJ;;;AF1KO,SAAS,kBACd,WACA,WACA,WACA,QACe;AACf,QAAM,YAAYG,QAAoB,oBAAI,IAAI,CAAC;AAC/C,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAwB,IAAI;AAE9D,EAAAC,WAAU,MAAM;AACd,UAAM,MAAM,QAAQ;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,OAAO,aAAa,EAAE;AAAA,MAC7D,OAAO,UAAU;AAAA,IACnB,CAAC;AACD,QAAI,OAAO,IAAI,YAAY,WAAW;AACpC,gBAAU,QAAQ,IAAI,IAAI,EAAE;AAC5B,mBAAa,IAAI,OAAO;AACxB,YAAM,QAAQ,WAAW,MAAM,aAAa,IAAI,GAAG,IAAM;AACzD,aAAO,MAAM,aAAa,KAAK;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,WAAW,QAAQ,WAAW,WAAW,SAAS,CAAC;AAEvD,SAAO;AACT;;;AGlCA,SAAS,aAAAC,YAAW,YAAAC,iBAAgB;AAwB7B,SAAS,gBACd,SACA,QACA,UACA,SACA,UACA,KACA,SACA,MACA,SACM;AACN,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAE1C,EAAAC,WAAU,MAAM;AACd,QAAI,UAAU,CAAC,QAAS;AACxB,cAAU,IAAI;AACd,UAAM,MAAM;AAEZ,KAAC,YAAY;AACX,YAAM,WAAW,QAAQ;AACzB,YAAM,cAAc,QAAQ;AAG5B,UAAI,OAAO,UAAU,QAAQ;AAC3B,cAAM,SAAS,MAAM,eAAe,OAAO,UAAU;AAAA,UACnD;AAAA,UAAS;AAAA,UAAK;AAAA,UACd,OAAO,CAAC,KAAK,QAAQ,QAAQ,OAAO,GAAG,IAAI,KAAK,EAAE;AAAA,QACpD,CAAC;AACD,aAAK,UAAU,UAAU,OAAO;AAChC,YAAI,CAAC,OAAO,YAAY;AACtB,kBAAQ,SAAS,8BAAyB,OAAO,OAAO,KAAK,IAAI,CAAC,oBAAoB,CAAC;AACvF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,YAAY,OAAO,MAAM;AAE3B,cAAM,EAAE,UAAU,KAAK,IAAI,iBAAiB,UAAU,OAAO,IAAI;AAGjE,cAAM,WAAW,aAAa,QAAQ;AACtC,YAAI,WAAW;AACf,mBAAW,OAAO,OAAO,KAAK,QAAQ,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG;AACzE,gBAAM,OAAO,SAAS,GAAG;AACzB,qBAAW,OAAO,MAAM;AACtB,kBAAM,KAAK;AACX,kBAAM,IAAI,QAAQ,KAAK,EAAE;AACzB,kBAAM,IAAI,MAAM,KAAK,EAAE;AAAA,UACzB;AACA,gBAAM,OAAO,KAAK,OAAO,OAAK,EAAE,SAAS,KAAK;AAC9C,cAAI,KAAK,OAAQ,OAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,YAAY,EAAE,MAAM,EAAE,SAAS,KAAM,CAAC,CAAC,CAAC;AACzF,eAAK,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,OAAK;AAC9C,kBAAM,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI;AAC/B,gBAAI,GAAI,IAAG,SAAS;AAAA,UACtB,CAAC;AAAA,QACH;AAGA,mBAAW,OAAO,MAAM;AACtB,gBAAM,KAAK;AACX,gBAAM,YAAY,mBAAmB,GAAG;AAGxC,gBAAM,YAA0B;AAAA,YAC9B,KAAK;AAAA,YAAW,MAAM;AAAA,YAAM,KAAK;AAAA,YACjC,QAAQ;AAAA,YAAQ,QAAQ;AAAA,YACxB,QAAQ;AAAA,YAAG,UAAU;AAAA,YAAG,WAAW;AAAA,YACnC,iBAAiB;AAAA,YAAO,UAAU;AAAA,UACpC;AACA,cAAI,MAAM,IAAI,IAAI,MAAM,SAAS;AAEjC,gBAAM,QAAQ,gBAAgB;AAAA,YAC5B,YAAY,IAAI;AAAA,YAChB,YAAY,UAAU;AAAA,YACtB,YAAY;AAAA,YACZ,eAAe,YAAY;AACzB,oBAAM,IAAI,QAAQ,WAAW,EAAE;AAC/B,oBAAM,IAAI,MAAM,WAAW,EAAE;AAC7B,oBAAM,KAAK,MAAM,YAAY,UAAU,UAAU,EAAE,SAAS,KAAM,CAAC;AACnE,oBAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,kBAAI,IAAI;AACN,mBAAG,SAAS,KAAK,YAAY;AAC7B,oBAAI,GAAI,IAAG,SAAS;AAAA,cACtB;AAAA,YACF;AAAA,YACA,YAAY,MAAM;AAChB,kBAAI,KAAK,IAAI,IAAI;AACjB,oBAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,kBAAI,IAAI;AAAE,mBAAG,SAAS;AAAQ,mBAAG,SAAS;AAAQ,mBAAG,MAAM;AAAM,mBAAG,OAAO;AAAM,mBAAG,YAAY;AAAA,cAAM;AAAA,YACxG;AAAA,YACA,SAAS,MAAM;AACb,oBAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,qBAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,KAAK,UAAU,GAAG,WAAW;AAAA,YAC/D;AAAA,UACF,CAAC;AAED,eAAK,YAAY,QAAS,IAAI,IAAI,MAAM,KAAK;AAAA,QAC/C;AAAA,MACF,OAAO;AAEL,cAAM,SAAS,aAAa,QAAQ;AACpC,YAAI,WAAW;AACf,mBAAW,OAAO,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG;AACvE,gBAAM,OAAO,OAAO,GAAG;AACvB,qBAAW,OAAO,MAAM;AACtB,kBAAM,KAAK;AACX,kBAAM,IAAI,QAAQ,KAAK,EAAE;AACzB,kBAAM,IAAI,MAAM,KAAK,EAAE;AAAA,UACzB;AACA,gBAAM,OAAO,KAAK,OAAO,OAAK,EAAE,SAAS,KAAK;AAC9C,cAAI,KAAK,OAAQ,OAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,YAAY,EAAE,MAAM,EAAE,SAAS,KAAM,CAAC,CAAC,CAAC;AACzF,eAAK,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,QAAQ,OAAK;AAC9C,kBAAM,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI;AAC/B,gBAAI,GAAI,IAAG,SAAS;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,GAAG;AAAA,EACL,GAAG,CAAC,QAAQ,SAAS,UAAU,SAAS,OAAO,MAAM,OAAO,UAAU,SAAS,KAAK,UAAU,MAAM,OAAO,CAAC;AAC9G;;;AC/IA,SAAgB,aAAAC,aAAW,eAAe;AAC1C,SAAS,OAAAC,MAAK,QAAAC,aAAY;AA0EpB,gBAAAC,MAAK,QAAAC,aAAL;AAlEC,SAAS,cAAc,SAAkB,QAAuB,kBAAyC;AAC9G,MAAI,QAAS,QAAO;AACpB,MAAI,UAAU,qBAAqB,QAAQ,oBAAoB,GAAG;AAChE,WAAO,UAAU,mBAAmB,UAAU,MAAM;AAAA,EACtD;AACA,SAAO;AACT;AAmBO,SAAS,UAAU,EAAE,MAAM,QAAQ,YAAY,QAAQ,gBAAgB,YAAY,QAAQ,SAAS,cAAc,aAAa,cAAc,OAAO,mBAAmB,KAAK,GAAU;AAC3L,QAAM,YAAY,SAAS,KAAK,OAAO,OAAK,EAAE,YAAY,MAAM,IAAI;AACpE,QAAM,WAAW,gBAAgB,QAC7B,YACA,gBAAgB,UACd,UAAU,OAAO,OAAK,EAAE,UAAU,OAAO,IACzC,UAAU,OAAO,OAAK,EAAE,UAAU,WAAW,EAAE,UAAU,MAAM;AACrE,QAAM,gBAAgB,KAAK,IAAI,GAAG,SAAS,CAAC;AAC5C,QAAM,aAAa,SAAS;AAG5B,QAAM,YAAY,KAAK,IAAI,GAAG,aAAa,aAAa;AACxD,QAAM,kBAAkB,iBAAiB,OAAO,mBAC5C,YACA,KAAK,IAAI,cAAc,SAAS;AACpC,QAAM,aAAa,KAAK,IAAI,GAAG,aAAa,gBAAgB,eAAe;AAC3E,QAAM,WAAW,KAAK,IAAI,aAAa,eAAe,UAAU;AAChE,QAAM,UAAU,SAAS,MAAM,YAAY,QAAQ;AAGnD,EAAAC,YAAU,MAAM;AACd,gBAAY;AAAA,EACd,GAAG,CAAC,QAAQ,YAAY,WAAW,CAAC;AAEpC,QAAM,UAAU,QAAQ,MAAM,qBAAqB,UAAU,GAAG,CAAC,UAAU,CAAC;AAE5E,QAAM,WAAW,kBAAkB;AACnC,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,SAAS,IAAI,MAAM,MAAM;AAAA,IACzB,aAAa,IAAI,UAAU,KAAK;AAAA,IAChC,SAAS,UAAU,oBAAoB;AAAA,IACvC,gBAAgB,QAAQ,WAAW,WAAW,GAAG,gBAAgB,SAAS,WAAW,EAAE,MAAM;AAAA,IAC7F,SAAS,aAAa;AAAA,IACtB,WAAW,aAAa;AAAA,IACxB,GAAG,SAAS,MAAM;AAAA,IAClB,WAAW,aAAa,IAAI,IAAI,aAAa,CAAC,IAAI,QAAQ,IAAI,UAAU,MAAM;AAAA,EAChF,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAE1B,SACE,gBAAAD,MAACE,MAAA,EAAI,eAAc,UAAS,aAAY,SAAQ,aAAa,cAAc,SAAS,QAAQ,gBAAgB,GAAG,QAC7G;AAAA,oBAAAH,KAACG,MAAA,EAAI,0BAAAF,MAACG,OAAA,EAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,MAAE;AAAA,MAAM;AAAA,OAAC,GAAO;AAAA,IAC5C,QAAQ,IAAI,CAAC,OAAO,MAAM;AACzB,YAAM,QAAQ,UAAU,MAAM,WAAW,UAAU,MAAM;AACzD,YAAM,KAAK,iBAAiB,IAAI,KAAK,MAAM,EAAE,EAAE,mBAAmB,OAAO,IAAI,MAAM;AACnF,YAAM,OAAO,MAAM;AACnB,YAAM,UAAU,UAAU,QAAQ,KAAK,IAAI,IAAI;AAC/C,aACE,gBAAAH,MAACE,MAAA,EACE;AAAA,0BAAkB,gBAAAH,KAACI,OAAA,EAAK,UAAQ,MAAE,cAAG;AAAA,QACtC,gBAAAH,MAACG,OAAA,EAAK,OAAc;AAAA;AAAA,UAAE,MAAM,QAAQ,OAAO,UAAU;AAAA,UAAE;AAAA,WAAC;AAAA,QACxD,gBAAAJ,KAACI,OAAA,EAAK,eAAC;AAAA,QACN,UAAU,gBAAAJ,KAACI,OAAA,EAAK,iBAAgB,UAAS,OAAM,SAAS,gBAAK,IAAU,gBAAAJ,KAACI,OAAA,EAAM,gBAAK;AAAA,WAJ5E,CAKV;AAAA,IAEJ,CAAC;AAAA,KACH;AAEJ;;;AC3FA,SAAS,OAAAC,MAAK,QAAAC,aAAY;AAKpB,SACE,OAAAC,MADF,QAAAC,aAAA;AAHC,SAAS,YAAY;AAC1B,SACE,gBAAAD,KAACF,MAAA,EACC,0BAAAG,MAACF,OAAA,EACC;AAAA,oBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,iBAAG;AAAA,IAAO;AAAA,IAAS,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,0BAAE;AAAA,IAAO;AAAA,IAAS,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,uBAAS;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,sBAAQ;AAAA,IAAO;AAAA,IAAW,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAQ,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAS,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAQ,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAM,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAU,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAS,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAQ,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAO,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,IAAU,gBAAAC,KAACD,OAAA,EAAK,MAAI,MAAC,eAAC;AAAA,IAAO;AAAA,KAC3d,GACF;AAEJ;;;ACXA,SAAgB,YAAAG,WAAU,WAAAC,gBAAe;AACzC,SAAS,OAAAC,MAAK,QAAAC,OAAM,YAAAC,iBAAgB;AAiDa,SAEzC,OAAAC,MAFyC,QAAAC,aAAA;AAtC1C,SAAS,YAAY,EAAE,OAAO,UAAU,UAAU,SAAS,WAAW,GAAU;AACrF,QAAM,WAAWL;AAAA,IACf,MAAM,CAAC,GAAG,SAAS,KAAK,CAAC,EAAE,OAAO,OAAK,CAAC,cAAc,SAAS,IAAI,CAAC,EAAG,IAAI,SAAS,UAAU;AAAA,IAC9F,CAAC,UAAU,UAAU;AAAA,EACvB;AACA,QAAM,CAAC,KAAK,MAAM,IAAID,UAAS,CAAC;AAChC,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,EAAE;AAErC,QAAM,QAAQC,SAAQ,MAAM;AAC1B,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,IAAI,MAAM,YAAY;AAC5B,WAAO,SAAS,OAAO,OAAK,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AAAA,EACzD,GAAG,CAAC,UAAU,KAAK,CAAC;AAGpB,QAAM,UAAU,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,MAAM,SAAS,CAAC,CAAC;AAE3D,EAAAG,UAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,UAAI,MAAO,UAAS,EAAE;AAAA,UACjB,SAAQ;AACb;AAAA,IACF;AACA,QAAI,IAAI,QAAQ;AACd,UAAI,MAAM,OAAO,EAAG,UAAS,MAAM,OAAO,CAAE;AAC5C;AAAA,IACF;AACA,QAAI,IAAI,SAAS;AAAE,aAAO,OAAK,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AAAG;AAAA,IAAQ;AAC5D,QAAI,IAAI,WAAW;AAAE,aAAO,OAAK,KAAK,IAAI,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC;AAAG;AAAA,IAAQ;AAC7E,QAAI,IAAI,aAAa,IAAI,QAAQ;AAAE,eAAS,OAAK,EAAE,MAAM,GAAG,EAAE,CAAC;AAAG,aAAO,CAAC;AAAG;AAAA,IAAQ;AACrF,QAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,QAAQ,MAAM,WAAW,GAAG;AACzD,eAAS,OAAK,IAAI,KAAK;AACvB,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,EAAE,UAAU,QAAQ,MAAM,SAAS,MAAM,CAAC;AAE7C,SACE,gBAAAE,MAACJ,MAAA,EAAI,eAAc,UAAS,aAAY,SAAQ,aAAY,QAAO,UAAU,GAC3E;AAAA,oBAAAI,MAACH,OAAA,EAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,MAAE;AAAA,MAAM;AAAA,MAAE,SAAS,gBAAAG,MAACH,OAAA,EAAK,OAAM,UAAS;AAAA;AAAA,QAAE;AAAA,QAAM;AAAA,SAAC;AAAA,OAAQ;AAAA,IAChF,MAAM,WAAW,IAChB,gBAAAE,KAACF,OAAA,EAAK,UAAQ,MAAC,4BAAc,IAE7B,MAAM,IAAI,CAAC,MAAM,MACf,gBAAAE,KAACH,MAAA,EACC,0BAAAI,MAACH,OAAA,EAAK,OAAO,MAAM,UAAU,SAAS,QAAW,SAAS,MAAM,SAAS;AAAA;AAAA,MAAE;AAAA,MAAK;AAAA,MAAG,SAAS,IAAI,IAAI,EAAG,IAAI;AAAA,MAAK;AAAA,OAAC,KADzG,IAEV,CACD;AAAA,IAEH,gBAAAE,KAACF,OAAA,EAAK,UAAQ,MAAC,kFAA0D;AAAA,KAC3E;AAEJ;;;AC/DA,SAAgB,YAAAI,iBAAgB;AAChC,SAAS,OAAAC,MAAK,QAAAC,OAAM,YAAAC,iBAAgB;AAkBhC,SACE,OAAAC,MADF,QAAAC,aAAA;AAXG,SAAS,YAAY,EAAE,UAAU,QAAQ,GAAU;AACxD,QAAM,CAAC,OAAO,QAAQ,IAAIL,UAAS,EAAE;AAErC,EAAAG,UAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,OAAQ,SAAQ;AAAA,aACf,IAAI,OAAQ,UAAS,MAAM,KAAK,KAAK,IAAI;AAAA,aACzC,IAAI,aAAa,IAAI,OAAQ,UAAS,OAAK,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,aACzD,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAM,UAAS,OAAK,IAAI,KAAK;AAAA,EACnE,GAAG,EAAE,UAAU,QAAQ,MAAM,SAAS,MAAM,CAAC;AAE7C,SACE,gBAAAE,MAACJ,MAAA,EAAI,aAAY,SAAQ,aAAY,UAAS,UAAU,GACtD;AAAA,oBAAAG,KAACF,OAAA,EAAK,MAAI,MAAC,OAAM,UAAS,sBAAQ;AAAA,IAClC,gBAAAE,KAACF,OAAA,EAAM,iBAAM;AAAA,IACb,gBAAAE,KAACF,OAAA,EAAK,UAAQ,MAAC,oBAAC;AAAA,KAClB;AAEJ;;;AfyFQ,SAIF,OAAAI,MAJE,QAAAC,aAAA;AAvFD,SAAS,gBACd,MACA,MACA,aACA,WACQ;AACR,MAAI,eAAe,WAAW;AAC5B,UAAM,MAAM,UAAU,OAAO,IAAI;AACjC,QAAI,QAAQ,QAAW;AACrB,YAAM,OAAO,MAAM,GAAG,GAAG,IAAI,UAAU,MAAM,KAAK,UAAU;AAC5D,YAAM,SAAS,UAAU,MAAM,UAAU;AACzC,aAAO,GAAG,MAAM,MAAM,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,SAAO,oBAAoB,IAAI;AACjC;AAcO,SAAS,IAAI,EAAE,QAAQ,UAAU,SAAS,UAAU,KAAK,SAAS,eAAe,WAAW,QAAQ,GAAU;AACnH,QAAM,OAAO,gBAAgB;AAC7B,QAAM,aAAa,KAAK,MAAM,OAAO,IAAI;AACzC,QAAM,cAAc,OAAO,aAAa;AACxC,QAAM,aAAa,KAAK,IAAI,GAAG,SAAS,IAAI,OAAK,EAAE,KAAK,MAAM,GAAG,EAAE;AAEnE,QAAM,KAAK,kBAAkB,UAAU,SAAS,KAAK,OAAO;AAC5D,QAAM,cAAcC,QAA+B,oBAAI,IAAI,CAAC;AAC5D,QAAM,YAAYA,QAAuB,CAAC,CAAC;AAE3C,QAAM,KAAK,eAAe;AAAA,IACxB,QAAQ,MAAM;AAAE,WAAK,SAAS;AAAA,IAAG;AAAA,IACjC,aAAa,GAAG;AAAA,IAChB,eAAe,MAAM;AAAA,IAAC;AAAA,EACxB,CAAC;AAED,QAAM,WAAW,iBAAiB,YAAY,EAAE,UAAU,eAAe,MAAM,UAAU,IAAI;AAC7F,QAAM,eAAe,gBAAgB,GAAG,SAAS,OAAO,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,UAAU,UAAU,OAAO,YAAY,CAAC,CAAC;AAEpJ,QAAM,WAAWC,aAAY,YAAY;AACvC,gBAAY,QAAQ,QAAQ,OAAK,EAAE,QAAQ,CAAC;AAC5C,UAAM,aAAa,SAAS,MAAM;AAClC,UAAM,GAAG,QAAQ;AACjB,QAAI,UAAU,QAAQ,QAAQ;AAC5B,YAAM,cAAc,UAAU,SAAS,UAAU;AAAA,QAC/C;AAAA,QAAS;AAAA,QACT,OAAO,CAAC,KAAK,QAAQ,GAAG,QAAQ,OAAO,GAAG,IAAI,KAAK,EAAE;AAAA,MACvD,CAAC;AACD,gBAAU,UAAU,CAAC;AAAA,IACvB;AACA,UAAM,SAAS,MAAM;AACrB,YAAQ,KAAK,CAAC;AAAA,EAChB,GAAG,CAAC,IAAI,SAAS,UAAU,SAAS,KAAK,YAAY,CAAC;AAEtD,eAAa,GAAG,SAAS,SAAS,SAAS,GAAG,OAAO;AACrD,eAAa,GAAG,WAAW,GAAG,YAAY,GAAG,gBAAgB;AAC7D,QAAM,YAAY,kBAAkB,GAAG,KAAK,QAAQ,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,GAAG,WAAW,GAAG,MAAM;AAC9F,eAAa,eAAe,WAAW,GAAG,QAAQ,GAAG,YAAY;AACjE;AAAA,IAAgB,GAAG;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAU;AAAA,IAAS;AAAA,IAAU;AAAA,IAAK;AAAA,IACpE,EAAE,aAAa,UAAU;AAAA,IAAG,GAAG;AAAA,EAAO;AAExC,QAAM,qBAAqBA,aAAY,CAAC,SAAiB,GAAG,UAAU,IAAI,GAAG,CAAC,EAAE,CAAC;AACjF,QAAM,sBAAsBA,aAAY,CAAC,SAAiB;AAAE,OAAG,QAAQ,IAAI;AAAG,OAAG,SAAS,MAAM;AAAA,EAAG,GAAG,CAAC,IAAI,EAAE,CAAC;AAC9G,QAAM,mBAAmBA,aAAY,CAAC,SAAiB;AACrD,UAAM,KAAK,GAAG,OAAO,IAAI,IAAI;AAC7B,QAAI,IAAI;AACN,YAAM,MAAM,gBAAgB,MAAM,GAAG,IAAI,MAAM,QAAQ,OAAO,SAAS;AACvE,eAAS,YAAY,GAAG;AAAA,IAC1B;AACA,OAAG,SAAS,MAAM;AAAA,EACpB,GAAG,CAAC,IAAI,UAAU,IAAI,QAAQ,OAAO,SAAS,CAAC;AAE/C,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,YAAY,QAAQ,QAAQ,OAAO,OAAO,SAAS;AAEzD,SACE,gBAAAF,MAACG,MAAA,EAAI,eAAc,UAAS,QAAQ,MAClC;AAAA,oBAAAH,MAACG,MAAA,EACC;AAAA,sBAAAH,MAACI,OAAA,EAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,QAAE;AAAA,QAAK;AAAA,QAAE,OAAO;AAAA,QAAK;AAAA,QAAY,SAAS;AAAA,QAAO;AAAA,QAAY;AAAA,QAAU;AAAA,SAAE;AAAA,MAChG,aAAa,gBAAAJ,MAACI,OAAA,EAAK,UAAQ,MAAC;AAAA;AAAA,QAAI;AAAA,SAAU;AAAA,OAC7C;AAAA,IAEA,gBAAAL;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,GAAG;AAAA,QAAM,QAAQ,GAAG;AAAA,QAAW,YAAY,GAAG;AAAA,QACpD,QAAQ,GAAG;AAAA,QAAY,gBAAgB,GAAG;AAAA,QAC1C;AAAA,QAAwB,QAAQ;AAAA,QAAY,SAAS,GAAG,UAAU;AAAA,QAClE,cAAc,GAAG;AAAA,QAAkB,aAAa,GAAG;AAAA,QACnD,aAAa,GAAG;AAAA,QAChB,kBAAkB,GAAG,YAAa,GAAG,OAAO,IAAI,GAAG,SAAS,GAAG,YAAY,OAAQ;AAAA;AAAA,IACrF;AAAA,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ,GAAG;AAAA,QAAQ,OAAO,GAAG;AAAA,QAAO,UAAU,GAAG;AAAA,QACjD;AAAA,QAAwB,QAAQ;AAAA,QAAa,SAAS,GAAG,UAAU;AAAA,QACnE,cAAc,GAAG;AAAA,QAAmB,aAAa,GAAG;AAAA,QACpD,SAAS,GAAG;AAAA;AAAA,IACd;AAAA,IAEC,GAAG,UAAU,YACZ,gBAAAA,KAAC,eAAY,OAAM,qBAAoB,UAAU,GAAG,QAAQ,UAAU,oBAAoB,SAAS,MAAM,GAAG,SAAS,MAAM,GAAG;AAAA,IAE/H,GAAG,UAAU,aACZ,gBAAAA,KAAC,eAAY,OAAM,mBAAkB,UAAU,GAAG,QAAQ,UAAU,qBAAqB,SAAS,MAAM,GAAG,SAAS,MAAM,GAAG;AAAA,IAE9H,GAAG,UAAU,UACZ,gBAAAA,KAAC,eAAY,OAAM,mBAAkB,UAAU,GAAG,QAAQ,UAAU,kBAAkB,SAAS,MAAM,GAAG,SAAS,MAAM,GAAG,YAAW,OAAM;AAAA,IAE5I,GAAG,UAAU,YACZ,gBAAAA,KAAC,eAAY,UAAU,GAAG,WAAW,SAAS,MAAM,GAAG,SAAS,MAAM,GAAG;AAAA,IAG3E,gBAAAA,KAAC,aAAU;AAAA,KACb;AAEJ;;;AgBrIO,SAAS,aAAa,MAA0B;AACrD,QAAM,EAAE,QAAQ,UAAU,SAAS,KAAK,eAAe,UAAU,IAAI;AACrE,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,aAAa,OAAO,QAAQ,WAAI,IAAI,OAAO,IAAI,EAAE;AAC5D,QAAM,KAAK,aAAa,QAAQ,QAAQ,OAAO,OAAO,SAAS,QAAQ,EAAE;AACzE,MAAI,QAAQ,QAAS,OAAM,KAAK,aAAa,QAAQ,OAAO,EAAE;AAC9D,QAAM,KAAK,aAAa,SAAS,MAAM,EAAE;AACzC,QAAM,KAAK,EAAE;AAEb,MAAI,OAAO,UAAU,QAAQ;AAC3B,UAAM,KAAK,cAAc,OAAO,SAAS,MAAM,IAAI;AACnD,eAAW,OAAO,OAAO,UAAU;AACjC,YAAM,KAAK,IAAI;AACf,YAAM,QAAQ,KACV,WAAW,GAAG,IAAI,GAAG,GAAG,SAAS,SAAS,OAAO,GAAG,QAAQ,OAAO,EAAE,KAAK,IAAI,QAAQ,GAAG,KACzF;AACJ,YAAM,KAAK,OAAO,IAAI,KAAK,OAAO,EAAE,CAAC,IAAI,IAAI,GAAG,GAAG,KAAK,EAAE;AAAA,IAC5D;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,WAAW,QAAQ,QAAQ,CAAC,CAAC,OAAO;AAC1C,MAAI,WAA4B;AAChC,MAAI,OAAwB,CAAC;AAC7B,MAAI,UAAU;AACZ,UAAM,IAAI,iBAAiB,UAAU,OAAO,IAAK;AACjD,eAAW,EAAE;AACb,WAAO,EAAE;AAAA,EACX;AAEA,QAAM,SAAS,aAAa,QAAQ;AACpC,QAAM,YAAY,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACtE,aAAW,OAAO,WAAW;AAC3B,UAAM,KAAK,SAAS,GAAG,GAAG;AAC1B,eAAW,OAAO,OAAO,GAAG,GAAI;AAC9B,YAAM,KAAK,cAAc,KAAK,KAAK,KAAK,CAAC;AAAA,IAC3C;AAAA,EACF;AAEA,MAAI,KAAK,QAAQ;AACf,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,mBAAmB;AAC9B,eAAW,OAAO,MAAM;AACtB,YAAM,YAAY,mBAAmB,GAAG;AACxC,YAAM,KAAK,cAAc,WAAW,KAAK,IAAI,CAAC;AAC9C,YAAM,KAAK,gBAAgB,IAAI,IAAI,YAAO,gBAAgB,IAAI,IAAI,CAAC,kBAAkB,QAAQ,WAAW,IAAI;AAAA,IAC9G;AAAA,EACF;AAEA,MAAI,iBAAiB,WAAW;AAC9B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,aAAa,cAAc,IAAI,WAAM,UAAU,QAAQ,EAAE;AAEpE,UAAM,YAAY,oBAAI,IAA0B;AAChD,eAAW,OAAO,UAAU;AAC1B,YAAM,OAAO,YAAY,CAAC,SAAS,SAAS,GAAG,IAAI,gBAAgB,IAAI,IAAI,IAAI;AAC/E,gBAAU,IAAI,IAAI,MAAM,EAAE,MAAM,IAAI,MAAM,QAAQ,MAAM,UAAU,KAAK,CAAC;AAAA,IAC1E;AACA,UAAM,UAAU,cAAc,SAAS,WAAW,SAAS;AAC3D,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,0BAA0B;AACrC,UAAM,KAAK,OAAO;AAAA,EACpB;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,cAAc,KAAoB,KAA6B,QAAyB;AAC/F,QAAM,OAAO,iBAAiB,GAAG;AACjC,QAAM,UAAU,CAAC,IAAI,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;AAC3C,QAAM,QAAQ,gBAAgB,KAAK,GAAG;AACtC,QAAM,WAAW,OAAO,KAAK,IAAI,YAAY,CAAC,CAAC,EAAE,SAC7C,WAAW,OAAO,QAAQ,IAAI,QAAS,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,IAC9E;AACJ,QAAM,SAAS,IAAI,SAAS,QAAQ,IAAI,MAAM,OAAO;AACrD,QAAM,KAAK,IAAI;AACf,QAAM,QAAQ,IAAI,SAAS,SAAS,gBAAgB,GAAG,QAAQ,GAAG,KAAK;AACvE,QAAM,UAAU,SAAS,YAAY;AACrC,OAAK;AACL,SAAO,OAAO,IAAI,KAAK,OAAO,EAAE,CAAC,KAAK,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ;AAChH;AAEO,SAAS,UAAU,MAAwB;AAEhD,UAAQ,IAAI,aAAa,IAAI,CAAC;AAChC;;;AChFA,eAAsB,QAAQ,MAAiC;AAC7D,QAAM,MAAM,KAAK,QAAQ,CAAC,MAAc,QAAQ,IAAI,CAAC;AACrD,QAAM,EAAE,QAAQ,UAAU,SAAS,UAAU,KAAK,SAAS,QAAQ,IAAI;AAEvE,QAAM,MAAM,IAAI,eAAe;AAAA,IAC7B;AAAA,IAAS;AAAA,IAAK;AAAA,IACd,QAAQ;AAAA,MACN,OAAO,CAAC,KAAK,SAAS;AAAE,iBAAS,MAAM,KAAK,IAAI;AAAG,YAAI,IAAI,GAAG,KAAK,IAAI,EAAE;AAAA,MAAG;AAAA,MAC5E,eAAe,MAAM;AAAA,MAAC;AAAA,IACxB;AAAA,EACF,CAAC;AAGD,MAAI,YAA4B,CAAC;AACjC,MAAI,OAAO,UAAU,QAAQ;AAC3B,QAAI,qBAAgB,OAAO,SAAS,MAAM,GAAG;AAC7C,UAAM,SAAS,MAAM,eAAe,OAAO,UAAU;AAAA,MACnD;AAAA,MAAS;AAAA,MAAK;AAAA,MACd,OAAO,CAAC,KAAK,QAAQ;AAAE,iBAAS,MAAM,OAAO,GAAG,IAAI,GAAG;AAAG,YAAI,QAAQ,GAAG,KAAK,GAAG,EAAE;AAAA,MAAG;AAAA,IACxF,CAAC;AACD,gBAAY,OAAO;AACnB,QAAI,CAAC,OAAO,YAAY;AACtB,UAAI,4BAAuB,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AACrD,YAAM,cAAc,WAAW,UAAU,EAAE,SAAS,IAAI,CAAC;AACzD,YAAM,IAAI,QAAQ;AAClB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,SAAS,aAAa,QAAQ;AACpC,QAAM,YAAY,OAAO,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACtE,QAAM,WAAW,SAAS,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,IAAI,OAAK,EAAE,IAAI;AACvE,QAAM,WAAW,KAAK,IAAI,IAAI,QAAQ,cAAc;AACpD,MAAI,WAAW;AAEf,aAAW,OAAO,WAAW;AAC3B,QAAI,gBAAW,GAAG,EAAE;AACpB,eAAW,OAAO,OAAO,GAAG,GAAI;AAC9B,YAAM,KAAK;AACX,YAAM,YAAY,MAAM,IAAI,QAAQ,KAAK,EAAE;AAC3C,UAAI,CAAC,WAAW;AACd,YAAI,6BAAwB,IAAI,IAAI,EAAE;AACtC,cAAM,IAAI,QAAQ;AAClB,cAAM,cAAc,WAAW,UAAU,EAAE,SAAS,IAAI,CAAC;AACzD,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,KAAK,EAAE;AAAA,IACzB;AAGA,UAAM,OAAO,OAAO,GAAG,EAAG,OAAO,OAAK,EAAE,SAAS,KAAK;AACtD,eAAW,OAAO,MAAM;AACtB,YAAM,KAAK,MAAMM,aAAY,KAAK,QAAQ;AAC1C,UAAI,CAAC,IAAI;AACP,YAAI,UAAK,IAAI,IAAI,kCAAkC,QAAQ,WAAW,GAAG;AACzE,cAAM,IAAI,QAAQ;AAClB,cAAM,cAAc,WAAW,UAAU,EAAE,SAAS,IAAI,CAAC;AACzD,eAAO;AAAA,MACT;AACA,UAAI,UAAK,IAAI,IAAI,QAAQ;AACzB,YAAM,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI;AACjC,UAAI,IAAI;AAAE,WAAG,SAAS;AAAW,WAAG,SAAS;AAAA,MAAM;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,UAAU,UAAU,SAAS,MAAM,cAAc,QAAQ,cAAc,OAAQ,WAAW,KAAK,IAAI,MAAM,KAAM,QAAQ,CAAC,CAAC;AAC/H,MAAI,OAAO;AACX,QAAM,IAAI,QAAQ;AAClB,QAAM,cAAc,WAAW,UAAU,EAAE,SAAS,IAAI,CAAC;AACzD,SAAO;AACT;AAEA,eAAeA,aAAY,KAAoB,UAAoC;AACjF,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,KAAK,MAAM,YAAY,IAAI,MAAM,IAAI,WAAW;AACtD,QAAI,GAAI,QAAO;AACf,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;;;ACbO,SAAS,aAAa,QAAwC;AACnE,SAAO;AACT;;;AxD/DA,SAAS,cAAsB;AAC7B,MAAI;AACF,UAAM,OAAOC,SAAQC,eAAc,YAAY,GAAG,CAAC;AACnD,UAAM,UAAUC,OAAK,MAAM,MAAM,cAAc;AAC/C,WAAO,KAAK,MAAMC,cAAa,SAAS,MAAM,CAAC,EAAE,WAAW;AAAA,EAC9D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,OAAO;AACpB,QAAM,MAAM,QAAQ,KAAK,MAAM,CAAC;AAEhC,MAAI,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,WAAW,GAAG;AACnD,YAAQ,IAAI,YAAY,CAAC;AACzB;AAAA,EACF;AACA,MAAI,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,QAAQ,GAAG;AAChD,YAAQ,IAAI,KAAK;AACjB;AAAA,EACF;AAIA,QAAM,SAAS,iBAAiB,GAAG;AACnC,MAAI,WAAW,QAAQ;AACrB,YAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC;AAAA,EACpC;AAEA,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,UAAU,aAAa,GAAG;AAEhC,MAAI,QAAQ;AACV,UAAM,UAAU,IAAI,MAAM,CAAC;AAE3B,QAAI;AACJ,QAAI;AAAE,gBAAU,eAAe,KAAK,QAAQ,UAAU;AAAA,IAAG,SAClD,GAAQ;AAAE,cAAQ,MAAM,UAAK,EAAE,OAAO,EAAE;AAAG,cAAQ,KAAK,CAAC;AAAA,IAAG;AACnE,UAAM,MAAM,MAAM,WAAW,OAAO;AACpC,UAAM,UAAU,EAAE,QAAQ,KAAK,SAAS,KAAK,KAAK,QAAQ,KAA+B,QAAQ,QAAQ,OAAO;AAChH,QAAI,WAAW,OAAW,SAAQ,KAAK,MAAM,QAAQ,SAAS,OAAO,CAAC;AACtE,QAAI,WAAW,UAAW,SAAQ,KAAK,MAAM,WAAW,OAAO,CAAC;AAChE,QAAI,WAAW,SAAW,SAAQ,KAAK,MAAM,UAAU,OAAO,CAAC;AAC/D,QAAI,WAAW,MAAW,SAAQ,KAAK,MAAM,OAAO,SAAS,OAAO,CAAC;AACrE,QAAI,WAAW,OAAW,SAAQ,KAAK,MAAM,QAAQ,OAAO,CAAC;AAAA,EAE/D;AAGA,MAAI;AACJ,MAAI;AACF,iBAAa,eAAe,KAAK,QAAQ,UAAU;AAAA,EACrD,SAAS,GAAQ;AACf,YAAQ,MAAM,UAAK,EAAE,OAAO,EAAE;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,MAAM,WAAW,UAAU;AAG1C,QAAM,SAAS,eAAe,QAAQ,GAAG;AACzC,MAAI,OAAO,QAAQ;AACjB,YAAQ,MAAM;AAAA,EAAgC,uBAAuB,MAAM,CAAC,EAAE;AAC9E,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,WAAW,gBAAgB,MAAM;AACvC,MAAI,SAAS,QAAQ;AACnB,YAAQ,KAAK;AAAA,EAAuB,yBAAyB,QAAQ,CAAC,EAAE;AAAA,EAC1E;AAGA,MAAI;AACJ,MAAI;AACF,eAAW,eAAe,OAAO,UAAU,SAAS,MAAM;AAAA,EAC5D,SAAS,GAAQ;AACf,YAAQ,MAAM,UAAK,EAAE,OAAO,EAAE;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,CAAC,SAAS,QAAQ;AACpB,YAAQ,MAAM,2CAAsC;AACpD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,WAAW,MAAM,eAAe;AAGtC,QAAM,UAAU,OAAO,UAAUD,OAAK,KAAK,OAAO,OAAO,IAAIA,OAAK,KAAK,MAAM;AAC7E,QAAM,MAAM,aAAa,SAAS,QAAQ,GAA6B;AACvE,MAAI,OAAO,KAAK;AACd,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG,GAAG;AAC/C,UAAI,CAAC,IAAI,CAAC,EAAG,KAAI,CAAC,IAAI;AAAA,IACxB;AAAA,EACF;AAGA,MAAI,gBAA4C;AAChD,MAAI,YAA8B;AAClC,MAAI,QAAQ,SAAS,OAAO,OAAO;AACjC,oBAAgB,oBAAoB,OAAO,MAAM,QAAQ;AACzD,gBAAY;AAAA,MACV,MAAM,QAAQ,aAAa,OAAO,MAAM,QAAQ,SAAS;AAAA,MACzD,QAAQ,IAAI,iBAAiB,KAAK,IAAI,QAAQ,KAAK;AAAA,MACnD,QAAQ,OAAO,MAAM;AAAA,MACrB,KAAK,QAAQ,YAAY,OAAO,MAAM,OAAO;AAAA,MAC7C,YAAY,QAAQ,mBAAmB,OAAO,MAAM,cAAc;AAAA,MAClE,UAAU,QAAQ,aAAa,OAAO,MAAM,YAAYA,OAAKE,SAAQ,GAAG,YAAY,mBAAmB;AAAA,IACzG;AAAA,EACF;AAGA,MAAI,QAAQ,QAAQ;AAClB,cAAU,EAAE,QAAQ,UAAU,SAAS,KAAK,SAAS,KAAK,eAAe,UAAU,CAAC;AACpF;AAAA,EACF;AAGA,MAAI,UAA0B;AAC9B,MAAI,QAAQ,SAAS;AACnB,cAAU,IAAI,QAAQ,EAAE,aAAa,OAAO,MAAM,SAAS,QAAQ,OAAO,CAAC;AAAA,EAC7E;AAOA,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,UAAM,eAAe,gBAAgB,OAAO,IAAI;AAChD,QAAI,aAAa,OAAO,CAAC,aAAa,OAAO;AAC3C,cAAQ,MAAM,iDAA4C,OAAO,IAAI,UAAU,aAAa,GAAG,IAAI;AACnG,cAAQ,MAAM,EAAE;AAChB,cAAQ,MAAM,qEAAqE;AACnF,cAAQ,MAAM,oBAAoB;AAClC,cAAQ,MAAM,iCAAiC;AAC/C,cAAQ,MAAM,2BAA2B;AACzC,YAAM,SAAS,MAAM;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAKA,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,UAAM,YAAY,MAAM,kBAAkB,QAAQ;AAClD,QAAI,UAAU,QAAQ;AACpB,YAAM,WAAW,MAAM,qBAAqB,WAAW;AAAA,QACrD,UAAU,QAAQ;AAAA,QAClB,KAAK,SAAO,QAAQ,OAAO,MAAM,MAAM,IAAI;AAAA,QAC3C,QAAQ,MAAM,SAAS,4CAA4C;AAAA,MACrE,CAAC;AACD,UAAI,CAAC,UAAU;AACb,cAAM,SAAS,MAAM;AACrB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,QAAQ,MAAM;AAChB,UAAM,OAAO,MAAM,QAAQ;AAAA,MACzB;AAAA,MAAQ;AAAA,MAAU;AAAA,MAAS;AAAA,MAAU;AAAA,MAAK,SAAS;AAAA,MAAK;AAAA,IAC1D,CAAC;AACD,UAAM,SAAS,MAAM;AACrB,YAAQ,KAAK,IAAI;AAAA,EACnB;AAIA,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,UAAM,WAAW,EAAE,QAAQ,UAAU,SAAS,UAAU,KAAK,SAAS,KAAK,eAAe,UAAU,CAAC;AACrG;AAAA,EACF;AAGA,MAAI,WAAW,MAAM;AACnB,QAAI,CAAC,IAAI,SAAS,IAAI,KAAK,CAAC,IAAI,SAAS,UAAU,GAAG;AACpD,cAAQ,MAAM,qDAAqD;AACnE,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,YAAQ,KAAK,MAAM,YAAY;AAAA,MAC7B;AAAA,MAAQ;AAAA,MAAU;AAAA,MAAS;AAAA,MAAU;AAAA,MAAK,SAAS;AAAA,MAAK;AAAA,MAAe;AAAA,IACzE,CAAC,CAAC;AAAA,EACJ;AAGA,QAAM,gBAAgB,QAAQ,MAAM,SAAS;AAC7C,QAAM,EAAE,cAAc,IAAI;AAAA,IACxBC,OAAM,cAAc,KAAK;AAAA,MACvB;AAAA,MAAQ;AAAA,MAAU;AAAA,MAAS;AAAA,MAAU;AAAA,MAAK,SAAS;AAAA,MACnD;AAAA,MAAe;AAAA,MAAW;AAAA,IAC5B,CAAC;AAAA,IACD,EAAE,aAAa,OAAO,cAAc,eAAe,aAAa,cAAc;AAAA,EAChF;AAEA,QAAM,cAAc;AACtB;AAWA,SAAS,SAAS,UAAoC;AACpD,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAC5B,UAAM,QAAQ,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,SAAS,QAAQ,OAAO,KAAK;AACzF,QAAI,CAAC,OAAO;AAAE,MAAAA,SAAQ,KAAK;AAAG;AAAA,IAAQ;AAEtC,YAAQ,OAAO,MAAM,QAAQ;AAC7B,YAAQ,MAAM,OAAO;AACrB,YAAQ,MAAM,YAAY,MAAM;AAEhC,UAAM,UAAU,MAAM;AACpB,cAAQ,MAAM,eAAe,QAAQ,MAAM;AAC3C,cAAQ,MAAM,eAAe,OAAO,KAAK;AACzC,cAAQ,MAAM,MAAM;AAAA,IACtB;AACA,UAAM,SAAS,CAAC,SAA0B;AACxC,cAAQ;AACR,MAAAA,SAAQ,YAAY,KAAK,OAAO,IAAI,EAAE,KAAK,CAAC,CAAC;AAAA,IAC/C;AACA,UAAM,QAAQ,MAAM;AAAE,cAAQ;AAAG,MAAAA,SAAQ,KAAK;AAAA,IAAG;AAEjD,YAAQ,MAAM,KAAK,QAAQ,MAAM;AACjC,YAAQ,MAAM,KAAK,OAAO,KAAK;AAAA,EACjC,CAAC;AACH;AAgBA,SAAS,oBAA6B;AACpC,QAAM,WAAW,QAAQ,KAAK,CAAC;AAC/B,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,aAAaL,eAAc,YAAY,GAAG;AAChD,MAAI;AACF,WAAO,aAAa,QAAQ,MAAM;AAAA,EACpC,QAAQ;AACN,WAAO,aAAa;AAAA,EACtB;AACF;AAEA,IAAI,kBAAkB,GAAG;AACvB,OAAK,EAAE,MAAM,OAAK;AAChB,YAAQ,MAAM,CAAC;AACf,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":["React","readFileSync","dirname","join","fileURLToPath","homedir","existsSync","resolve","existsSync","resolve","spawn","createReadStream","watchFile","unwatchFile","existsSync","statSync","readFile","join","dirname","homedir","createInterface","resolve","existsSync","lower","existsSync","readFileSync","join","createInterface","existsSync","existsSync","join","resolve","existsSync","resolve","createInterface","spawn","writeFileSync","readFileSync","existsSync","unlinkSync","mkdirSync","join","homedir","createInterface","join","existsSync","existsSync","resolve","spawn","existsSync","join","resolve","join","existsSync","resolve","spawn","resolve","join","existsSync","mkdirSync","join","dirname","homedir","spawn","join","resolve","join","spawn","net","net","sanitize","join","homedir","existsSync","readFileSync","mkdirSync","unlinkSync","resolve","createInterface","services","writeFileSync","spawn","p","join","homedir","sanitize","existsSync","statSync","resolve","createInterface","createReadStream","watchFile","unwatchFile","spawn","sleep","pidAlive","sleep","existsSync","mkdirSync","writeFileSync","dirname","existsSync","mkdirSync","writeFileSync","dirname","EMPTY_CONFIG","existsSync","mkdirSync","writeFileSync","dirname","EMPTY_CONFIG","useCallback","useRef","Box","Text","mgr","useState","useCallback","next","useEffect","useRef","useEffect","useState","useEffect","useEffect","useRef","createInterface","createReadStream","existsSync","totalmem","freemem","cpus","useRef","useEffect","existsSync","resolve","createInterface","createReadStream","totalmem","freemem","cpus","useEffect","useEffect","useEffect","useRef","useState","useEffect","useState","MAX_RESTARTS","cpus","useEffect","useState","useRef","useState","useEffect","useEffect","useState","useState","useEffect","useEffect","Box","Text","jsx","jsxs","useEffect","Box","Text","Box","Text","jsx","jsxs","useState","useMemo","Box","Text","useInput","jsx","jsxs","useState","Box","Text","useInput","jsx","jsxs","jsx","jsxs","useRef","useCallback","Box","Text","waitHealthy","dirname","fileURLToPath","join","readFileSync","homedir","React","resolve"]}
|