everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 33.8 kB
Source Map (JSON)
{"version":3,"file":"infra.mjs","names":[],"sources":["../../src/cli/infra.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { config as loadDotenv } from \"dotenv\";\nimport type { RuntimeConfig } from \"../types\";\n\nconst POSTGRES_USER = \"everythingdev\";\nconst POSTGRES_PASSWORD = \"everythingdev\";\nconst API_DATABASE_SECRET = \"API_DATABASE_URL\";\nconst AUTH_DATABASE_SECRET = \"AUTH_DATABASE_URL\";\nconst HOST_SECRET = \"CORS_ORIGIN\";\nconst BASE_POSTGRES_PORT = 5434;\nconst BASE_REDIS_PORT = 6379;\n\nexport interface DatabaseSecretConfig {\n secret: string;\n slug: string;\n fromKey: string;\n port: number;\n serviceName: string;\n containerName: string;\n databaseName: string;\n volumeName: string;\n url: string;\n}\n\nexport interface RedisSecretConfig {\n secret: string;\n slug: string;\n fromKey: string;\n port: number;\n serviceName: string;\n containerName: string;\n volumeName: string;\n url: string;\n}\n\nexport interface SecretGroup {\n section: string;\n secrets: string[];\n}\n\ninterface DevPortState {\n host?: number;\n api?: number;\n ui?: number;\n auth?: number;\n pluginPortStart?: number;\n}\n\nexport interface PortState {\n postgresPorts: Record<string, number>;\n redisPorts: Record<string, number>;\n devPorts?: DevPortState;\n}\n\nexport interface GeneratedInfraSpec {\n groups: SecretGroup[];\n databases: DatabaseSecretConfig[];\n redis: RedisSecretConfig[];\n}\n\ninterface SyncGeneratedInfraResult {\n secrets: string[];\n envExampleChanged: boolean;\n dockerComposeChanged: boolean;\n staleEnvWarnings: string[];\n}\n\nfunction uniqueSecrets(values: Array<string | undefined>): string[] {\n const secrets: string[] = [];\n const seen = new Set<string>();\n\n for (const value of values) {\n if (!value || seen.has(value)) continue;\n seen.add(value);\n secrets.push(value);\n }\n\n return secrets;\n}\n\nexport function loadPortState(configDir?: string): PortState {\n if (!configDir) return { postgresPorts: {}, redisPorts: {} };\n const statePath = join(configDir, \".bos\", \"infra-state.json\");\n if (!existsSync(statePath)) return { postgresPorts: {}, redisPorts: {} };\n try {\n const raw = JSON.parse(readFileSync(statePath, \"utf-8\")) as Partial<PortState>;\n return {\n postgresPorts: raw.postgresPorts ?? {},\n redisPorts: raw.redisPorts ?? {},\n devPorts: raw.devPorts,\n };\n } catch {\n return { postgresPorts: {}, redisPorts: {} };\n }\n}\n\nexport function savePortState(configDir: string, state: PortState): void {\n const statePath = join(configDir, \".bos\", \"infra-state.json\");\n mkdirSync(dirname(statePath), { recursive: true });\n writeFileSync(statePath, `${JSON.stringify(state, null, 2)}\\n`);\n}\n\nexport type { DevPortState };\n\nfunction resolvePort(slug: string, portMap: Record<string, number>, basePort: number): number {\n if (portMap[slug] !== undefined) return portMap[slug];\n const assigned = Object.values(portMap);\n const maxAssigned = assigned.length > 0 ? Math.max(...assigned) : basePort - 1;\n const next = Math.max(maxAssigned + 1, basePort);\n portMap[slug] = next;\n return next;\n}\n\nexport function normalizeRedisSlug(secret: string): string {\n return secret.replace(/_REDIS_URL$/, \"\").toLowerCase();\n}\n\nexport function getSecretGroups(runtimeConfig: RuntimeConfig): SecretGroup[] {\n const groups: SecretGroup[] = [];\n const seen = new Set<string>();\n\n const addGroup = (section: string, secrets: string[]) => {\n const filtered = secrets.filter((s) => {\n if (seen.has(s)) return false;\n seen.add(s);\n return true;\n });\n if (filtered.length > 0) {\n groups.push({ section, secrets: filtered });\n }\n };\n\n addGroup(\"app.host\", uniqueSecrets([...(runtimeConfig.host.secrets ?? []), HOST_SECRET]));\n\n addGroup(\"app.api\", uniqueSecrets(runtimeConfig.api.secrets ?? []));\n\n if (runtimeConfig.auth) {\n addGroup(\"app.auth\", uniqueSecrets(runtimeConfig.auth.secrets ?? []));\n }\n\n if (runtimeConfig.plugins) {\n for (const [pluginKey, plugin] of Object.entries(runtimeConfig.plugins)) {\n if (plugin.secrets && plugin.secrets.length > 0) {\n addGroup(`plugins.${pluginKey}`, plugin.secrets);\n }\n }\n }\n\n return groups;\n}\n\nfunction buildGeneratedInfraSpec(\n runtimeConfig: RuntimeConfig,\n configDir?: string,\n): { spec: GeneratedInfraSpec; portState: PortState } {\n const groups = getSecretGroups(runtimeConfig);\n const allSecrets = groups.flatMap((group) => group.secrets);\n const originMap = configDir ? buildOriginMap(configDir, runtimeConfig) : new Map();\n const portState = loadPortState(configDir);\n\n const databases = buildDatabaseConfigs(allSecrets, originMap, portState.postgresPorts);\n const redis = buildRedisConfigs(allSecrets, originMap, portState.redisPorts);\n\n return { spec: { groups, databases, redis }, portState };\n}\n\nexport function normalizeDatabaseSlug(secret: string): string {\n return secret.replace(/_DATABASE_URL$/, \"\").toLowerCase();\n}\n\nexport function buildOriginMap(\n configDir: string,\n runtimeConfig: RuntimeConfig,\n): Map<string, string> {\n const configPath = join(configDir, \"bos.config.json\");\n\n const originMap = new Map<string, string>();\n const account = runtimeConfig.account;\n\n const resolveOrigin = (extendsRef: unknown): string | null => {\n if (typeof extendsRef === \"string\") {\n const match = extendsRef.match(/^bos:\\/\\/([^/]+)\\//);\n return match?.[1] ?? null;\n }\n return null;\n };\n\n const rawConfig = existsSync(configPath)\n ? (JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>)\n : null;\n const rawPlugins = rawConfig?.plugins as Record<string, unknown> | undefined;\n\n for (const secret of runtimeConfig.api.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, account);\n }\n\n const rawApp = rawConfig?.app as Record<string, unknown> | undefined;\n const authExtends = (rawApp?.auth as Record<string, unknown> | undefined)?.extends;\n const authOrigin = resolveOrigin(authExtends) ?? account;\n for (const secret of runtimeConfig.auth?.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, authOrigin);\n }\n\n for (const [pluginKey, pluginEntry] of Object.entries(runtimeConfig.plugins ?? {})) {\n const rawPlugin = rawPlugins?.[pluginKey];\n let pluginOrigin: string;\n if (typeof rawPlugin === \"string\") {\n pluginOrigin = resolveOrigin(rawPlugin) ?? account;\n } else if (rawPlugin && typeof rawPlugin === \"object\") {\n pluginOrigin = resolveOrigin((rawPlugin as Record<string, unknown>).extends) ?? account;\n } else {\n pluginOrigin = account;\n }\n for (const secret of pluginEntry.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, pluginOrigin);\n }\n }\n\n for (const secret of runtimeConfig.host.secrets ?? []) {\n if (!originMap.has(secret)) originMap.set(secret, account);\n }\n\n return originMap;\n}\n\nexport function buildDatabaseConfigs(\n secrets: string[],\n originMap: Map<string, string>,\n portMap: Record<string, number>,\n): DatabaseSecretConfig[] {\n const databaseSecrets = uniqueSecrets(\n secrets.filter((secret) => secret.endsWith(\"_DATABASE_URL\")),\n );\n\n const orderedSecrets = [...databaseSecrets];\n\n // Prune stale entries from removed plugins\n const currentSlugs = new Set(orderedSecrets.map(normalizeDatabaseSlug));\n for (const slug of Object.keys(portMap)) {\n if (!currentSlugs.has(slug)) delete portMap[slug];\n }\n\n // Sort by slug for deterministic assignment order\n orderedSecrets.sort((a, b) => normalizeDatabaseSlug(a).localeCompare(normalizeDatabaseSlug(b)));\n\n for (const secret of orderedSecrets) {\n const slug = normalizeDatabaseSlug(secret);\n if (secret === API_DATABASE_SECRET) {\n portMap[slug] = 5432;\n } else if (secret === AUTH_DATABASE_SECRET) {\n portMap[slug] = 5433;\n } else {\n resolvePort(slug, portMap, BASE_POSTGRES_PORT);\n }\n }\n\n return orderedSecrets.map((secret) => {\n const slug = normalizeDatabaseSlug(secret);\n const fromKey = originMap.get(secret) ?? \"\";\n const port = portMap[slug];\n\n const volumeName = fromKey\n ? `${fromKey.replace(/\\./g, \"_\")}_postgres_${slug}_data`\n : `postgres_${slug}_data`;\n\n const containerName = fromKey ? `${fromKey}-postgres-${slug}` : `postgres-${slug}`;\n\n return {\n secret,\n slug,\n fromKey,\n port,\n serviceName: `postgres-${slug.replace(/_/g, \"-\")}`,\n containerName,\n databaseName: `${slug}_db`,\n volumeName,\n url: `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${port}/${slug}_db`,\n };\n });\n}\n\nexport function buildRedisConfigs(\n secrets: string[],\n originMap: Map<string, string>,\n portMap: Record<string, number>,\n): RedisSecretConfig[] {\n const redisSecrets = uniqueSecrets(secrets.filter((secret) => secret.endsWith(\"_REDIS_URL\")));\n const orderedSecrets = [...redisSecrets];\n\n // Prune stale entries from removed plugins\n const currentSlugs = new Set(orderedSecrets.map(normalizeRedisSlug));\n for (const slug of Object.keys(portMap)) {\n if (!currentSlugs.has(slug)) delete portMap[slug];\n }\n\n // Sort by slug for deterministic assignment order\n orderedSecrets.sort((a, b) => normalizeRedisSlug(a).localeCompare(normalizeRedisSlug(b)));\n\n for (const secret of orderedSecrets) {\n const slug = normalizeRedisSlug(secret);\n resolvePort(slug, portMap, BASE_REDIS_PORT);\n }\n\n return orderedSecrets.map((secret) => {\n const slug = normalizeRedisSlug(secret);\n const fromKey = originMap.get(secret) ?? \"\";\n const port = portMap[slug];\n\n const volumeName = fromKey\n ? `${fromKey.replace(/\\./g, \"_\")}_redis_${slug}_data`\n : `redis_${slug}_data`;\n\n const containerName = fromKey ? `${fromKey}-redis-${slug}` : `redis-${slug}`;\n\n return {\n secret,\n slug,\n fromKey,\n port,\n serviceName: `redis-${slug.replace(/_/g, \"-\")}`,\n containerName,\n volumeName,\n url: `redis://localhost:${port}`,\n };\n });\n}\n\nfunction extractPortFromUrl(url: string): string | null {\n const match = url.match(/:(\\d{4,5})(?:\\/|$)/);\n return match?.[1] ?? null;\n}\n\nfunction resolveDevHostPort(runtimeConfig: RuntimeConfig): number {\n if (typeof runtimeConfig.host?.port === \"number\") return runtimeConfig.host.port;\n const fromUrl = runtimeConfig.host?.url ? extractPortFromUrl(runtimeConfig.host.url) : null;\n if (fromUrl) {\n const parsed = Number.parseInt(fromUrl, 10);\n if (!Number.isNaN(parsed)) return parsed;\n }\n return 3000;\n}\n\nfunction defaultSecretValue(\n secret: string,\n databases: Map<string, DatabaseSecretConfig>,\n redisConfigs: Map<string, RedisSecretConfig>,\n options: { forExample: boolean; devHostPort?: number },\n): string {\n if (secret === \"BETTER_AUTH_SECRET\") {\n return options.forExample ? \"\" : randomBytes(32).toString(\"base64url\");\n }\n\n if (secret === \"CORS_ORIGIN\") {\n if (typeof options.devHostPort === \"number\") {\n return `http://localhost:${options.devHostPort}`;\n }\n return \"http://localhost:3000\";\n }\n\n return databases.get(secret)?.url ?? redisConfigs.get(secret)?.url ?? \"\";\n}\n\nfunction renderEnvFile(\n groups: SecretGroup[],\n databases: DatabaseSecretConfig[],\n redisConfigs: RedisSecretConfig[],\n options: { forExample: boolean; devHostPort?: number },\n): string {\n const databaseMap = new Map(databases.map((entry) => [entry.secret, entry]));\n const redisMap = new Map(redisConfigs.map((entry) => [entry.secret, entry]));\n const lines: string[] = [\n \"# Generated from configured bos secrets\",\n \"# Update values as needed for your local environment\",\n \"\",\n ];\n\n for (const group of groups) {\n lines.push(`# ${group.section}`);\n for (const secret of group.secrets) {\n lines.push(`${secret}=${defaultSecretValue(secret, databaseMap, redisMap, options)}`);\n }\n lines.push(\"\");\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction renderDockerCompose(\n databases: DatabaseSecretConfig[],\n redisConfigs: RedisSecretConfig[],\n projectName: string,\n): string {\n const lines = [`name: ${projectName}`, \"\"];\n\n if (databases.length > 0) {\n lines.push(\n \"x-pg-common: &pg-common\",\n \" image: postgres:17-alpine\",\n \" environment: &pg-env\",\n ` POSTGRES_USER: ${POSTGRES_USER}`,\n ` POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}`,\n \" healthcheck:\",\n ' test: [\"CMD-SHELL\", \"pg_isready -U everythingdev\"]',\n \" interval: 3s\",\n \" timeout: 3s\",\n \" retries: 5\",\n \"\",\n );\n }\n\n if (redisConfigs.length > 0) {\n lines.push(\n \"x-redis-common: &redis-common\",\n \" image: redis:7-alpine\",\n \" command: redis-server --appendonly yes\",\n \" healthcheck:\",\n ' test: [\"CMD\", \"redis-cli\", \"ping\"]',\n \" interval: 3s\",\n \" timeout: 3s\",\n \" retries: 5\",\n \"\",\n );\n }\n\n lines.push(\"services:\");\n\n for (const database of databases) {\n lines.push(` ${database.serviceName}:`);\n lines.push(\" <<: *pg-common\");\n lines.push(` container_name: ${database.containerName}`);\n lines.push(\" environment:\");\n lines.push(\" <<: *pg-env\");\n lines.push(` POSTGRES_DB: ${database.databaseName}`);\n lines.push(\" ports:\");\n lines.push(` - \"${database.port}:5432\"`);\n lines.push(\" volumes:\");\n lines.push(` - ${database.volumeName}:/var/lib/postgresql/data`);\n lines.push(\"\");\n }\n\n for (const redis of redisConfigs) {\n lines.push(` ${redis.serviceName}:`);\n lines.push(\" <<: *redis-common\");\n lines.push(` container_name: ${redis.containerName}`);\n lines.push(\" ports:\");\n lines.push(` - \"${redis.port}:6379\"`);\n lines.push(\" volumes:\");\n lines.push(` - ${redis.volumeName}:/data`);\n lines.push(\"\");\n }\n\n lines.push(\"volumes:\");\n for (const database of databases) {\n lines.push(` ${database.volumeName}:`);\n lines.push(` name: ${database.volumeName}`);\n }\n for (const redis of redisConfigs) {\n lines.push(` ${redis.volumeName}:`);\n lines.push(` name: ${redis.volumeName}`);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function renderEnvFileFromPlan(env: Record<string, string>, devHostPort?: number): string {\n const lines: string[] = [\n \"# Generated from bos dev infra plan\",\n \"# Update values as needed for your local environment\",\n \"\",\n ];\n const sortedKeys = Object.keys(env).sort();\n for (const key of sortedKeys) {\n let value = env[key];\n if (key === \"CORS_ORIGIN\" && devHostPort && !value) {\n value = `http://localhost:${devHostPort}`;\n }\n lines.push(`${key}=${value}`);\n }\n lines.push(\"\");\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function renderDockerComposeFromPlan(\n databases: {\n serviceName: string;\n containerName: string;\n port: number;\n volumeName: string;\n databaseName: string;\n }[],\n redis: { serviceName: string; containerName: string; port: number; volumeName: string }[],\n projectName: string,\n): string {\n const lines = [`name: ${projectName}`, \"\"];\n\n if (databases.length > 0) {\n lines.push(\n \"x-pg-common: &pg-common\",\n \" image: postgres:17-alpine\",\n \" environment: &pg-env\",\n ` POSTGRES_USER: ${POSTGRES_USER}`,\n ` POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}`,\n \" healthcheck:\",\n ' test: [\"CMD-SHELL\", \"pg_isready -U everythingdev\"]',\n \" interval: 3s\",\n \" timeout: 3s\",\n \" retries: 5\",\n \"\",\n );\n }\n\n if (redis.length > 0) {\n lines.push(\n \"x-redis-common: &redis-common\",\n \" image: redis:7-alpine\",\n \" command: redis-server --appendonly yes\",\n \" healthcheck:\",\n ' test: [\"CMD\", \"redis-cli\", \"ping\"]',\n \" interval: 3s\",\n \" timeout: 3s\",\n \" retries: 5\",\n \"\",\n );\n }\n\n lines.push(\"services:\");\n\n for (const db of databases) {\n lines.push(` ${db.serviceName}:`);\n lines.push(\" <<: *pg-common\");\n lines.push(` container_name: ${db.containerName}`);\n lines.push(\" environment:\");\n lines.push(\" <<: *pg-env\");\n lines.push(` POSTGRES_DB: ${db.databaseName}`);\n lines.push(\" ports:\");\n lines.push(` - \"${db.port}:5432\"`);\n lines.push(\" volumes:\");\n lines.push(` - ${db.volumeName}:/var/lib/postgresql/data`);\n lines.push(\"\");\n }\n\n for (const r of redis) {\n lines.push(` ${r.serviceName}:`);\n lines.push(\" <<: *redis-common\");\n lines.push(` container_name: ${r.containerName}`);\n lines.push(\" ports:\");\n lines.push(` - \"${r.port}:6379\"`);\n lines.push(\" volumes:\");\n lines.push(` - ${r.volumeName}:/data`);\n lines.push(\"\");\n }\n\n lines.push(\"volumes:\");\n for (const db of databases) {\n lines.push(` ${db.volumeName}:`);\n lines.push(` name: ${db.volumeName}`);\n }\n for (const r of redis) {\n lines.push(` ${r.volumeName}:`);\n lines.push(` name: ${r.volumeName}`);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function materializeInfraPlan(\n configDir: string,\n planEnv: Record<string, string>,\n planDatabases: {\n serviceName: string;\n containerName: string;\n port: number;\n volumeName: string;\n databaseName: string;\n }[],\n planRedis: { serviceName: string; containerName: string; port: number; volumeName: string }[],\n projectName: string,\n devHostPort?: number,\n): { envExampleChanged: boolean; dockerComposeChanged: boolean } {\n const envContent = renderEnvFileFromPlan(planEnv, devHostPort);\n const dockerContent = renderDockerComposeFromPlan(planDatabases, planRedis, projectName);\n\n const envExamplePath = join(configDir, \".env.example\");\n const dockerComposePath = join(configDir, \"docker-compose.yml\");\n\n return {\n envExampleChanged: syncTextFile(envExamplePath, envContent),\n dockerComposeChanged: syncTextFile(dockerComposePath, dockerContent),\n };\n}\n\nfunction syncTextFile(filePath: string, nextContent: string): boolean {\n if (existsSync(filePath) && readFileSync(filePath, \"utf-8\") === nextContent) {\n return false;\n }\n\n writeFileSync(filePath, nextContent);\n return true;\n}\n\nexport function writeGeneratedInfra(configDir: string, runtimeConfig: RuntimeConfig): string[] {\n const result = syncGeneratedInfra(configDir, runtimeConfig);\n\n if (result.staleEnvWarnings.length > 0) {\n p.log.warn(\n `.env has ${result.staleEnvWarnings.length} stale value(s) compared to .env.example:`,\n );\n for (const warning of result.staleEnvWarnings) {\n p.log.message(` ${warning}`);\n }\n }\n\n return result.secrets;\n}\n\nexport function syncGeneratedInfra(\n configDir: string,\n runtimeConfig: RuntimeConfig,\n): SyncGeneratedInfraResult {\n const { spec, portState } = buildGeneratedInfraSpec(runtimeConfig, configDir);\n const secrets = spec.groups.flatMap((group) => group.secrets);\n const envOptions: { forExample: true; devHostPort?: number } = { forExample: true };\n if (runtimeConfig.env === \"development\") {\n envOptions.devHostPort = resolveDevHostPort(runtimeConfig);\n }\n const newEnvContent = renderEnvFile(spec.groups, spec.databases, spec.redis, envOptions);\n const newDockerContent = renderDockerCompose(spec.databases, spec.redis, runtimeConfig.account);\n\n const envExamplePath = join(configDir, \".env.example\");\n const dockerComposePath = join(configDir, \"docker-compose.yml\");\n\n const staleWarnings = checkEnvStaleness(configDir, spec.databases, spec.redis);\n\n if (configDir) {\n savePortState(configDir, portState);\n }\n\n return {\n secrets,\n envExampleChanged: syncTextFile(envExamplePath, newEnvContent),\n dockerComposeChanged: syncTextFile(dockerComposePath, newDockerContent),\n staleEnvWarnings: staleWarnings,\n };\n}\n\nfunction checkEnvStaleness(\n configDir: string,\n databases: DatabaseSecretConfig[],\n redisConfigs: RedisSecretConfig[],\n): string[] {\n const envPath = join(configDir, \".env\");\n if (!existsSync(envPath)) return [];\n\n const existingEnv = readFileSync(envPath, \"utf-8\");\n const envMap = new Map<string, string>();\n for (const line of existingEnv.split(\"\\n\")) {\n const match = line.match(/^([A-Z_]+)=(.*)$/);\n if (match) envMap.set(match[1], match[2]);\n }\n\n const stale: string[] = [];\n\n for (const db of databases) {\n const existing = envMap.get(db.secret);\n if (existing && existing !== db.url) {\n const oldPort = extractPortFromUrl(existing) ?? \"?\";\n stale.push(`${db.secret}: port ${oldPort} → ${db.port}`);\n }\n }\n\n for (const redis of redisConfigs) {\n const existing = envMap.get(redis.secret);\n if (existing && existing !== redis.url) {\n const oldPort = extractPortFromUrl(existing) ?? \"?\";\n stale.push(`${redis.secret}: port ${oldPort} → ${redis.port}`);\n }\n }\n\n return stale;\n}\n\nexport function ensureEnvFile(configDir: string): void {\n const envPath = join(configDir, \".env\");\n const examplePath = join(configDir, \".env.example\");\n\n if (existsSync(envPath) || !existsSync(examplePath)) return;\n\n const content = readFileSync(examplePath, \"utf-8\");\n const lines = content.split(\"\\n\");\n const secret = randomBytes(32).toString(\"base64url\");\n const updated = lines\n .map((line) => {\n if (/^BETTER_AUTH_SECRET=/.test(line)) {\n return `BETTER_AUTH_SECRET=${secret}`;\n }\n return line;\n })\n .join(\"\\n\");\n\n writeFileSync(envPath, updated);\n p.log.info(\"Created .env from generated .env.example with generated BETTER_AUTH_SECRET\");\n}\n\nlet envLoadedDir: string | null = null;\n\nexport function loadProjectEnv(configDir: string): void {\n if (envLoadedDir === configDir) return;\n const envPath = join(configDir, \".env\");\n if (!existsSync(envPath)) return;\n\n loadDotenv({ path: envPath, processEnv: process.env, quiet: true });\n envLoadedDir = configDir;\n}\n"],"mappings":";;;;;;;AAOA,MAAM,gBAAgB;AACtB,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;AAC7B,MAAM,cAAc;AACpB,MAAM,qBAAqB;AAC3B,MAAM,kBAAkB;AAyDxB,SAAS,cAAc,QAA6C;CAClE,MAAM,UAAoB,CAAC;CAC3B,MAAM,uBAAO,IAAI,IAAY;CAE7B,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,CAAC,SAAS,KAAK,IAAI,KAAK,GAAG;EAC/B,KAAK,IAAI,KAAK;EACd,QAAQ,KAAK,KAAK;CACpB;CAEA,OAAO;AACT;AAEA,SAAgB,cAAc,WAA+B;CAC3D,IAAI,CAAC,WAAW,OAAO;EAAE,eAAe,CAAC;EAAG,YAAY,CAAC;CAAE;CAC3D,MAAM,YAAY,KAAK,WAAW,QAAQ,kBAAkB;CAC5D,IAAI,CAAC,WAAW,SAAS,GAAG,OAAO;EAAE,eAAe,CAAC;EAAG,YAAY,CAAC;CAAE;CACvE,IAAI;EACF,MAAM,MAAM,KAAK,MAAM,aAAa,WAAW,OAAO,CAAC;EACvD,OAAO;GACL,eAAe,IAAI,iBAAiB,CAAC;GACrC,YAAY,IAAI,cAAc,CAAC;GAC/B,UAAU,IAAI;EAChB;CACF,QAAQ;EACN,OAAO;GAAE,eAAe,CAAC;GAAG,YAAY,CAAC;EAAE;CAC7C;AACF;AAEA,SAAgB,cAAc,WAAmB,OAAwB;CACvE,MAAM,YAAY,KAAK,WAAW,QAAQ,kBAAkB;CAC5D,UAAU,QAAQ,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;CACjD,cAAc,WAAW,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,GAAG;AAChE;AAIA,SAAS,YAAY,MAAc,SAAiC,UAA0B;CAC5F,IAAI,QAAQ,UAAU,QAAW,OAAO,QAAQ;CAChD,MAAM,WAAW,OAAO,OAAO,OAAO;CACtC,MAAM,cAAc,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,QAAQ,IAAI,WAAW;CAC7E,MAAM,OAAO,KAAK,IAAI,cAAc,GAAG,QAAQ;CAC/C,QAAQ,QAAQ;CAChB,OAAO;AACT;AAEA,SAAgB,mBAAmB,QAAwB;CACzD,OAAO,OAAO,QAAQ,eAAe,EAAE,CAAC,CAAC,YAAY;AACvD;AAEA,SAAgB,gBAAgB,eAA6C;CAC3E,MAAM,SAAwB,CAAC;CAC/B,MAAM,uBAAO,IAAI,IAAY;CAE7B,MAAM,YAAY,SAAiB,YAAsB;EACvD,MAAM,WAAW,QAAQ,QAAQ,MAAM;GACrC,IAAI,KAAK,IAAI,CAAC,GAAG,OAAO;GACxB,KAAK,IAAI,CAAC;GACV,OAAO;EACT,CAAC;EACD,IAAI,SAAS,SAAS,GACpB,OAAO,KAAK;GAAE;GAAS,SAAS;EAAS,CAAC;CAE9C;CAEA,SAAS,YAAY,cAAc,CAAC,GAAI,cAAc,KAAK,WAAW,CAAC,GAAI,WAAW,CAAC,CAAC;CAExF,SAAS,WAAW,cAAc,cAAc,IAAI,WAAW,CAAC,CAAC,CAAC;CAElE,IAAI,cAAc,MAChB,SAAS,YAAY,cAAc,cAAc,KAAK,WAAW,CAAC,CAAC,CAAC;CAGtE,IAAI,cAAc,SAChB;OAAK,MAAM,CAAC,WAAW,WAAW,OAAO,QAAQ,cAAc,OAAO,GACpE,IAAI,OAAO,WAAW,OAAO,QAAQ,SAAS,GAC5C,SAAS,WAAW,aAAa,OAAO,OAAO;CAEnD;CAGF,OAAO;AACT;AAEA,SAAS,wBACP,eACA,WACoD;CACpD,MAAM,SAAS,gBAAgB,aAAa;CAC5C,MAAM,aAAa,OAAO,SAAS,UAAU,MAAM,OAAO;CAC1D,MAAM,YAAY,YAAY,eAAe,WAAW,aAAa,oBAAI,IAAI,IAAI;CACjF,MAAM,YAAY,cAAc,SAAS;CAKzC,OAAO;EAAE,MAAM;GAAE;GAAQ,WAHP,qBAAqB,YAAY,WAAW,UAAU,aAGvC;GAAG,OAFtB,kBAAkB,YAAY,WAAW,UAAU,UAEzB;EAAE;EAAG;CAAU;AACzD;AAEA,SAAgB,sBAAsB,QAAwB;CAC5D,OAAO,OAAO,QAAQ,kBAAkB,EAAE,CAAC,CAAC,YAAY;AAC1D;AAEA,SAAgB,eACd,WACA,eACqB;CACrB,MAAM,aAAa,KAAK,WAAW,iBAAiB;CAEpD,MAAM,4BAAY,IAAI,IAAoB;CAC1C,MAAM,UAAU,cAAc;CAE9B,MAAM,iBAAiB,eAAuC;EAC5D,IAAI,OAAO,eAAe,UAExB,OADc,WAAW,MAAM,oBACpB,CAAC,GAAG,MAAM;EAEvB,OAAO;CACT;CAEA,MAAM,YAAY,WAAW,UAAU,IAClC,KAAK,MAAM,aAAa,YAAY,OAAO,CAAC,IAC7C;CACJ,MAAM,aAAa,WAAW;CAE9B,KAAK,MAAM,UAAU,cAAc,IAAI,WAAW,CAAC,GACjD,IAAI,CAAC,UAAU,IAAI,MAAM,GAAG,UAAU,IAAI,QAAQ,OAAO;CAI3D,MAAM,gBADS,WAAW,IACC,EAAE,KAAI,EAA0C;CAC3E,MAAM,aAAa,cAAc,WAAW,KAAK;CACjD,KAAK,MAAM,UAAU,cAAc,MAAM,WAAW,CAAC,GACnD,IAAI,CAAC,UAAU,IAAI,MAAM,GAAG,UAAU,IAAI,QAAQ,UAAU;CAG9D,KAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,cAAc,WAAW,CAAC,CAAC,GAAG;EAClF,MAAM,YAAY,aAAa;EAC/B,IAAI;EACJ,IAAI,OAAO,cAAc,UACvB,eAAe,cAAc,SAAS,KAAK;OACtC,IAAI,aAAa,OAAO,cAAc,UAC3C,eAAe,cAAe,UAAsC,OAAO,KAAK;OAEhF,eAAe;EAEjB,KAAK,MAAM,UAAU,YAAY,WAAW,CAAC,GAC3C,IAAI,CAAC,UAAU,IAAI,MAAM,GAAG,UAAU,IAAI,QAAQ,YAAY;CAElE;CAEA,KAAK,MAAM,UAAU,cAAc,KAAK,WAAW,CAAC,GAClD,IAAI,CAAC,UAAU,IAAI,MAAM,GAAG,UAAU,IAAI,QAAQ,OAAO;CAG3D,OAAO;AACT;AAEA,SAAgB,qBACd,SACA,WACA,SACwB;CAKxB,MAAM,iBAAiB,CAAC,GAJA,cACtB,QAAQ,QAAQ,WAAW,OAAO,SAAS,eAAe,CAAC,CAGpB,CAAC;CAG1C,MAAM,eAAe,IAAI,IAAI,eAAe,IAAI,qBAAqB,CAAC;CACtE,KAAK,MAAM,QAAQ,OAAO,KAAK,OAAO,GACpC,IAAI,CAAC,aAAa,IAAI,IAAI,GAAG,OAAO,QAAQ;CAI9C,eAAe,MAAM,GAAG,MAAM,sBAAsB,CAAC,CAAC,CAAC,cAAc,sBAAsB,CAAC,CAAC,CAAC;CAE9F,KAAK,MAAM,UAAU,gBAAgB;EACnC,MAAM,OAAO,sBAAsB,MAAM;EACzC,IAAI,WAAW,qBACb,QAAQ,QAAQ;OACX,IAAI,WAAW,sBACpB,QAAQ,QAAQ;OAEhB,YAAY,MAAM,SAAS,kBAAkB;CAEjD;CAEA,OAAO,eAAe,KAAK,WAAW;EACpC,MAAM,OAAO,sBAAsB,MAAM;EACzC,MAAM,UAAU,UAAU,IAAI,MAAM,KAAK;EACzC,MAAM,OAAO,QAAQ;EAErB,MAAM,aAAa,UACf,GAAG,QAAQ,QAAQ,OAAO,GAAG,EAAE,YAAY,KAAK,SAChD,YAAY,KAAK;EAErB,MAAM,gBAAgB,UAAU,GAAG,QAAQ,YAAY,SAAS,YAAY;EAE5E,OAAO;GACL;GACA;GACA;GACA;GACA,aAAa,YAAY,KAAK,QAAQ,MAAM,GAAG;GAC/C;GACA,cAAc,GAAG,KAAK;GACtB;GACA,KAAK,cAAc,cAAc,GAAG,kBAAkB,aAAa,KAAK,GAAG,KAAK;EAClF;CACF,CAAC;AACH;AAEA,SAAgB,kBACd,SACA,WACA,SACqB;CAErB,MAAM,iBAAiB,CAAC,GADH,cAAc,QAAQ,QAAQ,WAAW,OAAO,SAAS,YAAY,CAAC,CACrD,CAAC;CAGvC,MAAM,eAAe,IAAI,IAAI,eAAe,IAAI,kBAAkB,CAAC;CACnE,KAAK,MAAM,QAAQ,OAAO,KAAK,OAAO,GACpC,IAAI,CAAC,aAAa,IAAI,IAAI,GAAG,OAAO,QAAQ;CAI9C,eAAe,MAAM,GAAG,MAAM,mBAAmB,CAAC,CAAC,CAAC,cAAc,mBAAmB,CAAC,CAAC,CAAC;CAExF,KAAK,MAAM,UAAU,gBAEnB,YADa,mBAAmB,MACjB,GAAG,SAAS,eAAe;CAG5C,OAAO,eAAe,KAAK,WAAW;EACpC,MAAM,OAAO,mBAAmB,MAAM;EACtC,MAAM,UAAU,UAAU,IAAI,MAAM,KAAK;EACzC,MAAM,OAAO,QAAQ;EAErB,MAAM,aAAa,UACf,GAAG,QAAQ,QAAQ,OAAO,GAAG,EAAE,SAAS,KAAK,SAC7C,SAAS,KAAK;EAElB,MAAM,gBAAgB,UAAU,GAAG,QAAQ,SAAS,SAAS,SAAS;EAEtE,OAAO;GACL;GACA;GACA;GACA;GACA,aAAa,SAAS,KAAK,QAAQ,MAAM,GAAG;GAC5C;GACA;GACA,KAAK,qBAAqB;EAC5B;CACF,CAAC;AACH;AAEA,SAAS,mBAAmB,KAA4B;CAEtD,OADc,IAAI,MAAM,oBACb,CAAC,GAAG,MAAM;AACvB;AAEA,SAAS,mBAAmB,eAAsC;CAChE,IAAI,OAAO,cAAc,MAAM,SAAS,UAAU,OAAO,cAAc,KAAK;CAC5E,MAAM,UAAU,cAAc,MAAM,MAAM,mBAAmB,cAAc,KAAK,GAAG,IAAI;CACvF,IAAI,SAAS;EACX,MAAM,SAAS,OAAO,SAAS,SAAS,EAAE;EAC1C,IAAI,CAAC,OAAO,MAAM,MAAM,GAAG,OAAO;CACpC;CACA,OAAO;AACT;AAEA,SAAS,mBACP,QACA,WACA,cACA,SACQ;CACR,IAAI,WAAW,sBACb,OAAO,QAAQ,aAAa,KAAK,YAAY,EAAE,CAAC,CAAC,SAAS,WAAW;CAGvE,IAAI,WAAW,eAAe;EAC5B,IAAI,OAAO,QAAQ,gBAAgB,UACjC,OAAO,oBAAoB,QAAQ;EAErC,OAAO;CACT;CAEA,OAAO,UAAU,IAAI,MAAM,CAAC,EAAE,OAAO,aAAa,IAAI,MAAM,CAAC,EAAE,OAAO;AACxE;AAEA,SAAS,cACP,QACA,WACA,cACA,SACQ;CACR,MAAM,cAAc,IAAI,IAAI,UAAU,KAAK,UAAU,CAAC,MAAM,QAAQ,KAAK,CAAC,CAAC;CAC3E,MAAM,WAAW,IAAI,IAAI,aAAa,KAAK,UAAU,CAAC,MAAM,QAAQ,KAAK,CAAC,CAAC;CAC3E,MAAM,QAAkB;EACtB;EACA;EACA;CACF;CAEA,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,KAAK,KAAK,MAAM,SAAS;EAC/B,KAAK,MAAM,UAAU,MAAM,SACzB,MAAM,KAAK,GAAG,OAAO,GAAG,mBAAmB,QAAQ,aAAa,UAAU,OAAO,GAAG;EAEtF,MAAM,KAAK,EAAE;CACf;CAEA,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC7B;AAEA,SAAS,oBACP,WACA,cACA,aACQ;CACR,MAAM,QAAQ,CAAC,SAAS,eAAe,EAAE;CAEzC,IAAI,UAAU,SAAS,GACrB,MAAM,KACJ,2BACA,+BACA,0BACA,sBAAsB,iBACtB,0BAA0B,qBAC1B,kBACA,8DACA,oBACA,mBACA,kBACA,EACF;CAGF,IAAI,aAAa,SAAS,GACxB,MAAM,KACJ,iCACA,2BACA,4CACA,kBACA,gDACA,oBACA,mBACA,kBACA,EACF;CAGF,MAAM,KAAK,WAAW;CAEtB,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,KAAK,KAAK,SAAS,YAAY,EAAE;EACvC,MAAM,KAAK,oBAAoB;EAC/B,MAAM,KAAK,uBAAuB,SAAS,eAAe;EAC1D,MAAM,KAAK,kBAAkB;EAC7B,MAAM,KAAK,mBAAmB;EAC9B,MAAM,KAAK,sBAAsB,SAAS,cAAc;EACxD,MAAM,KAAK,YAAY;EACvB,MAAM,KAAK,YAAY,SAAS,KAAK,OAAO;EAC5C,MAAM,KAAK,cAAc;EACzB,MAAM,KAAK,WAAW,SAAS,WAAW,0BAA0B;EACpE,MAAM,KAAK,EAAE;CACf;CAEA,KAAK,MAAM,SAAS,cAAc;EAChC,MAAM,KAAK,KAAK,MAAM,YAAY,EAAE;EACpC,MAAM,KAAK,uBAAuB;EAClC,MAAM,KAAK,uBAAuB,MAAM,eAAe;EACvD,MAAM,KAAK,YAAY;EACvB,MAAM,KAAK,YAAY,MAAM,KAAK,OAAO;EACzC,MAAM,KAAK,cAAc;EACzB,MAAM,KAAK,WAAW,MAAM,WAAW,OAAO;EAC9C,MAAM,KAAK,EAAE;CACf;CAEA,MAAM,KAAK,UAAU;CACrB,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,KAAK,KAAK,SAAS,WAAW,EAAE;EACtC,MAAM,KAAK,aAAa,SAAS,YAAY;CAC/C;CACA,KAAK,MAAM,SAAS,cAAc;EAChC,MAAM,KAAK,KAAK,MAAM,WAAW,EAAE;EACnC,MAAM,KAAK,aAAa,MAAM,YAAY;CAC5C;CAEA,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC7B;AAEA,SAAgB,sBAAsB,KAA6B,aAA8B;CAC/F,MAAM,QAAkB;EACtB;EACA;EACA;CACF;CACA,MAAM,aAAa,OAAO,KAAK,GAAG,CAAC,CAAC,KAAK;CACzC,KAAK,MAAM,OAAO,YAAY;EAC5B,IAAI,QAAQ,IAAI;EAChB,IAAI,QAAQ,iBAAiB,eAAe,CAAC,OAC3C,QAAQ,oBAAoB;EAE9B,MAAM,KAAK,GAAG,IAAI,GAAG,OAAO;CAC9B;CACA,MAAM,KAAK,EAAE;CACb,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC7B;AAEA,SAAgB,4BACd,WAOA,OACA,aACQ;CACR,MAAM,QAAQ,CAAC,SAAS,eAAe,EAAE;CAEzC,IAAI,UAAU,SAAS,GACrB,MAAM,KACJ,2BACA,+BACA,0BACA,sBAAsB,iBACtB,0BAA0B,qBAC1B,kBACA,8DACA,oBACA,mBACA,kBACA,EACF;CAGF,IAAI,MAAM,SAAS,GACjB,MAAM,KACJ,iCACA,2BACA,4CACA,kBACA,gDACA,oBACA,mBACA,kBACA,EACF;CAGF,MAAM,KAAK,WAAW;CAEtB,KAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,KAAK,KAAK,GAAG,YAAY,EAAE;EACjC,MAAM,KAAK,oBAAoB;EAC/B,MAAM,KAAK,uBAAuB,GAAG,eAAe;EACpD,MAAM,KAAK,kBAAkB;EAC7B,MAAM,KAAK,mBAAmB;EAC9B,MAAM,KAAK,sBAAsB,GAAG,cAAc;EAClD,MAAM,KAAK,YAAY;EACvB,MAAM,KAAK,YAAY,GAAG,KAAK,OAAO;EACtC,MAAM,KAAK,cAAc;EACzB,MAAM,KAAK,WAAW,GAAG,WAAW,0BAA0B;EAC9D,MAAM,KAAK,EAAE;CACf;CAEA,KAAK,MAAM,KAAK,OAAO;EACrB,MAAM,KAAK,KAAK,EAAE,YAAY,EAAE;EAChC,MAAM,KAAK,uBAAuB;EAClC,MAAM,KAAK,uBAAuB,EAAE,eAAe;EACnD,MAAM,KAAK,YAAY;EACvB,MAAM,KAAK,YAAY,EAAE,KAAK,OAAO;EACrC,MAAM,KAAK,cAAc;EACzB,MAAM,KAAK,WAAW,EAAE,WAAW,OAAO;EAC1C,MAAM,KAAK,EAAE;CACf;CAEA,MAAM,KAAK,UAAU;CACrB,KAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,KAAK,KAAK,GAAG,WAAW,EAAE;EAChC,MAAM,KAAK,aAAa,GAAG,YAAY;CACzC;CACA,KAAK,MAAM,KAAK,OAAO;EACrB,MAAM,KAAK,KAAK,EAAE,WAAW,EAAE;EAC/B,MAAM,KAAK,aAAa,EAAE,YAAY;CACxC;CAEA,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC7B;AAEA,SAAgB,qBACd,WACA,SACA,eAOA,WACA,aACA,aAC+D;CAC/D,MAAM,aAAa,sBAAsB,SAAS,WAAW;CAC7D,MAAM,gBAAgB,4BAA4B,eAAe,WAAW,WAAW;CAEvF,MAAM,iBAAiB,KAAK,WAAW,cAAc;CACrD,MAAM,oBAAoB,KAAK,WAAW,oBAAoB;CAE9D,OAAO;EACL,mBAAmB,aAAa,gBAAgB,UAAU;EAC1D,sBAAsB,aAAa,mBAAmB,aAAa;CACrE;AACF;AAEA,SAAS,aAAa,UAAkB,aAA8B;CACpE,IAAI,WAAW,QAAQ,KAAK,aAAa,UAAU,OAAO,MAAM,aAC9D,OAAO;CAGT,cAAc,UAAU,WAAW;CACnC,OAAO;AACT;AAEA,SAAgB,oBAAoB,WAAmB,eAAwC;CAC7F,MAAM,SAAS,mBAAmB,WAAW,aAAa;CAE1D,IAAI,OAAO,iBAAiB,SAAS,GAAG;EACtC,EAAE,IAAI,KACJ,YAAY,OAAO,iBAAiB,OAAO,0CAC7C;EACA,KAAK,MAAM,WAAW,OAAO,kBAC3B,EAAE,IAAI,QAAQ,KAAK,SAAS;CAEhC;CAEA,OAAO,OAAO;AAChB;AAEA,SAAgB,mBACd,WACA,eAC0B;CAC1B,MAAM,EAAE,MAAM,cAAc,wBAAwB,eAAe,SAAS;CAC5E,MAAM,UAAU,KAAK,OAAO,SAAS,UAAU,MAAM,OAAO;CAC5D,MAAM,aAAyD,EAAE,YAAY,KAAK;CAClF,IAAI,cAAc,QAAQ,eACxB,WAAW,cAAc,mBAAmB,aAAa;CAE3D,MAAM,gBAAgB,cAAc,KAAK,QAAQ,KAAK,WAAW,KAAK,OAAO,UAAU;CACvF,MAAM,mBAAmB,oBAAoB,KAAK,WAAW,KAAK,OAAO,cAAc,OAAO;CAE9F,MAAM,iBAAiB,KAAK,WAAW,cAAc;CACrD,MAAM,oBAAoB,KAAK,WAAW,oBAAoB;CAE9D,MAAM,gBAAgB,kBAAkB,WAAW,KAAK,WAAW,KAAK,KAAK;CAE7E,IAAI,WACF,cAAc,WAAW,SAAS;CAGpC,OAAO;EACL;EACA,mBAAmB,aAAa,gBAAgB,aAAa;EAC7D,sBAAsB,aAAa,mBAAmB,gBAAgB;EACtE,kBAAkB;CACpB;AACF;AAEA,SAAS,kBACP,WACA,WACA,cACU;CACV,MAAM,UAAU,KAAK,WAAW,MAAM;CACtC,IAAI,CAAC,WAAW,OAAO,GAAG,OAAO,CAAC;CAElC,MAAM,cAAc,aAAa,SAAS,OAAO;CACjD,MAAM,yBAAS,IAAI,IAAoB;CACvC,KAAK,MAAM,QAAQ,YAAY,MAAM,IAAI,GAAG;EAC1C,MAAM,QAAQ,KAAK,MAAM,kBAAkB;EAC3C,IAAI,OAAO,OAAO,IAAI,MAAM,IAAI,MAAM,EAAE;CAC1C;CAEA,MAAM,QAAkB,CAAC;CAEzB,KAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,WAAW,OAAO,IAAI,GAAG,MAAM;EACrC,IAAI,YAAY,aAAa,GAAG,KAAK;GACnC,MAAM,UAAU,mBAAmB,QAAQ,KAAK;GAChD,MAAM,KAAK,GAAG,GAAG,OAAO,SAAS,QAAQ,KAAK,GAAG,MAAM;EACzD;CACF;CAEA,KAAK,MAAM,SAAS,cAAc;EAChC,MAAM,WAAW,OAAO,IAAI,MAAM,MAAM;EACxC,IAAI,YAAY,aAAa,MAAM,KAAK;GACtC,MAAM,UAAU,mBAAmB,QAAQ,KAAK;GAChD,MAAM,KAAK,GAAG,MAAM,OAAO,SAAS,QAAQ,KAAK,MAAM,MAAM;EAC/D;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,cAAc,WAAyB;CACrD,MAAM,UAAU,KAAK,WAAW,MAAM;CACtC,MAAM,cAAc,KAAK,WAAW,cAAc;CAElD,IAAI,WAAW,OAAO,KAAK,CAAC,WAAW,WAAW,GAAG;CAGrD,MAAM,QADU,aAAa,aAAa,OACtB,CAAC,CAAC,MAAM,IAAI;CAChC,MAAM,SAAS,YAAY,EAAE,CAAC,CAAC,SAAS,WAAW;CAUnD,cAAc,SATE,MACb,KAAK,SAAS;EACb,IAAI,uBAAuB,KAAK,IAAI,GAClC,OAAO,sBAAsB;EAE/B,OAAO;CACT,CAAC,CAAC,CACD,KAAK,IAEqB,CAAC;CAC9B,EAAE,IAAI,KAAK,4EAA4E;AACzF;AAEA,IAAI,eAA8B;AAElC,SAAgB,eAAe,WAAyB;CACtD,IAAI,iBAAiB,WAAW;CAChC,MAAM,UAAU,KAAK,WAAW,MAAM;CACtC,IAAI,CAAC,WAAW,OAAO,GAAG;CAE1B,OAAW;EAAE,MAAM;EAAS,YAAY,QAAQ;EAAK,OAAO;CAAK,CAAC;CAClE,eAAe;AACjB"}