@gachlab/devup 0.5.0 → 0.7.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/CHANGELOG.md +42 -0
- package/README.md +74 -454
- package/dist/config/cli.d.ts +2 -1
- package/dist/config/cli.d.ts.map +1 -1
- package/dist/config/diff.d.ts +19 -0
- package/dist/config/diff.d.ts.map +1 -0
- package/dist/config/validator.d.ts +9 -0
- package/dist/config/validator.d.ts.map +1 -1
- package/dist/control-plane/socket-server.d.ts +31 -0
- package/dist/control-plane/socket-server.d.ts.map +1 -0
- package/dist/index.js +1047 -525
- package/dist/index.js.map +1 -1
- package/dist/process/health-poller.d.ts +15 -0
- package/dist/process/health-poller.d.ts.map +1 -0
- package/dist/process/internals.d.ts +14 -0
- package/dist/process/internals.d.ts.map +1 -0
- package/dist/process/lifecycle.d.ts +31 -0
- package/dist/process/lifecycle.d.ts.map +1 -0
- package/dist/process/manager.d.ts +11 -13
- package/dist/process/manager.d.ts.map +1 -1
- package/dist/process/restarter.d.ts +26 -0
- package/dist/process/restarter.d.ts.map +1 -0
- package/dist/process/spawner.d.ts +38 -0
- package/dist/process/spawner.d.ts.map +1 -0
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/LogsPanel.d.ts +9 -1
- package/dist/tui/LogsPanel.d.ts.map +1 -1
- package/dist/tui/hooks/useBootSequence.d.ts +20 -0
- package/dist/tui/hooks/useBootSequence.d.ts.map +1 -0
- package/dist/tui/hooks/useContextualTips.d.ts +6 -0
- package/dist/tui/hooks/useContextualTips.d.ts.map +1 -0
- package/dist/tui/hooks/useControlPlane.d.ts +10 -0
- package/dist/tui/hooks/useControlPlane.d.ts.map +1 -0
- package/dist/tui/hooks/useHotReload.d.ts +7 -0
- package/dist/tui/hooks/useHotReload.d.ts.map +1 -0
- package/dist/tui/hooks/useLogsPause.d.ts +4 -0
- package/dist/tui/hooks/useLogsPause.d.ts.map +1 -0
- package/dist/tui/hooks/useTerminalSize.d.ts +4 -0
- package/dist/tui/hooks/useTerminalSize.d.ts.map +1 -0
- package/dist/utils/colors.d.ts +4 -0
- package/dist/utils/colors.d.ts.map +1 -0
- package/dist/utils/env.d.ts +5 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/format.d.ts +3 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/install-stamp.d.ts +6 -0
- package/dist/utils/install-stamp.d.ts.map +1 -0
- package/dist/utils/phases.d.ts +4 -0
- package/dist/utils/phases.d.ts.map +1 -0
- package/dist/utils/process-args.d.ts +8 -0
- package/dist/utils/process-args.d.ts.map +1 -0
- package/dist/utils/redact.d.ts +4 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/search.d.ts +17 -0
- package/dist/utils/search.d.ts.map +1 -0
- package/dist/utils/stats.d.ts +19 -0
- package/dist/utils/stats.d.ts.map +1 -0
- package/dist/utils.d.ts +10 -41
- package/dist/utils.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.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/process/manager.ts","../src/process/installer.ts","../src/tui/hooks/useKeyBindings.ts","../src/tui/hooks/useProxySync.ts","../src/tui/LogsPanel.tsx","../src/tui/StatsPanel.tsx","../src/tui/StatusBar.tsx","../src/tui/ServiceList.tsx","../src/tui/SearchInput.tsx","../src/lazy/proxy.ts","../src/process/external.ts","../src/tui/tips.ts","../src/process/log-sink.ts","../src/orchestrator/dry-run.ts","../src/orchestrator/once.ts","../src/config/types.ts"],"sourcesContent":["import React from 'react';\nimport { render } from 'ink';\nimport { readFileSync } 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 } from './config/validator.js';\nimport { parseCliArgs, filterServices, USAGE } from './config/cli.js';\nimport { detectSubcommand, runLogs, runInstall, runStatus, runHelp } from './orchestrator/subcommands.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 }\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\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 // --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 // 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\nmain().catch(e => {\n console.error(e);\n process.exit(1);\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 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}\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\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 };\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 }\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 type { DevStackConfig } from '../config/types.js';\n\nconst KNOWN = new Set(['logs', 'install', 'status', 'help']);\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 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 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 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\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\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, writeFileSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { join } from 'node:path';\nimport type { ServiceConfig } from './config/types.js';\n\n// ── .env parsing ──\n\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\n// ── Resource awareness ──\n\n/** Hysteresis state machine for the \"RAM pressure\" banner.\n * Returns the next visibility given the current sample and previous visibility.\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\n// ── Verbose stats helpers ──\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\n// ── Log level detection ──\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\n// ── Search pattern ──\n\nexport 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\n// ── Format helpers ──\n\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\n// ── npm install stamps ──\n\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\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\n// ── Sort helpers ──\n\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// ── Phase grouping ──\n\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\n// ── Process args / env builders ──\n\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\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\n// ── CPU percent calculation ──\n\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// ── Color palette ──\n\nexport const tagColors = [\n 'cyan', 'yellow', 'green', 'magenta', 'blue',\n 'red', '#5faf5f', '#d7af5f', '#5f87d7', '#af5faf',\n '#5fd7d7', '#d75f5f', 'white',\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, { useEffect, useState, useCallback, useRef } from 'react';\nimport { Box, Text, useStdout } 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 { 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 { 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 type { ProcessState } from '../process/types.js';\nimport { startExternals, stopExternals, type ExternalProc } from '../process/external.js';\nimport { isCrashLooped } from './StatsPanel.js';\nimport { pickTip } from './tips.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 { 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 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 [booted, setBooted] = useState(false);\n const lazyProxies = useRef<Map<string, LazyProxy>>(new Map());\n const externals = useRef<ExternalProc[]>([]);\n const shownTips = useRef<Set<string>>(new Set());\n const [activeTip, setActiveTip] = useState<string | null>(null);\n\n const kb = useKeyBindings({\n onQuit: () => {\n void shutdown();\n },\n onClearLogs: pm.clearLogs,\n onToggleProxy: () => {},\n });\n\n const shutdown = useCallback(async () => {\n lazyProxies.current.forEach(p => p.destroy());\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]);\n\n // Propagar pausa al sink de logs (incluye auto-pausa cuando el usuario scrolleó arriba).\n useEffect(() => {\n pm.setPaused(kb.logsPaused || kb.logsScrollOffset > 0);\n }, [kb.logsPaused, kb.logsScrollOffset, pm]);\n\n // Contextual tips: evaluate periodically, surface once per session.\n useEffect(() => {\n const tip = pickTip({\n totalLogs: pm.logs.length,\n hasSearch: !!kb.searchTerm,\n hasFilter: !!kb.logFilter,\n crashLoopedCount: [...pm.states.values()].filter(isCrashLooped).length,\n shown: shownTips.current,\n });\n if (tip && tip.id !== 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 }, [pm.logs.length, pm.states, kb.searchTerm, kb.logFilter, activeTip]);\n\n useProxySync(proxyProvider, proxyOpts, pm.states, kb.proxyEnabled);\n\n // Boot sequence\n useEffect(() => {\n if (booted || !pm.manager) return;\n setBooted(true);\n const mgr = pm.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) => pm.pushLog(`ext:${svc}`, msg, 12),\n });\n externals.current = result.procs;\n if (!result.allHealthy) {\n pm.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 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, pm.manager, services, cliArgs, config.lazy]);\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 />\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';\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 useEffect(() => {\n const mgr = new ProcessManager({\n baseCwd, env, platform,\n events: {\n onLog: (svcName, text, colorIdx) => {\n sinkRef.current?.write(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: () => setStates(new Map(mgr.state)),\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 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 };\n}\n","import { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join, resolve } 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 { checkHealth, deriveHealth, checkPort } from './health.js';\nimport { installService } from './installer.js';\nimport { buildProcessArgs, buildProcessEnv } from '../utils.js';\n\nconst MAX_RESTARTS = 3;\nconst BACKOFF_BASE_MS = 2000;\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\nfunction 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\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 platform: Platform;\n private readonly events: ProcessManagerEvents;\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.platform = opts.platform;\n this.events = opts.events;\n }\n\n async 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.log(svc.name, msg, idx));\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\n if (svc.type === 'api') {\n const occupied = await checkPort(svc.port);\n if (occupied && !isRestart) {\n this.log(svc.name, `⚠ port ${svc.port} already in use — skipping`, 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 // Record crashed state so the UI shows the failure.\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 // Catches stale config after a rebase that renamed directories — Node 22 watch\n // would die with a cryptic message buried in stderr.\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 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\n const errorRegex = compileReadyPattern(svc.errorPattern); // reuses same /pattern/flags grammar\n const countsAsError = (line: string) => errorRegex ? errorRegex.test(line) : true;\n\n const stdoutBuf = lineBuffer(line => {\n markReadyIfMatch(line);\n this.log(svc.name, line, colorIdx);\n });\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 proc.on('close', code => {\n this.procs.delete(proc);\n // Tear down the side-car watch process when the main one stops.\n this.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\n if (state.restarts < MAX_RESTARTS) {\n state.restarts++;\n const delay = BACKOFF_BASE_MS * Math.pow(2, state.restarts - 1);\n this.log(svc.name, `🔄 auto-restart ${state.restarts}/${MAX_RESTARTS} in ${delay}ms...`, colorIdx);\n setTimeout(() => this.start(svc, colorIdx, true), delay);\n } else {\n this.log(svc.name, '⛔ max restarts reached', colorIdx);\n }\n });\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 runPreBuild(svc: ServiceConfig, cwd: string, colorIdx: number): Promise<boolean> {\n this.log(svc.name, `🔨 preBuild: ${svc.preBuild}`, colorIdx);\n return new Promise(resolve => {\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 resolve(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 resolve(true);\n } else {\n this.log(svc.name, `[build] ❌ exited with code ${code}`, colorIdx);\n resolve(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 (used when preBuild fails). */\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 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 private 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 async restart(name: string): Promise<void> {\n const st = this.state.get(name);\n if (!st) return;\n this.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.start(st.svc, st.colorIdx, true);\n this.log(name, '🔄 manual restart', st.colorIdx);\n }\n\n async checkAllHealth(): 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 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 (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 private log(name: string, text: string, colorIdx: number): void {\n this.events.onLog(name, text, colorIdx);\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 { 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 React, { useEffect, useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport type { LogEntry } from './hooks/useProcessManager.js';\nimport { tagColors, compileSearchPattern } from '../utils.js';\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}\n\nexport function LogsPanel({ logs, filter, searchTerm, paused, showTimestamps, maxNameLen, height, focused, scrollOffset, resetScroll, levelFilter = 'all' }: 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={focused ? 'cyan' : 'gray'} 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, { 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 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 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 { 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","/** 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 { 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","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,qBAAoB;AAC7B,SAAS,WAAAC,UAAS,QAAAC,aAAY;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;;;ADrBO,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;;;AElLA,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;AAuCd,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,EACX;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,IACtD;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;;;AC7IA,SAAS,aAAa;AACtB,SAAS,kBAAkB,WAAW,aAAa,cAAAC,aAAY,gBAAgB;AAC/E,SAAS,YAAAC,iBAAgB;AACzB,SAAS,QAAAC,OAAM,eAAe;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AACxB,SAAS,uBAAuB;;;ACNhC,OAAO,SAAS;AAChB,OAAO,UAAU;AAIV,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;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;;;ACpEA,SAAS,cAAAC,aAAY,cAAc,qBAAqB;AACxD,SAAS,kBAAkB;AAC3B,SAAS,QAAAC,aAAY;AAKd,SAAS,aAAa,UAAkB,UAAkC,CAAC,GAA2B;AAC3G,QAAM,MAAM,EAAE,GAAG,QAAQ;AACzB,MAAI,CAACD,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;AASO,SAAS,wBACd,UACA,iBACA,gBAAgB,IAChB,eAAe,IACN;AACT,MAAI,YAAY,cAAe,QAAO;AACtC,MAAI,WAAW,aAAc,QAAO;AACpC,SAAO;AACT;AAMO,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;AAQO,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;AAgBO,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,YAAME,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;AAIO,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;AAIO,SAAS,aAAa,SAA0B;AACrD,QAAM,KAAKD,MAAK,SAAS,cAAc;AACvC,MAAI,CAACD,YAAW,EAAE,EAAG,QAAO;AAC5B,MAAI;AACF,UAAM,UAAU,WAAW,KAAK,EAAE,OAAO,aAAaC,MAAK,SAAS,cAAc,CAAC,CAAC,EAAE,OAAO,KAAK;AAClG,UAAM,YAAYA,MAAK,IAAI,gBAAgB;AAC3C,QAAID,YAAW,SAAS,KAAK,aAAa,WAAW,MAAM,MAAM,QAAS,QAAO;AAAA,EACnF,QAAQ;AAAA,EAAoC;AAC5C,SAAO;AACT;AAEO,SAAS,kBAAkB,SAAuB;AACvD,MAAI;AACF,UAAM,UAAU,WAAW,KAAK,EAAE,OAAO,aAAaC,MAAK,SAAS,cAAc,CAAC,CAAC,EAAE,OAAO,KAAK;AAClG,kBAAcA,MAAK,SAAS,gBAAgB,gBAAgB,GAAG,OAAO;AAAA,EACxE,QAAQ;AAAA,EAAoB;AAC9B;AAIO,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,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;AAIO,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;AAEO,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;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;AAIO,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;;;AF1LA,IAAM,QAAQ,oBAAI,IAAI,CAAC,QAAQ,WAAW,UAAU,MAAM,CAAC;AAGpD,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,YAAYE,MAAK,QAAQ,GAAG,UAAU,MAAM;AACzD,SAAOA,MAAK,MAAM,SAAS,OAAO,IAAI,CAAC;AACzC;AAEA,SAAS,SAAS,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,OAAOA,MAAK,QAAQ,KAAK,QAAQ,KAAK,MAAM,GAAG,GAAG,SAAS,MAAM,CAAC,MAAM;AAC9E,MAAI,CAACC,YAAW,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,KAAK,SAAS,IAAI,EAAE,IAAI;AACxD;AAEA,eAAe,WAAW,MAAc,KAAyC;AAC/E,SAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,UAAM,KAAK,gBAAgB,EAAE,OAAO,iBAAiB,MAAM,EAAE,UAAU,OAAO,CAAC,EAAE,CAAC;AAClF,OAAG,GAAG,QAAQ,OAAK,IAAI,CAAC,CAAC;AACzB,OAAG,GAAG,SAAS,MAAMA,SAAQ,CAAC;AAC9B,OAAG,GAAG,SAAS,MAAM;AAAA,EACvB,CAAC;AACH;AAEA,eAAe,WAAW,MAAc,KAA0B,UAAU,GAAoB;AAC9F,MAAI,MAAM;AAEV,SAAO,CAACD,YAAW,IAAI,EAAG,OAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AACnE,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAC5B,UAAM,OAAO,YAAY;AACvB,YAAM,OAAO,SAAS,IAAI,EAAE;AAC5B,UAAI,OAAO,KAAK;AACd,cAAM,IAAI,QAAc,SAAO;AAC7B,gBAAM,KAAK,gBAAgB,EAAE,OAAO,iBAAiB,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,cAAU,MAAM,EAAE,UAAU,IAAI,GAAG,MAAM;AAAE,WAAK,KAAK;AAAA,IAAG,CAAC;AACzD,YAAQ,KAAK,UAAU,MAAM;AAAE,kBAAY,IAAI;AAAG,MAAAA,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,KAAKF,MAAK,KAAK,SAAS,EAAE,GAAG,EAAE,EAAE;AAC9F,QAAM,QAAQ,CAAC,GAAG,KAAK;AACvB,QAAM,SAAmB,CAAC;AAC1B,MAAI,WAAW;AAEf,QAAM,IAAI,QAAc,CAAAE,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,CAACD,YAAW,GAAG,EAAG,QAAO,QAAQ,QAAQ,KAAK;AAClD,MAAI,CAAC,aAAa,GAAG,EAAG,QAAO,QAAQ,QAAQ,IAAI;AACnD,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAC5B,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,SAAK,GAAG,SAAS,UAAQ;AACvB,UAAI,SAAS,GAAG;AAAE,0BAAkB,GAAG;AAAG,QAAAA,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;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,cAAc;AAClB,MAAI,iEAAiE;AACrE,MAAI,4EAA4E;AAChF,MAAI,0EAA0E;AAC9E,MAAI,yEAAyE;AAC7E,MAAI,EAAE;AACN,MAAI,kDAA6C;AACjD,SAAO;AACT;;;AG5LA,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,cAAAC,aAAY,WAAW,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,CAACF,YAAW,GAAG,EAAG,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,aAAY,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,YAAW,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,aAAY,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,YAAW,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,aAAAC,YAAW,YAAAC,WAAU,eAAAC,cAAa,UAAAC,eAAc;AAChE,SAAS,OAAAC,MAAK,QAAAC,OAAM,iBAAiB;;;ACDrC,SAAS,UAAU,WAAW,QAAQ,mBAAmB;;;ACAzD,SAAS,SAAAC,cAAa;AACtB,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,OAAM,WAAAC,gBAAe;;;ACF9B,SAAS,SAAAC,cAAa;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,OAAOC,OAAM,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,QAAAD,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;;;AD3BA,IAAM,eAAe;AACrB,IAAM,kBAAkB;AAGjB,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;AAEA,SAAS,WAAW,QAAgC;AAClD,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;AAEO,IAAM,iBAAN,MAAqB;AAAA,EACjB,QAAQ,oBAAI,IAA0B;AAAA,EAC9B,QAAQ,oBAAI,IAAkB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAKT;AACD,SAAK,UAAU,KAAK;AACpB,SAAK,MAAM,KAAK;AAChB,SAAK,WAAW,KAAK;AACrB,SAAK,SAAS,KAAK;AAAA,EACrB;AAAA,EAEA,MAAM,QAAQ,KAAoB,UAAqC;AACrE,UAAM,MAAME,MAAK,KAAK,SAAS,IAAI,GAAG;AACtC,UAAM,MAAM,YAAY,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,YAAY;AAC9D,WAAO,eAAe,KAAK,KAAK,KAAK,SAAO,KAAK,IAAI,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,EAC1E;AAAA,EAEA,MAAM,MAAM,KAAoB,UAAkB,YAAY,OAAsB;AAClF,UAAM,MAAMA,MAAK,KAAK,SAAS,IAAI,GAAG;AAGtC,QAAI,IAAI,SAAS,OAAO;AACtB,YAAM,WAAW,MAAM,UAAU,IAAI,IAAI;AACzC,UAAI,YAAY,CAAC,WAAW;AAC1B,aAAK,IAAI,IAAI,MAAM,eAAU,IAAI,IAAI,mCAA8B,QAAQ;AAC3E;AAAA,MACF;AAAA,IACF;AAGA,QAAI,IAAI,UAAU;AAChB,YAAM,QAAQ,MAAM,KAAK,YAAY,KAAK,KAAK,QAAQ;AACvD,UAAI,CAAC,OAAO;AAEV,aAAK,mBAAmB,KAAK,QAAQ;AACrC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,iBAAiB,GAAG;AAKjC,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,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;AAEA,UAAM,aAAa,oBAAoB,IAAI,YAAY;AACvD,UAAM,gBAAgB,CAAC,SAAiB,aAAa,WAAW,KAAK,IAAI,IAAI;AAE7E,UAAM,YAAY,WAAW,UAAQ;AACnC,uBAAiB,IAAI;AACrB,WAAK,IAAI,IAAI,MAAM,MAAM,QAAQ;AAAA,IACnC,CAAC;AACD,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;AAE9C,SAAK,GAAG,SAAS,UAAQ;AACvB,WAAK,MAAM,OAAO,IAAI;AAEtB,WAAK,cAAc,KAAK;AACxB,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;AAEzC,UAAI,MAAM,WAAW,cAAc;AACjC,cAAM;AACN,cAAM,QAAQ,kBAAkB,KAAK,IAAI,GAAG,MAAM,WAAW,CAAC;AAC9D,aAAK,IAAI,IAAI,MAAM,0BAAmB,MAAM,QAAQ,IAAI,YAAY,OAAO,KAAK,SAAS,QAAQ;AACjG,mBAAW,MAAM,KAAK,MAAM,KAAK,UAAU,IAAI,GAAG,KAAK;AAAA,MACzD,OAAO;AACL,aAAK,IAAI,IAAI,MAAM,+BAA0B,QAAQ;AAAA,MACvD;AAAA,IACF,CAAC;AAGD,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,YAAY,KAAoB,KAAa,UAAoC;AACvF,SAAK,IAAI,IAAI,MAAM,uBAAgB,IAAI,QAAQ,IAAI,QAAQ;AAC3D,WAAO,IAAI,QAAQ,CAAAD,aAAW;AAC5B,YAAM,QAAQ,QAAQ,aAAa;AACnC,YAAM,QAAQ,QAAQ,YAAY;AAClC,YAAM,YAAY,QAAQ,OAAO;AACjC,YAAM,MAAM,gBAAgB,KAAK,KAAK,GAAG;AACzC,YAAM,QAAQC,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,QAAAD,SAAQ,KAAK;AAAA,MACf,CAAC;AACD,YAAM,GAAG,SAAS,UAAQ;AACxB,eAAO,MAAM;AAAG,eAAO,MAAM;AAC7B,YAAI,SAAS,GAAG;AACd,eAAK,IAAI,IAAI,MAAM,uBAAkB,QAAQ;AAC7C,UAAAA,SAAQ,IAAI;AAAA,QACd,OAAO;AACL,eAAK,IAAI,IAAI,MAAM,mCAA8B,IAAI,IAAI,QAAQ;AACjE,UAAAA,SAAQ,KAAK;AAAA,QACf;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,QAAQC,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,EAGQ,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,EAEA,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,EAEQ,cAAc,OAA2B;AAC/C,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,EAEA,MAAM,QAAQ,MAA6B;AACzC,UAAM,KAAK,KAAK,MAAM,IAAI,IAAI;AAC9B,QAAI,CAAC,GAAI;AACT,SAAK,KAAK,IAAI;AAEd,OAAG,WAAW;AACd,UAAM,QAAQ,GAAG,OAAO,OAAO;AAC/B,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,KAAK,CAAC;AAC3C,UAAM,KAAK,MAAM,GAAG,KAAK,GAAG,UAAU,IAAI;AAC1C,SAAK,IAAI,MAAM,4BAAqB,GAAG,QAAQ;AAAA,EACjD;AAAA,EAEA,MAAM,iBAAgC;AACpC,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;AAAA,EAEA,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;AAEA,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,CAAAD,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;AAAA,EAEQ,IAAI,MAAc,MAAc,UAAwB;AAC9D,SAAK,OAAO,MAAM,MAAM,MAAM,QAAQ;AAAA,EACxC;AACF;;;ADnVO,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;AAElB,YAAU,MAAM;AACd,UAAME,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,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,MAAM,UAAU,IAAI,IAAIA,KAAI,KAAK,CAAC;AAAA,MACnD;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,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,EACX;AACF;;;AG1IA,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,SAAgB,aAAAE,YAAW,eAAe;AAC1C,SAAS,KAAK,YAAY;AA2DpB,cAAK,YAAL;AAzCC,SAAS,UAAU,EAAE,MAAM,QAAQ,YAAY,QAAQ,gBAAgB,YAAY,QAAQ,SAAS,cAAc,aAAa,cAAc,MAAM,GAAU;AAClK,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,WAAU,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,qBAAC,OAAI,eAAc,UAAS,aAAY,SAAQ,aAAa,UAAU,SAAS,QAAQ,QACtF;AAAA,wBAAC,OAAI,+BAAC,QAAK,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,qBAAC,OACE;AAAA,0BAAkB,oBAAC,QAAK,UAAQ,MAAE,cAAG;AAAA,QACtC,qBAAC,QAAK,OAAc;AAAA;AAAA,UAAE,MAAM,QAAQ,OAAO,UAAU;AAAA,UAAE;AAAA,WAAC;AAAA,QACxD,oBAAC,QAAK,eAAC;AAAA,QACN,UAAU,oBAAC,QAAK,iBAAgB,UAAS,OAAM,SAAS,gBAAK,IAAU,oBAAC,QAAM,gBAAK;AAAA,WAJ5E,CAKV;AAAA,IAEJ,CAAC;AAAA,KACH;AAEJ;;;AC7EA,SAAgB,aAAAC,YAAW,YAAAC,iBAAgB;AAC3C,SAAS,OAAAC,MAAK,QAAAC,aAAY;AAI1B,OAAO,QAAQ;AA6BT,gBAAAC,MASA,QAAAC,aATA;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,gBAAAF,KAACG,OAAA,EAAK,OAAM,OAAM,MAAI,MAAC,oBAAC,IACxB,gBAAAH,KAACG,OAAA,EAAK,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,gBAAAF,MAACE,OAAA,EACE;AAAA;AAAA,MAAU;AAAA,MAAC,gBAAAH,KAACG,OAAA,EAAK,OAAe,eAAK,OAAO,EAAE,GAAE;AAAA,MAAO;AAAA,MAAE,OAAO,GAAG,IAAI,IAAI,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAC,gBAAAH,KAACG,OAAA,EAAK,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,gBAAAF,MAACG,MAAA,EAAI,eAAc,UACjB;AAAA,oBAAAH,MAACE,OAAA,EACE;AAAA;AAAA,MAAU;AAAA,MAAC,gBAAAH,KAACG,OAAA,EAAK,OAAe,eAAK,OAAO,EAAE,GAAE;AAAA,MAAO;AAAA,MAAE,OAAO,GAAG,IAAI,IAAI,EAAE,SAAS,CAAC;AAAA,MAAE;AAAA,MAAC,gBAAAH,KAACG,OAAA,EAAK,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,gBAAAF,MAACE,OAAA,EAAK,UAAQ,MAAC;AAAA;AAAA,MAAS,GAAG,IAAI;AAAA,MAAI;AAAA,MAAE;AAAA,OAAa;AAAA,IACjD,UAAU,gBAAAF,MAACE,OAAA,EAAK,UAAQ,MAAC;AAAA;AAAA,MAAS;AAAA,OAAO;AAAA,KAC5C;AAEJ;AAEA,SAAS,UAAU,EAAE,GAAG,GAAmB;AACzC,SAAO,gBAAAF,MAACE,OAAA,EAAK,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,QAAM,OAAO,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,EAAAE,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,gBAAAJ,MAACG,MAAA,EAAI,eAAc,UAAS,aAAY,SAAQ,aAAa,UAAU,UAAU,QAAQ,QACvF;AAAA,oBAAAH,MAACG,MAAA,EACC;AAAA,sBAAAH,MAACE,OAAA,EAAK,MAAI,MAAC,OAAM,SAAQ;AAAA;AAAA,QAAQ;AAAA,SAAa;AAAA,MAC7C,YAAY,gBAAAH,KAACG,OAAA,EAAK,OAAM,UAAS,uBAAS;AAAA,MAC1C,cAAc,KAAK,gBAAAF,MAACE,OAAA,EAAK,OAAM,OAAM,MAAI,MAAC;AAAA;AAAA,QAAI;AAAA,QAAY;AAAA,SAAe;AAAA,MAC1E,gBAAAF,MAACE,OAAA,EAAK,UAAQ,MAAC;AAAA;AAAA,QAAU;AAAA,QAAK;AAAA,QAAQ;AAAA,QAAK;AAAA,QAAM;AAAA,QAAO;AAAA,QAAE;AAAA,QAAQ;AAAA,SAAE;AAAA,MACpE,gBAAAH,KAACG,OAAA,EAAK,UAAQ,MAAC,sBAAG;AAAA,MAClB,gBAAAF,MAACE,OAAA,EAAK,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,gBAAAF,MAACE,OAAA,EAAK,UAAQ,MAAC;AAAA;AAAA,QAAU;AAAA,SAAS;AAAA,OAC5D;AAAA,IACC,aACC,gBAAAF,MAACG,MAAA,EACC;AAAA,sBAAAH,MAACE,OAAA,EAAK,OAAM,UAAS,MAAI,MAAC;AAAA;AAAA,QAAQ,OAAO,QAAQ,CAAC;AAAA,QAAE;AAAA,SAAS;AAAA,MAC7D,gBAAAH,KAACG,OAAA,EAAK,OAAM,UAAU,uBAAa,IAAI,OAAK,GAAG,EAAE,IAAI,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,GAAE;AAAA,OAC3F;AAAA,IAEF,gBAAAF,MAACG,MAAA,EAAI,UAAU,GAEb;AAAA,sBAAAH,MAACG,MAAA,EAAI,eAAc,UAAS,UAAU,GAAG,WAAW,GAClD;AAAA,wBAAAH,MAACE,OAAA,EAAK,MAAI,MAAC,OAAM,QAAO;AAAA;AAAA,UAAQ,KAAK;AAAA,UAAO;AAAA,WAAC;AAAA,QAC7C,gBAAAH,KAAC,aAAU,IAAQ;AAAA,QAClB,YAAY,IAAI,OACf,gBAAAA,KAAC,OAAY,MAAM,GAAG,IAAI,OAAO,IAAI,CAAC,GAAI,MAAM,MAAM,IAAI,CAAC,GAAG,IAAQ,WAA5D,CAA8E,CACzF;AAAA,SACH;AAAA,MAEA,gBAAAA,KAACI,MAAA,EAAI,eAAc,UAAS,OAAO,GAChC,gBAAM,KAAK,EAAE,QAAQ,cAAc,GAAG,CAAC,GAAG,MAAM,gBAAAJ,KAACG,OAAA,EAAa,UAAQ,MAAC,sBAAZ,CAAa,CAAO,GAClF;AAAA,MAEA,gBAAAF,MAACG,MAAA,EAAI,eAAc,UAAS,UAAU,GAAG,WAAW,GAClD;AAAA,wBAAAH,MAACE,OAAA,EAAK,MAAI,MAAC,OAAM,WAAU;AAAA;AAAA,UAAQ,KAAK;AAAA,UAAO;AAAA,WAAC;AAAA,QAChD,gBAAAH,KAAC,aAAU,IAAQ;AAAA,QAClB,YAAY,IAAI,OACf,gBAAAA,KAAC,OAAY,MAAM,GAAG,IAAI,OAAO,IAAI,CAAC,GAAI,MAAM,MAAM,IAAI,CAAC,GAAG,IAAQ,WAA5D,CAA8E,CACzF;AAAA,SACH;AAAA,OACF;AAAA,KACF;AAEJ;;;ACjLA,SAAS,OAAAO,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;;;ACzBA,OAAOI,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,SAAAC,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;;;ACpGO,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;;;AbyNQ,SAIF,OAAAC,MAJE,QAAAC,aAAA;AA5ND,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,EAAE,OAAO,IAAI,UAAU;AAC7B,QAAM,CAAC,MAAM,OAAO,IAAIC,UAAS,QAAQ,QAAQ,EAAE;AACnD,EAAAC,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,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,CAAC,QAAQ,SAAS,IAAID,UAAS,KAAK;AAC1C,QAAM,cAAcE,QAA+B,oBAAI,IAAI,CAAC;AAC5D,QAAM,YAAYA,QAAuB,CAAC,CAAC;AAC3C,QAAM,YAAYA,QAAoB,oBAAI,IAAI,CAAC;AAC/C,QAAM,CAAC,WAAW,YAAY,IAAIF,UAAwB,IAAI;AAE9D,QAAM,KAAK,eAAe;AAAA,IACxB,QAAQ,MAAM;AACZ,WAAK,SAAS;AAAA,IAChB;AAAA,IACA,aAAa,GAAG;AAAA,IAChB,eAAe,MAAM;AAAA,IAAC;AAAA,EACxB,CAAC;AAED,QAAM,WAAWG,aAAY,YAAY;AACvC,gBAAY,QAAQ,QAAQ,OAAK,EAAE,QAAQ,CAAC;AAC5C,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,GAAG,CAAC;AAGxC,EAAAF,WAAU,MAAM;AACd,OAAG,UAAU,GAAG,cAAc,GAAG,mBAAmB,CAAC;AAAA,EACvD,GAAG,CAAC,GAAG,YAAY,GAAG,kBAAkB,EAAE,CAAC;AAG3C,EAAAA,WAAU,MAAM;AACd,UAAM,MAAM,QAAQ;AAAA,MAClB,WAAW,GAAG,KAAK;AAAA,MACnB,WAAW,CAAC,CAAC,GAAG;AAAA,MAChB,WAAW,CAAC,CAAC,GAAG;AAAA,MAChB,kBAAkB,CAAC,GAAG,GAAG,OAAO,OAAO,CAAC,EAAE,OAAO,aAAa,EAAE;AAAA,MAChE,OAAO,UAAU;AAAA,IACnB,CAAC;AACD,QAAI,OAAO,IAAI,OAAO,WAAW;AAC/B,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,GAAG,KAAK,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,SAAS,CAAC;AAEtE,eAAa,eAAe,WAAW,GAAG,QAAQ,GAAG,YAAY;AAGjE,EAAAA,WAAU,MAAM;AACd,QAAI,UAAU,CAAC,GAAG,QAAS;AAC3B,cAAU,IAAI;AACd,UAAM,MAAM,GAAG;AAEf,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,GAAG,QAAQ,OAAO,GAAG,IAAI,KAAK,EAAE;AAAA,QACvD,CAAC;AACD,kBAAU,UAAU,OAAO;AAC3B,YAAI,CAAC,OAAO,YAAY;AACtB,aAAG,QAAQ,SAAS,8BAAyB,OAAO,OAAO,KAAK,IAAI,CAAC,oBAAoB,CAAC;AAC1F;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,sBAAY,QAAQ,IAAI,IAAI,MAAM,KAAK;AAAA,QACzC;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,GAAG,SAAS,UAAU,SAAS,OAAO,IAAI,CAAC;AAEvD,QAAM,qBAAqBE,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,gBAAAJ,MAACK,MAAA,EAAI,eAAc,UAAS,QAAQ,MAClC;AAAA,oBAAAL,MAACK,MAAA,EACC;AAAA,sBAAAL,MAACM,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,gBAAAN,MAACM,OAAA,EAAK,UAAQ,MAAC;AAAA;AAAA,QAAI;AAAA,SAAU;AAAA,OAC7C;AAAA,IAEA,gBAAAP;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;AAAA,IAClB;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;;;Ac1RA,SAAS,cAAAQ,cAAY,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,MAAMG,UAAS,KAAK,WAAW,CAAC;AAChD,SAAK,gBAAgB,KAAK,iBAAiB;AAC3C,IAAAJ,WAAU,KAAK,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACzC;AAAA;AAAA,EAGA,QAAQ,SAAyB;AAC/B,WAAOC,MAAK,KAAK,KAAK,GAAGG,UAAS,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,KAAKL,aAAW,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,SAASE,UAAS,MAAsB;AACtC,SAAO,KAAK,QAAQ,qBAAqB,GAAG,EAAE,QAAQ,YAAY,EAAE,KAAK;AAC3E;;;AClDO,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,MAAMC,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;;;A9BjEA,SAAS,cAAsB;AAC7B,MAAI;AACF,UAAM,OAAOC,SAAQC,eAAc,YAAY,GAAG,CAAC;AACnD,UAAM,UAAUC,MAAK,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;AAAA,EACjE;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;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,MAAK,KAAK,OAAO,OAAO,IAAIA,MAAK,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,MAAKE,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;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;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;AAEA,KAAK,EAAE,MAAM,OAAK;AAChB,UAAQ,MAAM,CAAC;AACf,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["React","readFileSync","dirname","join","fileURLToPath","homedir","existsSync","resolve","existsSync","resolve","existsSync","readFile","join","resolve","existsSync","join","lower","join","existsSync","resolve","existsSync","writeFileSync","dirname","existsSync","mkdirSync","writeFileSync","dirname","EMPTY_CONFIG","existsSync","mkdirSync","writeFileSync","dirname","EMPTY_CONFIG","useEffect","useState","useCallback","useRef","Box","Text","spawn","existsSync","join","resolve","spawn","existsSync","existsSync","resolve","spawn","join","existsSync","resolve","spawn","mgr","useState","useCallback","next","useEffect","useRef","useEffect","useEffect","useEffect","useState","Box","Text","jsx","jsxs","MAX_RESTARTS","Text","Box","useEffect","useState","Box","Text","jsx","jsxs","useState","useMemo","Box","Text","useInput","jsx","jsxs","useState","Box","Text","useInput","jsx","jsxs","net","net","spawn","join","resolve","join","spawn","jsx","jsxs","useState","useEffect","useRef","useCallback","Box","Text","existsSync","mkdirSync","join","dirname","homedir","sanitize","waitHealthy","dirname","fileURLToPath","join","readFileSync","homedir","React"]}
|
|
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/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/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/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/control-plane/socket-server.ts","../src/tui/hooks/useHotReload.ts","../src/config/diff.ts","../src/tui/hooks/useContextualTips.ts","../src/tui/tips.ts","../src/tui/StatsPanel.tsx","../src/tui/hooks/useBootSequence.ts","../src/lazy/proxy.ts","../src/process/external.ts","../src/tui/LogsPanel.tsx","../src/tui/StatusBar.tsx","../src/tui/ServiceList.tsx","../src/tui/SearchInput.tsx","../src/process/log-sink.ts","../src/orchestrator/dry-run.ts","../src/orchestrator/once.ts","../src/config/types.ts"],"sourcesContent":["import React from 'react';\nimport { render } from 'ink';\nimport { readFileSync } 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 } from './orchestrator/subcommands.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 }\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 // --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 // 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\nmain().catch(e => {\n console.error(e);\n process.exit(1);\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}\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\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 };\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 }\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 type { DevStackConfig } from '../config/types.js';\n\nconst KNOWN = new Set(['logs', 'install', 'status', 'help']);\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 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 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 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\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\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 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 socketServer = useControlPlane(pm.manager, config.name, logSink, pm.pushLog);\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';\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 useEffect(() => {\n const mgr = new ProcessManager({\n baseCwd, env, platform,\n events: {\n onLog: (svcName, text, colorIdx) => {\n sinkRef.current?.write(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: () => setStates(new Map(mgr.state)),\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 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 };\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 { checkPort } 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 if (svc.type === 'api') {\n const occupied = await checkPort(svc.port);\n if (occupied && !isRestart) {\n this.log(svc.name, `⚠ port ${svc.port} already in use — skipping`, 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 { 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 type { ProcessManager } from '../../process/manager.js';\nimport type { LogSink } from '../../process/log-sink.js';\nimport { startSocketServer, type SocketServerHandle } from '../../control-plane/socket-server.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): React.RefObject<SocketServerHandle | null> {\n const handleRef = useRef<SocketServerHandle | null>(null);\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 }, { 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]);\n return handleRef;\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 *\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 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}\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 const server = createServer(socket => handleClient(socket, ctx));\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 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 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 try {\n const result = await dispatch(req.method, (req.params ?? {}) as Record<string, unknown>, 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\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({\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 return { services: out };\n }\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 { useEffect } from 'react';\nimport { watch as fsWatch, type FSWatcher } from 'node:fs';\nimport type { ProcessManager } from '../../process/manager.js';\nimport type { CliArgs } from '../../config/cli.js';\nimport { loadConfig, findConfigFile } from '../../config/loader.js';\nimport { validateConfig, formatValidationErrors } from '../../config/validator.js';\nimport { diffServices, summariseDiff } from '../../config/diff.js';\n\n/** Watches the resolved config file when --watch-config is on. On each save:\n * re-load, validate, diff against the running set, apply add/remove/restart.\n * A failed validation leaves the running set untouched. 250 ms debounce. */\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 watcher: FSWatcher | null = null;\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\n let reloadInFlight = false;\n let reloadAgain = false;\n const reload = async () => {\n if (reloadInFlight) { reloadAgain = true; return; }\n reloadInFlight = true;\n try {\n const nextCfg = await loadConfig(configPath);\n const errs = validateConfig(nextCfg, baseCwd);\n if (errs.length) {\n pushLog('devup', `⚠ config reload failed:\\n${formatValidationErrors(errs)}`, 5);\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 // Apply: stop removed + changed, start added + changed.\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 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 pushLog('devup', `🔁 config reloaded: ${summariseDiff(diff)}`, 12);\n } catch (e: any) {\n pushLog('devup', `⚠ config reload error: ${e.message}`, 5);\n } finally {\n reloadInFlight = false;\n if (reloadAgain) { reloadAgain = false; void reload(); }\n }\n };\n\n // Debounce: editors often emit several change events per save.\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n watcher = fsWatch(configPath, () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => void reload(), 250);\n });\n return () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n watcher?.close();\n };\n }, [cliArgs.watchConfig, cliArgs.configPath, baseCwd, manager, pushLog]);\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","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 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 { 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 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 { 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","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":"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","names":["React","readFileSync","dirname","join","fileURLToPath","homedir","existsSync","resolve","existsSync","resolve","existsSync","readFile","join","resolve","existsSync","lower","existsSync","readFileSync","join","join","existsSync","resolve","existsSync","writeFileSync","dirname","existsSync","mkdirSync","writeFileSync","dirname","EMPTY_CONFIG","existsSync","mkdirSync","writeFileSync","dirname","EMPTY_CONFIG","useCallback","useRef","Box","Text","join","spawn","existsSync","existsSync","resolve","spawn","spawn","existsSync","join","resolve","join","existsSync","resolve","spawn","resolve","join","mgr","useState","useCallback","next","useEffect","useRef","useEffect","useState","useEffect","useEffect","useRef","createInterface","createReadStream","existsSync","createInterface","existsSync","mkdirSync","statSync","dirname","join","homedir","resolve","useRef","useEffect","existsSync","resolve","createInterface","createReadStream","useEffect","useEffect","useEffect","useRef","useState","useEffect","useState","MAX_RESTARTS","useEffect","useState","useRef","useState","useEffect","useEffect","useState","net","net","spawn","join","resolve","join","spawn","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","existsSync","mkdirSync","join","dirname","homedir","sanitize","waitHealthy","dirname","fileURLToPath","join","readFileSync","homedir","React"]}
|