@dennisrepa/elevate 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/chunk-4YCMSRA6.js +5817 -0
- package/dist/chunk-4YCMSRA6.js.map +1 -0
- package/dist/cli.js +136 -3604
- package/dist/cli.js.map +1 -1
- package/dist/config-DRANL4H4.js +13 -0
- package/dist/config-DRANL4H4.js.map +1 -0
- package/docs/de.md +104 -24
- package/docs/en.md +104 -24
- package/package.json +3 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/domain/version-policy.ts","../src/domain/versions.ts","../src/adapters/npm/npm-package-manager.ts","../src/adapters/shared/checkout.ts","../src/adapters/shared/process.ts","../src/adapters/npm/npm-discovery.ts","../src/adapters/npm/pnpm-workspace.ts","../src/adapters/npm/npm-registry.ts","../src/domain/origin.ts","../src/adapters/npm/npm-commands.ts","../src/adapters/npm/npm-config.ts","../src/adapters/npm/npm-scanner.ts","../src/adapters/shared/pool.ts","../src/adapters/npm/npm-protocols.ts","../src/adapters/npm/npm-updater.ts","../src/domain/ports.ts","../src/adapters/npm/npm-lockfile.ts","../src/adapters/npm/pnpm-audit.ts","../src/adapters/npm/pnpm-lockfile.ts","../src/adapters/npm/npm-verifier.ts","../src/adapters/npm/npm-strategy.ts","../src/adapters/cargo/cargo-strategy.ts","../src/adapters/cargo/cargo-discovery.ts","../src/adapters/cargo/cargo-command.ts","../src/adapters/cargo/cargo-metadata.ts","../src/adapters/cargo/cargo-config.ts","../src/version.ts","../src/adapters/cargo/cargo-index.ts","../src/adapters/cargo/cargo-registry.ts","../src/adapters/cargo/cargo-versions.ts","../src/adapters/cargo/cargo-requirement.ts","../src/adapters/cargo/cargo-scanner.ts","../src/adapters/cargo/cargo-toml.ts","../src/adapters/cargo/cargo-lockfile.ts","../src/adapters/cargo/cargo-updater.ts","../src/adapters/shared/xml.ts","../src/adapters/shared/text-edit.ts","../src/adapters/cargo/cargo-verifier.ts","../src/adapters/maven/maven-discovery.ts","../src/adapters/maven/maven-project.ts","../src/adapters/maven/maven-pom.ts","../src/adapters/maven/maven-registry.ts","../src/adapters/maven/maven-command.ts","../src/adapters/maven/maven-resolution.ts","../src/adapters/maven/maven-scanner.ts","../src/adapters/maven/maven-locator.ts","../src/adapters/maven/maven-updater.ts","../src/adapters/maven/maven-verifier.ts","../src/adapters/maven/maven-strategy.ts","../src/adapters/gradle/gradle-discovery.ts","../src/adapters/gradle/gradle-probe.ts","../src/adapters/gradle/gradle-command.ts","../src/adapters/gradle/gradle-init-script.ts","../src/adapters/gradle/gradle-registry.ts","../src/adapters/gradle/gradle-repositories.ts","../src/adapters/gradle/gradle-versions.ts","../src/adapters/gradle/gradle-scanner.ts","../src/adapters/gradle/gradle-locator.ts","../src/adapters/gradle/gradle-catalog.ts","../src/adapters/gradle/gradle-text.ts","../src/adapters/gradle/gradle-updater.ts","../src/adapters/gradle/gradle-locks.ts","../src/adapters/gradle/gradle-verifier.ts","../src/adapters/gradle/gradle-strategy.ts","../src/domain/ecosystem-factory.ts"],"sourcesContent":["/**\r\n * Elevate — configuration.\r\n *\r\n * Detects the repository root and loads an optional `elevate.config.json`\r\n * from it. Without a configuration file Elevate works with sensible defaults\r\n * in any npm workspace or Maven repository.\r\n */\r\n\r\nimport { existsSync, readFileSync } from 'node:fs';\r\nimport { dirname, join, resolve } from 'node:path';\r\nimport type { Locale } from './i18n/types.js';\r\nimport type { ReleaseChannel } from './domain/models.js';\r\nimport { EcosystemFactory } from './domain/ecosystem-factory.js';\r\nimport { findCheckoutBoundary } from './adapters/shared/checkout.js';\r\nimport { DEFAULT_MAVEN_PLUGINS } from './adapters/maven/maven-resolution.js';\r\nimport type { MavenPluginVersions } from './adapters/maven/maven-resolution.js';\r\n\r\nexport interface ElevateConfig {\r\n /** Detected repository root. */\r\n rootDir: string;\r\n /** Display name in the header (optional). */\r\n author?: string;\r\n /**\r\n * Internal npm scopes and Maven groupId prefixes (e.g. `@my-org`,\r\n * `com.mycompany`). Packages matching them are internal: they are looked\r\n * up only in a private registry, never on a public one.\r\n */\r\n internalScopes: string[];\r\n /** Optional command that replaces the default verification after an update. */\r\n postUpdateScript?: string;\r\n /** Label for the verification command in the UI. */\r\n postUpdateLabel?: string;\r\n /** Preferred language ('de' | 'en'); undefined means auto-detect. */\r\n locale?: Locale | 'auto';\r\n /** Release channel ('stable' | 'all', default 'stable'). */\r\n channel: ReleaseChannel;\r\n /** Human-readable notices about deprecated configuration keys. */\r\n deprecations: string[];\r\n /** Versions of the Maven plugins Elevate runs (always filled, defaults applied). */\r\n mavenPlugins: MavenPluginVersions;\r\n /** Human-readable notices about invalid configuration values that were replaced by defaults. */\r\n warnings: string[];\r\n}\r\n\r\n/**\r\n * Detects the repository root for a start directory, so Elevate behaves the\r\n * same wherever in the repository it is started.\r\n *\r\n * 1. The nearest `elevate.config.json` marks the root explicitly.\r\n * 2. Otherwise every ecosystem proposes a root and the outermost proposal wins.\r\n * 3. Without any marker the start directory is the root.\r\n *\r\n * The search stays inside the version-control checkout (see\r\n * `findCheckoutBoundary`) so markers of unrelated directories above it are\r\n * never picked up.\r\n */\r\nexport function findRepositoryRoot(startDir: string): string {\r\n const start = resolve(startDir);\r\n const boundary = findCheckoutBoundary(start);\r\n\r\n let dir = start;\r\n for (;;) {\r\n if (existsSync(join(dir, 'elevate.config.json'))) return dir;\r\n const parent = dirname(dir);\r\n if (dir === boundary || parent === dir) break;\r\n dir = parent;\r\n }\r\n\r\n const proposals = EcosystemFactory.getAvailableEcosystems()\r\n .map((ecosystem) => EcosystemFactory.getStrategy(ecosystem).discovery.findRoot?.(start, boundary))\r\n .filter((root): root is string => root !== undefined);\r\n // All proposals are the start directory or one of its ancestors, so the\r\n // outermost one has the shortest path.\r\n return proposals.sort((a, b) => a.length - b.length)[0] ?? start;\r\n}\r\n\r\n/** Thrown when `elevate.config.json` cannot be used; Elevate stops instead of ignoring it. */\r\nexport class ConfigError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'ConfigError';\r\n }\r\n}\r\n\r\nconst NO_CONTINUE = 'Elevate does not continue without your internalScopes.';\r\n\r\n/**\r\n * Reads a scope list. A missing key is fine; a key that is present but is not\r\n * a list of strings is an error, because ignoring it would silently switch off\r\n * the protection of internal packages.\r\n */\r\nfunction stringList(file: Record<string, unknown>, key: string, source: string): string[] | undefined {\r\n if (!Object.hasOwn(file, key)) return undefined;\r\n const value = file[key];\r\n if (Array.isArray(value) && value.every((entry) => typeof entry === 'string')) return value;\r\n throw new ConfigError(\r\n `Invalid elevate.config.json (${source}): \\`${key}\\` must be a list of strings, ` +\r\n `for example [\"@my-org\", \"com.mycompany\"]. ${NO_CONTINUE}`,\r\n );\r\n}\r\n\r\n/** A plugin version is 1 to 64 characters, starts with a digit and has only letters, digits, `.` and `-`. */\r\nconst PLUGIN_VERSION = /^[0-9][A-Za-z0-9.-]{0,63}$/;\r\n\r\n/**\r\n * Reads the optional `mavenPlugins` object. An invalid value is replaced by\r\n * the default and reported in `warnings`; unknown keys, and a `mavenPlugins`\r\n * that is not an object, are ignored silently.\r\n */\r\nfunction resolveMavenPlugins(value: unknown, warnings: string[]): MavenPluginVersions {\r\n const plugins = { ...DEFAULT_MAVEN_PLUGINS };\r\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return plugins;\r\n\r\n const given = value as Record<string, unknown>;\r\n for (const key of Object.keys(DEFAULT_MAVEN_PLUGINS) as (keyof MavenPluginVersions)[]) {\r\n if (!Object.hasOwn(given, key)) continue;\r\n const version = given[key];\r\n if (typeof version === 'string' && PLUGIN_VERSION.test(version)) {\r\n plugins[key] = version;\r\n } else {\r\n warnings.push(\r\n `\\`mavenPlugins.${key}\\` is not a valid version (${JSON.stringify(version)}); using the default ${DEFAULT_MAVEN_PLUGINS[key]}.`,\r\n );\r\n }\r\n }\r\n return plugins;\r\n}\r\n\r\n/**\r\n * Builds the configuration from parsed `elevate.config.json` content.\r\n *\r\n * `excludeScopes` is the former name of `internalScopes`. It is still read so\r\n * existing configurations keep working, and reported as deprecated.\r\n */\r\nexport function resolveConfig(\r\n rootDir: string,\r\n file: Record<string, unknown>,\r\n source = 'elevate.config.json',\r\n): ElevateConfig {\r\n const deprecations: string[] = [];\r\n const warnings: string[] = [];\r\n const internal = stringList(file, 'internalScopes', source);\r\n const legacy = stringList(file, 'excludeScopes', source);\r\n\r\n if (legacy) {\r\n deprecations.push(\r\n internal\r\n ? '`excludeScopes` is deprecated and ignored because `internalScopes` is set; remove it from elevate.config.json.'\r\n : '`excludeScopes` is deprecated; rename it to `internalScopes` in elevate.config.json.',\r\n );\r\n }\r\n\r\n return {\r\n rootDir,\r\n author: typeof file.author === 'string' ? file.author : undefined,\r\n internalScopes: internal ?? legacy ?? [],\r\n postUpdateScript: typeof file.postUpdateScript === 'string' ? file.postUpdateScript : undefined,\r\n postUpdateLabel:\r\n typeof file.postUpdateLabel === 'string'\r\n ? file.postUpdateLabel\r\n : typeof file.postUpdateScript === 'string'\r\n ? file.postUpdateScript\r\n : undefined,\r\n locale: file.locale === 'de' || file.locale === 'en' ? file.locale : undefined,\r\n channel: file.channel === 'all' ? 'all' : 'stable',\r\n deprecations,\r\n mavenPlugins: resolveMavenPlugins(file.mavenPlugins, warnings),\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Loads the configuration:\r\n * 1. detects the repository root (see `findRepositoryRoot`),\r\n * 2. reads `elevate.config.json` from it, if present,\r\n * 3. applies defaults for missing values.\r\n */\r\nexport function loadConfig(startDir: string = process.cwd()): ElevateConfig {\r\n const rootDir = findRepositoryRoot(startDir);\r\n const configPath = join(rootDir, 'elevate.config.json');\r\n let file: Record<string, unknown> = {};\r\n\r\n if (existsSync(configPath)) {\r\n const unreadable = (detail: string) =>\r\n new ConfigError(\r\n `Cannot read elevate.config.json: ${detail} (${configPath}). ` +\r\n `Fix the file or remove it; ${NO_CONTINUE}`,\r\n );\r\n\r\n let parsed: unknown;\r\n try {\r\n // Windows editors often save JSON with a byte order mark, which JSON.parse rejects.\r\n parsed = JSON.parse(readFileSync(configPath, 'utf8').replace(/^/, ''));\r\n } catch (err) {\r\n throw unreadable(err instanceof Error ? err.message : String(err));\r\n }\r\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\r\n throw unreadable('the file must contain a JSON object');\r\n }\r\n file = parsed as Record<string, unknown>;\r\n }\r\n\r\n return resolveConfig(rootDir, file, configPath);\r\n}\r\n","/**\r\n * Elevate — per-ecosystem version rules.\r\n *\r\n * Collects what differs between ecosystems when a target version is chosen, so\r\n * callers ask the strategy instead of testing the ecosystem name.\r\n */\r\n\r\nimport semver from 'semver';\r\nimport type { VersionDiff } from './models.js';\r\nimport { cleanJavaVersion, diffVersions, rangePrefix } from './versions.js';\r\n\r\nexport interface VersionPolicy {\r\n /** A version in comparable SemVer form, or null when it has no numeric core. */\r\n normalize(version: string): string | null;\r\n /** The text to write for `target`, given the requirement currently in the manifest. */\r\n rewrite(currentRange: string, target: string): string;\r\n /** Size of the change from `current` (normalised) to `target` (raw). */\r\n diff(current: string, target: string): VersionDiff;\r\n /** Whether a dependency without a pending update may be set to a version by hand. */\r\n readonly allowsManualTargets: boolean;\r\n}\r\n\r\n/** Diff using SemVer; an unreadable side counts as `minor`. */\r\nexport function semverDiff(current: string, target: string, normalize: (v: string) => string | null): VersionDiff {\r\n const to = normalize(target);\r\n if (!to || !semver.valid(current)) return 'minor';\r\n return semver.eq(current, to) ? 'patch' : diffVersions(current, to);\r\n}\r\n\r\nexport const npmVersionPolicy: VersionPolicy = {\r\n normalize: (v) => semver.valid(v),\r\n rewrite: (current, target) => `${rangePrefix(current)}${target}`,\r\n diff: (current, target) => semverDiff(current, target, (v) => semver.valid(v)),\r\n allowsManualTargets: true,\r\n};\r\n\r\nexport const mavenVersionPolicy: VersionPolicy = {\r\n normalize: cleanJavaVersion,\r\n rewrite: (_current, target) => target,\r\n diff: (current, target) => semverDiff(current, target, cleanJavaVersion),\r\n allowsManualTargets: false,\r\n};\r\n","/**\r\n * Elevate — version helpers shared by all ecosystems.\r\n */\r\n\r\nimport semver from 'semver';\r\n\r\n/**\r\n * Matches a pre-release qualifier as a whole token: it must start the string,\r\n * follow a separator or a digit, and end at a separator, a digit or the end.\r\n * This keeps words such as `android`, `jre` or `devtools` from being taken for\r\n * pre-releases. Single-letter forms (`a1`, `b2`, `M3`) require a number.\r\n */\r\nconst PRE_RELEASE =\r\n /(?:^|[.\\-_+]|(?<=\\d))(alpha|beta|rc|cr|milestone|preview|snapshot|ea|dev|pre|(?:a|b|m)(?=\\d))(?=$|[.\\-_+]|\\d)/i;\r\n\r\n/** Whether a version is a pre-release (alpha, beta, RC, milestone, snapshot, …). */\r\nexport function isPreReleaseVersion(version: string): boolean {\r\n return PRE_RELEASE.test(version);\r\n}\r\n\r\n/** Short label for a pre-release, e.g. \"BETA\", \"RC\", \"M2\"; undefined for releases. */\r\nexport function extractPreReleaseTag(version: string): string | undefined {\r\n const match = version.match(PRE_RELEASE);\r\n if (!match) return undefined;\r\n const token = match[1]!.toLowerCase();\r\n if (token === 'a') return 'ALPHA';\r\n if (token === 'b') return 'BETA';\r\n if (token === 'm') {\r\n const number = version.slice((match.index ?? 0) + match[0].length).match(/^\\d+/)?.[0];\r\n return `M${number ?? ''}`;\r\n }\r\n return token.toUpperCase();\r\n}\r\n\r\n/**\r\n * Normalises a Java-style version (e.g. \"5.10.2\", \"1.71.0.Final\",\r\n * \"32.0.0-jre\") to a SemVer string for diffing. Returns null when the version\r\n * has no numeric core.\r\n */\r\nexport function cleanJavaVersion(version: string): string | null {\r\n const match = version.match(/^v?(\\d+(?:\\.\\d+){0,2})/);\r\n if (!match) return null;\r\n return semver.coerce(match[1])?.version ?? null;\r\n}\r\n\r\n/** SemVer difference between two versions, collapsed to patch/minor/major. */\r\nexport function diffVersions(from: string, to: string): 'patch' | 'minor' | 'major' {\r\n const kind = semver.diff(from, to);\r\n if (kind === 'major' || kind === 'premajor') return 'major';\r\n if (kind === 'minor' || kind === 'preminor') return 'minor';\r\n return 'patch';\r\n}\r\n\r\n/** Returns the range operator (`^`, `~` or none) of an npm range. */\r\nexport function rangePrefix(range: string): '^' | '~' | '' {\r\n if (range.startsWith('^')) return '^';\r\n if (range.startsWith('~')) return '~';\r\n return '';\r\n}\r\n","/**\r\n * Elevate — package manager detection.\r\n *\r\n * Elevate's Node.js support drives npm and pnpm. In a repository managed by\r\n * Yarn or Bun, running either would create a second lockfile and a\r\n * `node_modules` layout the project does not use, so such repositories are\r\n * recognised and refused.\r\n */\r\n\r\nimport { existsSync, readFileSync } from 'node:fs';\r\nimport { dirname, join, resolve } from 'node:path';\r\nimport { findCheckoutBoundary } from '../shared/checkout.js';\r\nimport { runCommand } from '../shared/process.js';\r\n\r\nexport type PackageManagerName = 'npm' | 'pnpm' | 'yarn' | 'bun';\r\n\r\nexport interface DetectedPackageManager {\r\n name: PackageManagerName;\r\n /** What decided: the `packageManager` field, a file name, or the lack of both. */\r\n evidence: string;\r\n}\r\n\r\n/** Marker files per package manager, checked in this order; the first match decides. */\r\nconst MARKER_FILES: readonly [PackageManagerName, readonly string[]][] = [\r\n ['npm', ['package-lock.json', 'npm-shrinkwrap.json']],\r\n ['pnpm', ['pnpm-lock.yaml', 'pnpm-workspace.yaml']],\r\n ['yarn', ['yarn.lock', '.yarnrc.yml']],\r\n ['bun', ['bun.lock', 'bun.lockb']],\r\n];\r\n\r\n/** Thrown when the repository is managed by a package manager Elevate does not drive (Yarn, Bun). */\r\nexport class UnsupportedPackageManagerError extends Error {\r\n constructor(detected: DetectedPackageManager) {\r\n super(\r\n `This repository is managed by ${detected.name} (${detected.evidence}). ` +\r\n `Elevate supports npm and pnpm for Node.js projects; using either here would create a lockfile next to ` +\r\n `${detected.name}'s. Nothing was changed.`,\r\n );\r\n this.name = 'UnsupportedPackageManagerError';\r\n }\r\n}\r\n\r\n/**\r\n * Recognises the package manager that manages `dir`. Starting at `dir`, each\r\n * directory up to the checkout boundary is examined; the first one with a\r\n * decisive finding wins. This matters when Elevate is started inside a\r\n * workspace package: pnpm keeps its workspace file and lockfile at the\r\n * workspace root, not next to the package. Without a checkout boundary only\r\n * `dir` itself is examined: files of unrelated directories above it say\r\n * nothing about this project.\r\n */\r\nexport function detectPackageManager(dir: string): DetectedPackageManager {\r\n const boundary = findCheckoutBoundary(dir);\r\n let current = resolve(dir);\r\n for (;;) {\r\n const found = detectIn(current);\r\n if (found) return found;\r\n const parent = dirname(current);\r\n if (boundary === undefined || current === boundary || parent === current) break;\r\n current = parent;\r\n }\r\n return { name: 'npm', evidence: 'no other package manager detected' };\r\n}\r\n\r\n/** The decisive finding in one directory, if any. */\r\nfunction detectIn(dir: string): DetectedPackageManager | undefined {\r\n const declared = readPackageManagerField(dir);\r\n const name = declared?.match(/^(npm|pnpm|yarn|bun)@/)?.[1] as PackageManagerName | undefined;\r\n if (declared && name) return { name, evidence: `\"packageManager\": \"${declared}\" in package.json` };\r\n\r\n for (const [manager, files] of MARKER_FILES) {\r\n const found = files.find((file) => existsSync(join(dir, file)));\r\n if (found) return { name: manager, evidence: found };\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Returns the package manager Elevate drives for this repository; throws\r\n * `UnsupportedPackageManagerError` for Yarn and Bun.\r\n */\r\nexport function assertSupportedPackageManager(rootDir: string): 'npm' | 'pnpm' {\r\n const detected = detectPackageManager(rootDir);\r\n if (detected.name === 'npm' || detected.name === 'pnpm') return detected.name;\r\n throw new UnsupportedPackageManagerError(detected);\r\n}\r\n\r\n/** Thrown when pnpm is required but cannot be run. */\r\nexport class PackageManagerNotFoundError extends Error {\r\n constructor(reason: string, detected: DetectedPackageManager) {\r\n super(\r\n `pnpm could not be run in this repository (${reason}). This repository is managed by pnpm ` +\r\n `(${detected.evidence}); install pnpm or enable Corepack (corepack enable). Nothing was changed.`,\r\n );\r\n this.name = 'PackageManagerNotFoundError';\r\n }\r\n}\r\n\r\nconst VERSION_TIMEOUT_MS = 15_000;\r\nconst verifiedRoots = new Set<string>();\r\n\r\n/**\r\n * Makes sure `pnpm --version` succeeds before anything is touched. A success is\r\n * remembered per root for the life of the process; a failure is not.\r\n */\r\nexport async function ensurePnpmRunnable(rootDir: string, detected: DetectedPackageManager): Promise<void> {\r\n const key = resolve(rootDir);\r\n if (verifiedRoots.has(key)) return;\r\n\r\n let reason: string | undefined;\r\n try {\r\n const result = await runCommand('pnpm', ['--version'], { cwd: rootDir, timeoutMs: VERSION_TIMEOUT_MS });\r\n if (result.timedOut) reason = 'pnpm --version timed out';\r\n else if (result.exitCode !== 0) {\r\n const line = firstLine(result.stderr) || firstLine(result.stdout);\r\n reason = `pnpm --version exited with code ${result.exitCode}: ${line}`;\r\n }\r\n } catch {\r\n reason = 'command not found';\r\n }\r\n if (reason !== undefined) throw new PackageManagerNotFoundError(reason, detected);\r\n verifiedRoots.add(key);\r\n}\r\n\r\n/**\r\n * Guard for operations on a repository: refuses Yarn and Bun, and for pnpm\r\n * checks that it can run. Returns the manager to drive.\r\n */\r\nexport async function prepareSupportedPackageManager(rootDir: string): Promise<'npm' | 'pnpm'> {\r\n const manager = assertSupportedPackageManager(rootDir);\r\n if (manager === 'pnpm') await ensurePnpmRunnable(rootDir, detectPackageManager(rootDir));\r\n return manager;\r\n}\r\n\r\nfunction firstLine(text: string): string {\r\n return text.split(/\\r?\\n/).find((l) => l.trim() !== '')?.trim() ?? '';\r\n}\r\n\r\nfunction readPackageManagerField(rootDir: string): string | undefined {\r\n try {\r\n const field = JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf8'))?.packageManager;\r\n return typeof field === 'string' ? field : undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n","/**\r\n * Elevate — version-control checkout boundary.\r\n *\r\n * Searches for markers of the repository (configuration, workspace files,\r\n * lockfiles) stop at the checkout, so files of unrelated directories above it\r\n * are never picked up.\r\n */\r\n\r\nimport { existsSync } from 'node:fs';\r\nimport { dirname, join, resolve } from 'node:path';\r\n\r\n/**\r\n * The nearest directory, starting at `startDir` and walking upwards, that\r\n * contains an entry named `.git` (a directory, or a file in worktrees and\r\n * submodules). Undefined when there is none.\r\n */\r\nexport function findCheckoutBoundary(startDir: string): string | undefined {\r\n let dir = resolve(startDir);\r\n for (;;) {\r\n if (existsSync(join(dir, '.git'))) return dir;\r\n const parent = dirname(dir);\r\n if (parent === dir) return undefined;\r\n dir = parent;\r\n }\r\n}\r\n","/**\r\n * Elevate — child process helper.\r\n *\r\n * Runs external tools (npm, Maven) with an argument list instead of a\r\n * concatenated command line. On Windows, `npm`, `mvn` and `mvnw` are batch\r\n * files that can only be started through the shell; there every argument is\r\n * quoted, and arguments containing shell metacharacters are rejected outright\r\n * rather than escaped, so a crafted package name can never inject a command.\r\n * The working directory is handed to the process directly, never through the\r\n * command line, so callers name files relative to it.\r\n */\r\n\r\nimport { exec, spawn } from 'node:child_process';\r\nimport { isAbsolute, relative } from 'node:path';\r\n\r\nexport interface RunOptions {\r\n cwd: string;\r\n /** Kill the process after this many milliseconds. */\r\n timeoutMs?: number;\r\n}\r\n\r\nexport interface RunResult {\r\n exitCode: number;\r\n stdout: string;\r\n stderr: string;\r\n timedOut: boolean;\r\n}\r\n\r\n/** Thrown when an argument cannot be passed safely to the shell. */\r\nexport class UnsafeArgumentError extends Error {\r\n constructor(argument: string) {\r\n super(\r\n `Cannot pass ${JSON.stringify(argument)} to the Windows command shell: it contains one of the characters ` +\r\n '\" % ! ^ & | < > or a line break, which cmd.exe would interpret. ' +\r\n 'If this is part of a directory or file name, rename it or move the project to a path without these characters.',\r\n );\r\n this.name = 'UnsafeArgumentError';\r\n }\r\n}\r\n\r\nconst IS_WINDOWS = process.platform === 'win32';\r\n\r\n/** Characters cmd.exe interprets even inside double quotes, plus quotes themselves. */\r\nconst WINDOWS_UNSAFE = /[\"%!^&|<>\\r\\n]/;\r\n\r\n/**\r\n * Runs a command and resolves with its exit code and output. Never rejects for\r\n * a non-zero exit code; callers decide what a failure means.\r\n */\r\nexport function runCommand(command: string, args: string[], options: RunOptions): Promise<RunResult> {\r\n return new Promise((resolve, reject) => {\r\n const spawnOptions = { cwd: options.cwd, windowsHide: true, env: process.env };\r\n let child;\r\n\r\n if (IS_WINDOWS) {\r\n for (const arg of [command, ...args]) {\r\n if (WINDOWS_UNSAFE.test(arg)) {\r\n reject(new UnsafeArgumentError(arg));\r\n return;\r\n }\r\n }\r\n // The shell receives one pre-quoted command line; passing an argument\r\n // array together with `shell: true` is deprecated because Node would\r\n // concatenate it unescaped.\r\n const commandLine = [command, ...args].map(quoteWindows).join(' ');\r\n child = spawn(commandLine, { ...spawnOptions, shell: true });\r\n } else {\r\n child = spawn(command, args, spawnOptions);\r\n }\r\n\r\n let stdout = '';\r\n let stderr = '';\r\n let timedOut = false;\r\n child.stdout.setEncoding('utf8').on('data', (chunk: string) => (stdout += chunk));\r\n child.stderr.setEncoding('utf8').on('data', (chunk: string) => (stderr += chunk));\r\n\r\n const timer = options.timeoutMs\r\n ? setTimeout(() => {\r\n timedOut = true;\r\n killTree(child.pid, () => child.kill());\r\n }, options.timeoutMs)\r\n : undefined;\r\n\r\n child.on('error', (err) => {\r\n if (timer) clearTimeout(timer);\r\n reject(err);\r\n });\r\n\r\n child.on('close', (code) => {\r\n if (timer) clearTimeout(timer);\r\n resolve({ exitCode: code ?? 1, stdout, stderr, timedOut });\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Runs a user-defined command line (`postUpdateScript`) through the shell.\r\n * The script comes from the repository's own configuration file, not from\r\n * dependency data, so it is trusted like any other project script.\r\n */\r\nexport function runShellScript(script: string, options: RunOptions): Promise<RunResult> {\r\n return new Promise((resolve) => {\r\n exec(\r\n script,\r\n { cwd: options.cwd, timeout: options.timeoutMs, maxBuffer: 64 * 1024 * 1024, windowsHide: true },\r\n (error, stdout, stderr) => {\r\n const timedOut = Boolean(error?.killed);\r\n const exitCode = error ? (typeof error.code === 'number' ? error.code : 1) : 0;\r\n resolve({ exitCode, stdout, stderr, timedOut });\r\n },\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * Kills a process together with its children. On Windows the command runs\r\n * inside cmd.exe; killing only the shell would leave npm or Java running with\r\n * the output pipes open, so the 'close' event would never fire.\r\n */\r\nfunction killTree(pid: number | undefined, fallback: () => void): void {\r\n if (!IS_WINDOWS || pid === undefined) {\r\n fallback();\r\n return;\r\n }\r\n const killer = spawn('taskkill', ['/pid', String(pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' });\r\n killer.on('error', fallback);\r\n}\r\n\r\n/** Returns the last lines of a tool's output for use in error messages. */\r\nexport function tail(output: string, lines = 15): string {\r\n return output.trim().split(/\\r?\\n/).slice(-lines).join('\\n');\r\n}\r\n\r\nfunction quoteWindows(arg: string): string {\r\n // `=`, `,` and `;` separate arguments for batch files, so they force quoting too.\r\n return /^[\\w.:\\\\/@+-]+$/.test(arg) ? arg : `\"${arg}\"`;\r\n}\r\n\r\n/**\r\n * Names a file relative to the working directory a process runs in, with the\r\n * platform's separators. The working directory is handed to the process\r\n * directly, so the directory the repository lives in (which may contain\r\n * characters cmd.exe would interpret) never appears in an argument. A file\r\n * that cannot be expressed relative to `cwd` (another drive on Windows) is\r\n * returned unchanged.\r\n */\r\nexport function relativeToCwd(cwd: string, file: string): string {\r\n const path = relative(cwd, file);\r\n return isAbsolute(path) ? file : path || '.';\r\n}\r\n","/**\r\n * Elevate — npm workspace discovery.\r\n *\r\n * Resolves the `workspaces` patterns of the root package.json with\r\n * `@npmcli/map-workspaces`, the same library npm uses internally. Glob\r\n * patterns (`packages/**`, `apps/*-service`), negations and nested folders\r\n * therefore behave exactly as they do for `npm install`. In a pnpm repository\r\n * the patterns come from `pnpm-workspace.yaml` instead and go through the same\r\n * library, so patterns, negation and `node_modules` are treated alike.\r\n */\r\n\r\nimport { readFileSync } from 'node:fs';\r\nimport { dirname, join, relative, resolve } from 'node:path';\r\nimport mapWorkspaces from '@npmcli/map-workspaces';\r\nimport type { ModuleDiscoveryPort } from '../../domain/ports.js';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { detectPackageManager } from './npm-package-manager.js';\r\nimport { readPnpmWorkspace } from './pnpm-workspace.js';\r\n\r\nfunction readJson(filePath: string): any {\r\n try {\r\n return JSON.parse(readFileSync(filePath, 'utf8'));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport class NpmModuleDiscoveryAdapter implements ModuleDiscoveryPort {\r\n /**\r\n * The nearest directory, from `startDir` upwards to the boundary, whose\r\n * package.json is valid JSON and declares `workspaces`, or that contains a\r\n * valid `pnpm-workspace.yaml`.\r\n */\r\n findRoot(startDir: string, boundaryDir: string | undefined): string | undefined {\r\n let dir = resolve(startDir);\r\n const boundary = boundaryDir ? resolve(boundaryDir) : undefined;\r\n for (;;) {\r\n if (readJson(join(dir, 'package.json'))?.workspaces || readPnpmWorkspace(dir)) return dir;\r\n const parent = dirname(dir);\r\n if (dir === boundary || parent === dir) return undefined;\r\n dir = parent;\r\n }\r\n }\r\n\r\n async discover(rootDir: string): Promise<ProjectModule[]> {\r\n const rootPkg = readJson(join(rootDir, 'package.json'));\r\n\r\n const modules: ProjectModule[] = [\r\n {\r\n id: rootPkg?.name ?? 'root',\r\n name: rootPkg?.name ?? 'Root Workspace (npm)',\r\n path: rootDir,\r\n relPath: 'Root',\r\n ecosystem: 'npm',\r\n isRoot: true,\r\n version: typeof rootPkg?.version === 'string' ? rootPkg.version : undefined,\r\n },\r\n ];\r\n\r\n // A pnpm repository declares its packages in pnpm-workspace.yaml and ignores the field.\r\n const patterns =\r\n detectPackageManager(rootDir).name === 'pnpm' ? readPnpmWorkspace(rootDir)?.packages : rootPkg?.workspaces;\r\n if (!patterns || (Array.isArray(patterns) && patterns.length === 0)) return modules;\r\n\r\n let workspaces: Map<string, string>;\r\n try {\r\n workspaces = await mapWorkspaces({ cwd: rootDir, pkg: { ...rootPkg, workspaces: patterns } });\r\n } catch {\r\n // Invalid workspace configuration (e.g. duplicate names): npm refuses it\r\n // as well, so only the root is reported.\r\n return modules;\r\n }\r\n\r\n for (const [name, path] of workspaces) {\r\n const pkg = readJson(join(path, 'package.json'));\r\n modules.push({\r\n id: name,\r\n name,\r\n path,\r\n relPath: relative(rootDir, path).replace(/\\\\/g, '/'),\r\n ecosystem: 'npm',\r\n isRoot: false,\r\n version: typeof pkg?.version === 'string' ? pkg.version : undefined,\r\n });\r\n }\r\n\r\n modules.sort((a, b) => (a.isRoot ? -1 : b.isRoot ? 1 : a.relPath.localeCompare(b.relPath)));\r\n return modules;\r\n }\r\n}\r\n","/**\r\n * Elevate — pnpm-workspace.yaml.\r\n *\r\n * Reads the package patterns and catalogs of a pnpm workspace, and replaces a\r\n * catalog entry's range in place. The YAML document API is used for writing\r\n * because it keeps the position of every node: only the entry's range is\r\n * replaced, comments, quoting and line endings stay as they are.\r\n */\r\n\r\nimport { readFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { isMap, isScalar, parse, parseDocument } from 'yaml';\r\nimport type { Scalar } from 'yaml';\r\n\r\nexport const PNPM_WORKSPACE_FILE = 'pnpm-workspace.yaml';\r\n\r\nexport interface PnpmWorkspace {\r\n /** Absolute path of the file. */\r\n file: string;\r\n /** `[]` when missing or empty. */\r\n packages: string[];\r\n /** By catalog name; the default catalog is `default`. */\r\n catalogs: ReadonlyMap<string, ReadonlyMap<string, string>>;\r\n /** `catalog` and `catalogs.default` are both defined. */\r\n ambiguousDefaultCatalog: boolean;\r\n}\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction entries(value: unknown): Map<string, string> {\r\n const map = new Map<string, string>();\r\n if (isRecord(value)) {\r\n for (const [name, range] of Object.entries(value)) {\r\n if (typeof range === 'string') map.set(name, range);\r\n }\r\n }\r\n return map;\r\n}\r\n\r\n/** `undefined` when the file is absent or not valid YAML. */\r\nexport function readPnpmWorkspace(rootDir: string): PnpmWorkspace | undefined {\r\n const file = join(rootDir, PNPM_WORKSPACE_FILE);\r\n let data: unknown;\r\n try {\r\n data = parse(readFileSync(file, 'utf8'));\r\n } catch {\r\n return undefined;\r\n }\r\n if (data !== null && !isRecord(data)) return undefined;\r\n const doc = (data ?? {}) as Record<string, unknown>;\r\n\r\n const packages = Array.isArray(doc.packages) ? doc.packages.filter((p): p is string => typeof p === 'string') : [];\r\n\r\n const catalogs = new Map<string, Map<string, string>>();\r\n const named = isRecord(doc.catalogs) ? doc.catalogs : {};\r\n for (const [name, content] of Object.entries(named)) catalogs.set(name, entries(content));\r\n const hasTopLevel = isRecord(doc.catalog);\r\n const hasNamedDefault = isRecord(named.default);\r\n if (hasTopLevel) catalogs.set('default', entries(doc.catalog));\r\n\r\n return { file, packages, catalogs, ambiguousDefaultCatalog: hasTopLevel && hasNamedDefault };\r\n}\r\n\r\n/**\r\n * Returns `source` with the range of one catalog entry replaced. Throws when\r\n * the entry does not exist.\r\n */\r\nexport function setCatalogRange(source: string, catalog: string, name: string, newRange: string): string {\r\n const doc = parseDocument(source);\r\n const holders = catalog === 'default' ? [doc.get('catalog', true), doc.getIn(['catalogs', 'default'], true)] : [doc.getIn(['catalogs', catalog], true)];\r\n\r\n for (const holder of holders) {\r\n if (!isMap(holder)) continue;\r\n const node = holder.get(name, true);\r\n if (!isScalar(node) || !node.range) continue;\r\n const scalar = node as Scalar;\r\n const [start, end] = scalar.range!;\r\n const quote = scalar.type === 'QUOTE_DOUBLE' ? '\"' : scalar.type === 'QUOTE_SINGLE' ? \"'\" : '';\r\n return source.slice(0, start) + quote + newRange + quote + source.slice(end);\r\n }\r\n throw new Error(`No entry for '${name}' in catalog '${catalog}' of ${PNPM_WORKSPACE_FILE}.`);\r\n}\r\n","/**\r\n * Elevate — npm registry adapter.\r\n *\r\n * Queries versions through `npm view`, so the registry, authentication and\r\n * proxy settings of the user's npm configuration apply automatically.\r\n */\r\n\r\nimport semver from 'semver';\r\nimport type { RegistryEndpoint, RegistryPort } from '../../domain/ports.js';\r\nimport type { DependencyCoordinate, ReleaseChannel } from '../../domain/models.js';\r\nimport { runCommand } from '../shared/process.js';\r\nimport { NpmConfigReader, isPublicNpmRegistry } from './npm-config.js';\r\nimport { commands, driverFor } from './npm-commands.js';\r\n\r\nconst LOOKUP_TIMEOUT_MS = 15_000;\r\n\r\n/** Valid npm package names (lower- or mixed-case legacy names included). */\r\nconst PACKAGE_NAME = /^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/i;\r\n\r\n/** Whether a string is a syntactically valid npm package name. */\r\nexport function isValidPackageName(name: string): boolean {\r\n return name.length <= 214 && PACKAGE_NAME.test(name);\r\n}\r\n\r\nexport class NpmRegistryAdapter implements RegistryPort {\r\n constructor(readonly config = new NpmConfigReader()) {}\r\n\r\n async resolveEndpoint(coordinate: DependencyCoordinate, cwd: string): Promise<RegistryEndpoint> {\r\n const url = await this.config.registryFor(coordinate.identifier, cwd);\r\n return { url, isPublic: isPublicNpmRegistry(url) };\r\n }\r\n\r\n async getLatestVersion(\r\n coordinate: DependencyCoordinate,\r\n channel: ReleaseChannel = 'stable',\r\n cwd = process.cwd(),\r\n ): Promise<string | null> {\r\n if (!isValidPackageName(coordinate.identifier)) return null;\r\n\r\n if (channel === 'stable') {\r\n // The `latest` dist-tag is the maintainers' designated stable release.\r\n const latest = await this.view(coordinate.identifier, 'dist-tags.latest', cwd);\r\n if (typeof latest === 'string' && semver.valid(latest) && semver.prerelease(latest) === null) {\r\n return latest;\r\n }\r\n // The tag points to a pre-release (or is missing): fall back to the\r\n // highest published release, never to the pre-release itself.\r\n const releases = (await this.getAllVersions(coordinate, cwd)).filter(\r\n (v) => semver.valid(v) && semver.prerelease(v) === null,\r\n );\r\n return releases.length > 0 ? semver.rsort(releases)[0]! : null;\r\n }\r\n\r\n // `version` is the version the `latest` tag points to.\r\n const version = await this.view(coordinate.identifier, 'version', cwd);\r\n return typeof version === 'string' && version ? version : null;\r\n }\r\n\r\n async getAllVersions(coordinate: DependencyCoordinate, cwd = process.cwd()): Promise<string[]> {\r\n if (!isValidPackageName(coordinate.identifier)) return [];\r\n const versions = await this.view(coordinate.identifier, 'versions', cwd);\r\n const list = Array.isArray(versions) ? versions : versions ? [versions] : [];\r\n return list.map(String).reverse();\r\n }\r\n\r\n /** Runs `npm view <name> <field> --json` (`pnpm view` in a pnpm repository); resolves null on any failure. */\r\n protected async view(name: string, field: string, cwd: string): Promise<unknown> {\r\n try {\r\n const { command, args } = commands.view(driverFor(cwd), name, field);\r\n const result = await runCommand(command, args, {\r\n cwd,\r\n timeoutMs: LOOKUP_TIMEOUT_MS,\r\n });\r\n if (result.exitCode !== 0 || !result.stdout.trim()) return null;\r\n return JSON.parse(result.stdout);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n}\r\n","/**\r\n * Elevate — dependency origin classification.\r\n *\r\n * Decides whether a dependency is a workspace module, an internal package from\r\n * a private registry, or a public package. The registry URL alone is not a\r\n * reliable signal: in most companies every request — public packages included\r\n * — goes through one Artifactory or Nexus proxy. The classification therefore\r\n * relies on what is explicitly known: the modules found in the repository,\r\n * the configured internal scopes, and explicit per-scope registry mappings.\r\n */\r\n\r\nimport type { DependencyOrigin, Ecosystem, ProjectModule } from './models.js';\r\n\r\n/** Index of the repository's own modules, keyed by dependency identifier. */\r\nexport type WorkspaceIndex = ReadonlyMap<string, ProjectModule>;\r\n\r\nexport interface OriginContext {\r\n workspace: WorkspaceIndex;\r\n /** Configured internal scopes / groupId prefixes (e.g. `@my-org`, `com.mycompany`). */\r\n internalScopes: readonly string[];\r\n /** npm only: explicit `@scope:registry` mappings from the npm configuration. */\r\n scopedRegistries?: ReadonlyMap<string, string>;\r\n}\r\n\r\n/**\r\n * Builds the workspace index from discovered modules, keyed by the identifier a\r\n * dependency on the module has: `coordinates` (Gradle's `group:name`) when the\r\n * module has them, its id otherwise (npm package name, Maven `groupId:artifactId`).\r\n */\r\nexport function buildWorkspaceIndex(modules: readonly ProjectModule[]): WorkspaceIndex {\r\n const index = new Map<string, ProjectModule>();\r\n for (const module of modules) {\r\n const key = module.coordinates ?? module.id;\r\n if (key && key !== 'empty') index.set(key, module);\r\n }\r\n return index;\r\n}\r\n\r\nexport function classifyOrigin(\r\n identifier: string,\r\n ecosystem: Ecosystem,\r\n context: OriginContext,\r\n): DependencyOrigin {\r\n const module = context.workspace.get(identifier);\r\n if (module) {\r\n return { kind: 'workspace', moduleId: module.id, moduleRelPath: module.relPath };\r\n }\r\n\r\n if (matchesInternalScope(identifier, ecosystem, context.internalScopes)) {\r\n return { kind: 'private', matchedBy: 'internal-scope' };\r\n }\r\n\r\n if (ecosystem === 'npm' && context.scopedRegistries) {\r\n const scope = npmScopeOf(identifier);\r\n const registry = scope ? context.scopedRegistries.get(scope) : undefined;\r\n if (registry) return { kind: 'private', matchedBy: 'scoped-registry', registry };\r\n }\r\n\r\n return { kind: 'public' };\r\n}\r\n\r\n/**\r\n * Checks an identifier against the configured internal scopes.\r\n *\r\n * npm: `@scope` (or `@scope/`) matches every package in that scope; any other\r\n * entry matches the exact package name, or a name prefix when it ends in `*`.\r\n *\r\n * Maven and Gradle: an entry matches the groupId itself and every groupId below it on a\r\n * segment boundary — `com.acme` matches `com.acme` and `com.acme.billing`, but\r\n * not `com.acmecorp`. A leading `@` is ignored so one shared list can serve\r\n * both ecosystems.\r\n */\r\nexport function matchesInternalScope(\r\n identifier: string,\r\n ecosystem: Ecosystem,\r\n internalScopes: readonly string[],\r\n): boolean {\r\n // Maven and Gradle name a library `group:artifact`; the group is what a scope matches.\r\n if (ecosystem === 'maven' || ecosystem === 'gradle') {\r\n const groupId = identifier.split(':')[0] ?? '';\r\n return internalScopes.some((entry) => {\r\n const prefix = entry.replace(/^@/, '').replace(/[.:/]+$/, '');\r\n return prefix.length > 0 && (groupId === prefix || groupId.startsWith(`${prefix}.`));\r\n });\r\n }\r\n\r\n return internalScopes.some((entry) => {\r\n if (entry.startsWith('@')) {\r\n const scope = entry.replace(/\\/+$/, '');\r\n return identifier.startsWith(`${scope}/`);\r\n }\r\n if (entry.endsWith('*')) return identifier.startsWith(entry.slice(0, -1));\r\n return identifier === entry;\r\n });\r\n}\r\n\r\n/** Returns the `@scope` part of a scoped npm package name. */\r\nexport function npmScopeOf(name: string): string | undefined {\r\n if (!name.startsWith('@')) return undefined;\r\n const slash = name.indexOf('/');\r\n return slash > 1 ? name.slice(0, slash) : undefined;\r\n}\r\n","/**\r\n * Elevate — package manager commands.\r\n *\r\n * The only place that knows which executable and arguments each package\r\n * manager gets. Everything else asks this table.\r\n */\r\n\r\nimport { detectPackageManager } from './npm-package-manager.js';\r\n\r\nexport type Driver = 'npm' | 'pnpm';\r\n\r\nexport interface CommandLine {\r\n command: Driver;\r\n args: string[];\r\n}\r\n\r\n/**\r\n * The package manager that answers version and configuration queries in\r\n * `dir`. Yarn and Bun repositories are not refused for read-only queries and\r\n * are served by npm.\r\n */\r\nexport function driverFor(dir: string): Driver {\r\n return detectPackageManager(dir).name === 'pnpm' ? 'pnpm' : 'npm';\r\n}\r\n\r\nexport const commands = {\r\n /** Install after Elevate wrote new ranges. pnpm is told explicitly not to freeze: `CI` would otherwise imply it. */\r\n install: (m: Driver): CommandLine =>\r\n m === 'pnpm' ? { command: 'pnpm', args: ['install', '--no-frozen-lockfile'] } : { command: 'npm', args: ['install'] },\r\n /** Restore the installed state after a rollback. */\r\n restore: (m: Driver): CommandLine =>\r\n m === 'pnpm' ? { command: 'pnpm', args: ['install', '--frozen-lockfile'] } : { command: 'npm', args: ['install'] },\r\n /** Default verification. */\r\n verify: (m: Driver): CommandLine =>\r\n m === 'pnpm'\r\n ? { command: 'pnpm', args: ['install', '--frozen-lockfile', '--lockfile-only'] }\r\n : { command: 'npm', args: ['ls'] },\r\n view: (m: Driver, name: string, field: string): CommandLine => ({ command: m, args: ['view', name, field, '--json'] }),\r\n config: (m: Driver): CommandLine => ({ command: m, args: ['config', 'list', '--json'] }),\r\n};\r\n","/**\r\n * Elevate — npm configuration reader.\r\n *\r\n * Reads the effective npm configuration through `npm config list --json`, so\r\n * every source npm itself honours (project, user and global `.npmrc`,\r\n * environment variables) is taken into account without re-implementing npm's\r\n * precedence rules.\r\n */\r\n\r\nimport { runCommand } from '../shared/process.js';\r\nimport { npmScopeOf } from '../../domain/origin.js';\r\nimport { commands, driverFor } from './npm-commands.js';\r\n\r\nexport interface NpmRegistryConfig {\r\n /** Default registry for unscoped packages and scopes without a mapping. */\r\n registry: string;\r\n /** Explicit `@scope:registry` mappings. */\r\n scopedRegistries: ReadonlyMap<string, string>;\r\n}\r\n\r\nconst DEFAULT_REGISTRY = 'https://registry.npmjs.org/';\r\n\r\n/** Hosts of public npm registries. */\r\nconst PUBLIC_NPM_HOSTS = new Set(['registry.npmjs.org', 'registry.npmjs.com', 'registry.yarnpkg.com', 'npm.jsr.io']);\r\n\r\nexport class NpmConfigReader {\r\n private readonly cache = new Map<string, Promise<NpmRegistryConfig>>();\r\n\r\n /** Returns the registry configuration that applies in `cwd` (cached per directory). */\r\n read(cwd: string): Promise<NpmRegistryConfig> {\r\n let pending = this.cache.get(cwd);\r\n if (!pending) {\r\n pending = loadConfig(cwd);\r\n this.cache.set(cwd, pending);\r\n }\r\n return pending;\r\n }\r\n\r\n /** The registry npm would contact for this package. */\r\n async registryFor(packageName: string, cwd: string): Promise<string> {\r\n const config = await this.read(cwd);\r\n const scope = npmScopeOf(packageName);\r\n return (scope && config.scopedRegistries.get(scope)) || config.registry;\r\n }\r\n}\r\n\r\n/** Whether a registry URL points to a public npm registry. */\r\nexport function isPublicNpmRegistry(url: string): boolean {\r\n try {\r\n return PUBLIC_NPM_HOSTS.has(new URL(url).hostname.toLowerCase());\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/** Extracts registry settings from the JSON printed by `npm config list --json`. */\r\nexport function parseNpmConfig(json: Record<string, unknown>): NpmRegistryConfig {\r\n const scopedRegistries = new Map<string, string>();\r\n for (const [key, value] of Object.entries(json)) {\r\n const match = key.match(/^(@[^:]+):registry$/);\r\n if (match && typeof value === 'string' && value) scopedRegistries.set(match[1]!, value);\r\n }\r\n const registry = typeof json.registry === 'string' && json.registry ? json.registry : DEFAULT_REGISTRY;\r\n return { registry, scopedRegistries };\r\n}\r\n\r\nasync function loadConfig(cwd: string): Promise<NpmRegistryConfig> {\r\n try {\r\n const { command, args } = commands.config(driverFor(cwd));\r\n const result = await runCommand(command, args, { cwd, timeoutMs: 15_000 });\r\n if (result.exitCode !== 0) return parseNpmConfig({});\r\n return parseNpmConfig(JSON.parse(result.stdout) as Record<string, unknown>);\r\n } catch {\r\n // Without a readable configuration npm falls back to the public registry,\r\n // and so do we — which keeps internal packages from being looked up.\r\n return parseNpmConfig({});\r\n }\r\n}\r\n","/**\r\n * Elevate — npm dependency scanner.\r\n *\r\n * Classifies every dependency of a module by origin and consults the matching\r\n * version source:\r\n *\r\n * - workspace: the local version of the sibling module. A dependency whose\r\n * range does not include that version is not linked by npm but installed\r\n * from a registry, so it is offered for alignment.\r\n * - private: the registry configured for the package; never a public one.\r\n * - public: the configured registry via `npm view` (`pnpm view` in a pnpm repository).\r\n *\r\n * In a pnpm repository `workspace:` ranges are aligned, a plain range on a\r\n * module is listed as not linked, and `catalog:` ranges are resolved through\r\n * pnpm-workspace.yaml.\r\n */\r\n\r\nimport { readFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport semver from 'semver';\r\nimport type { DependencyReaderPort, RegistryPort, ScanContext } from '../../domain/ports.js';\r\nimport type {\r\n DependencyCoordinate,\r\n VersionDeclaration,\r\n DependencyOrigin,\r\n ProjectModule,\r\n ScanResult,\r\n SkippedDependency,\r\n UpdateCandidate,\r\n} from '../../domain/models.js';\r\nimport { classifyOrigin } from '../../domain/origin.js';\r\nimport { diffVersions, extractPreReleaseTag, rangePrefix } from '../../domain/versions.js';\r\nimport { mapPooled } from '../shared/pool.js';\r\nimport { isPublicNpmRegistry } from './npm-config.js';\r\nimport type { NpmConfigReader } from './npm-config.js';\r\nimport { prepareSupportedPackageManager } from './npm-package-manager.js';\r\nimport { splitRangeProtocol } from './npm-protocols.js';\r\nimport { readPnpmWorkspace } from './pnpm-workspace.js';\r\nimport type { PnpmWorkspace } from './pnpm-workspace.js';\r\nimport { isValidPackageName } from './npm-registry.js';\r\n\r\nconst CONCURRENCY = 6;\r\nconst DIFF_ORDER: Record<string, number> = { major: 0, minor: 1, patch: 2 };\r\n\r\ninterface DeclaredDependency {\r\n name: string;\r\n range: string;\r\n scope: 'prod' | 'dev';\r\n}\r\n\r\ntype Outcome = { candidate: UpdateCandidate } | { skipped: SkippedDependency } | null;\r\n\r\nexport class NpmDependencyAdapter implements DependencyReaderPort {\r\n constructor(\r\n private readonly registry: RegistryPort,\r\n private readonly config: NpmConfigReader,\r\n ) {}\r\n\r\n async scan(module: ProjectModule, context: ScanContext): Promise<ScanResult> {\r\n const manager = await prepareSupportedPackageManager(context.rootDir);\r\n const pnpm = manager === 'pnpm';\r\n\r\n let pkg: any;\r\n try {\r\n pkg = JSON.parse(readFileSync(join(module.path, 'package.json'), 'utf8'));\r\n } catch {\r\n return { candidates: [], skipped: [] };\r\n }\r\n\r\n const npmConfig = await this.config.read(context.rootDir);\r\n const originContext = {\r\n workspace: context.workspace,\r\n internalScopes: context.internalScopes,\r\n // A scope mapped to a public registry is not internal; only private\r\n // mappings mark their scope as private.\r\n scopedRegistries: new Map(\r\n [...npmConfig.scopedRegistries].filter(([, url]) => !isPublicNpmRegistry(url)),\r\n ),\r\n };\r\n\r\n const workspaceFile = pnpm ? readPnpmWorkspace(context.rootDir) : undefined;\r\n\r\n const outcomes = await mapPooled(declaredDependencies(pkg), CONCURRENCY, async (dep): Promise<Outcome> => {\r\n const origin = classifyOrigin(dep.name, 'npm', originContext);\r\n if (origin.kind === 'workspace') {\r\n const target = context.workspace.get(dep.name);\r\n if (pnpm && isUpgradableRange(dep.range) && splitRangeProtocol(dep.range).protocol === undefined) {\r\n // pnpm resolves a plain range from the registry, never from the workspace.\r\n return { skipped: { identifier: dep.name, origin: 'workspace', reason: 'not-linked', detail: dep.range } };\r\n }\r\n const candidate = target ? alignmentCandidate(dep, target, origin, pnpm) : null;\r\n return candidate ? { candidate } : null;\r\n }\r\n if (pnpm && splitRangeProtocol(dep.range).protocol === 'catalog') {\r\n return this.catalogOutcome(dep, origin, context, module.path, workspaceFile);\r\n }\r\n return this.registryOutcome(dep, origin, context);\r\n });\r\n\r\n const candidates: UpdateCandidate[] = [];\r\n const skipped: SkippedDependency[] = [];\r\n for (const outcome of outcomes) {\r\n if (!outcome) continue;\r\n if ('candidate' in outcome) candidates.push(outcome.candidate);\r\n else skipped.push(outcome.skipped);\r\n }\r\n\r\n candidates.sort((a, b) => (DIFF_ORDER[a.diff] ?? 3) - (DIFF_ORDER[b.diff] ?? 3));\r\n return { candidates, skipped };\r\n }\r\n\r\n /** A `catalog:` dependency: the range comes from pnpm-workspace.yaml and is written back there. */\r\n private async catalogOutcome(\r\n dep: DeclaredDependency,\r\n origin: DependencyOrigin,\r\n context: ScanContext,\r\n modulePath: string,\r\n workspaceFile: PnpmWorkspace | undefined,\r\n ): Promise<Outcome> {\r\n const catalogName = splitRangeProtocol(dep.range).rest || 'default';\r\n const unresolved = (detail: string): Outcome => ({\r\n skipped: { identifier: dep.name, origin: origin.kind, reason: 'catalog-unresolved', detail },\r\n });\r\n if (!workspaceFile) return unresolved('pnpm-workspace.yaml is missing or not valid YAML');\r\n if (catalogName === 'default' && workspaceFile.ambiguousDefaultCatalog) {\r\n return unresolved(\"catalog 'default' is defined twice (catalog and catalogs.default)\");\r\n }\r\n const catalog = workspaceFile.catalogs.get(catalogName);\r\n if (!catalog) return unresolved(`no catalog '${catalogName}'`);\r\n const range = catalog.get(dep.name);\r\n if (range === undefined) return unresolved(`no entry for '${dep.name}' in catalog '${catalogName}'`);\r\n\r\n const declaration: VersionDeclaration = {\r\n file: workspaceFile.file,\r\n kind: 'catalog',\r\n catalogName,\r\n displayPath: 'pnpm-workspace.yaml',\r\n };\r\n const sharedWith = usersOfCatalogEntry(context, modulePath, dep.name, catalogName);\r\n return this.registryOutcome({ ...dep, range }, origin, context, {\r\n declaration,\r\n ...(sharedWith.length > 0 ? { sharedWith } : {}),\r\n });\r\n }\r\n\r\n /** Looks up a private or public dependency in its registry. */\r\n private async registryOutcome(\r\n dep: DeclaredDependency,\r\n origin: DependencyOrigin,\r\n context: ScanContext,\r\n extra: Partial<UpdateCandidate> = {},\r\n ): Promise<Outcome> {\r\n // Git URLs, file paths, aliases and dist-tags are not registry versions.\r\n if (!isUpgradableRange(dep.range)) return null;\r\n\r\n if (!isValidPackageName(dep.name)) {\r\n return { skipped: { identifier: dep.name, origin: origin.kind, reason: 'invalid-name' } };\r\n }\r\n\r\n const coordinate: DependencyCoordinate = { identifier: dep.name, artifact: dep.name, ecosystem: 'npm' };\r\n\r\n let resolvedOrigin = origin;\r\n if (origin.kind === 'private') {\r\n // Asking a public registry about an internal name is exactly what a\r\n // dependency-confusion attack exploits, so the lookup is not made at all.\r\n const endpoint = await this.registry.resolveEndpoint(coordinate, context.rootDir);\r\n if (endpoint.isPublic) {\r\n return {\r\n skipped: {\r\n identifier: dep.name,\r\n origin: 'private',\r\n reason: 'private-on-public-registry',\r\n detail: endpoint.url,\r\n },\r\n };\r\n }\r\n resolvedOrigin = { ...origin, registry: endpoint.url };\r\n }\r\n\r\n const latest = await this.registry.getLatestVersion(coordinate, context.channel, context.rootDir);\r\n if (!latest) {\r\n return { skipped: { identifier: dep.name, origin: origin.kind, reason: 'lookup-failed' } };\r\n }\r\n\r\n const currentClean = semver.minVersion(dep.range)?.version;\r\n if (!currentClean || !semver.valid(latest) || !semver.gt(latest, currentClean)) return null;\r\n\r\n const tag = semver.prerelease(latest) ? extractPreReleaseTag(latest) ?? 'PRE' : undefined;\r\n const diff = diffVersions(currentClean, latest);\r\n return {\r\n candidate: {\r\n coordinate,\r\n currentRange: dep.range,\r\n currentClean,\r\n latest,\r\n newRange: `${rangePrefix(dep.range)}${latest}`,\r\n diff,\r\n scope: dep.scope,\r\n selected: diff !== 'major',\r\n origin: resolvedOrigin,\r\n action: 'update',\r\n isPreRelease: tag !== undefined,\r\n preReleaseTag: tag,\r\n ...extra,\r\n },\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * The sections whose ranges say \"this is what I install\": they are scanned and\r\n * written. `peerDependencies`, `overrides` and `bundleDependencies` are\r\n * statements to others and are never offered or changed. Listed in npm's\r\n * increasing precedence for a name declared more than once.\r\n */\r\nexport const DEPENDENCY_SECTIONS = ['dependencies', 'optionalDependencies', 'devDependencies'] as const;\r\n\r\n/**\r\n * Lists the dependencies of the scanned sections once per name. A name in\r\n * several sections takes the range of the last one in `DEPENDENCY_SECTIONS`\r\n * (npm installs the optional range over the regular one); a name that is also\r\n * a devDependency counts as dev.\r\n */\r\nfunction declaredDependencies(pkg: any): DeclaredDependency[] {\r\n const deps = new Map<string, DeclaredDependency>();\r\n for (const section of DEPENDENCY_SECTIONS) {\r\n const scope = section === 'devDependencies' ? 'dev' : 'prod';\r\n for (const [name, range] of Object.entries(pkg[section] ?? {})) {\r\n if (typeof range === 'string') deps.set(name, { name, range, scope });\r\n }\r\n }\r\n return [...deps.values()];\r\n}\r\n\r\n/** Whether a range is a SemVer range pinned to something more specific than \"any\". */\r\nexport function isUpgradableRange(range: string): boolean {\r\n const trimmed = range.trim();\r\n if (trimmed === '' || trimmed === '*' || trimmed.toLowerCase() === 'x') return false;\r\n return semver.validRange(trimmed) !== null;\r\n}\r\n\r\n/**\r\n * Builds an alignment candidate when the declared range excludes the local\r\n * version of the workspace module, i.e. when npm would not link the module.\r\n * Ranges npm links regardless of the version (`*`, `file:`, `link:`,\r\n * `workspace:`) never need alignment.\r\n */\r\nexport function alignmentCandidate(\r\n dep: DeclaredDependency,\r\n target: ProjectModule,\r\n origin: DependencyOrigin,\r\n pnpm = false,\r\n): UpdateCandidate | null {\r\n // Only a pnpm repository interprets `workspace:`; elsewhere it is no SemVer range and stays untouched.\r\n const split = pnpm ? splitRangeProtocol(dep.range) : { protocol: undefined, rest: dep.range };\r\n const range = split.protocol === 'workspace' ? split.rest : dep.range;\r\n const protocol = split.protocol === 'workspace' ? 'workspace:' : '';\r\n\r\n const local = target.version;\r\n if (!local || !semver.valid(local) || !isUpgradableRange(range)) return null;\r\n if (semver.satisfies(local, range, { includePrerelease: true })) return null;\r\n\r\n const currentClean = semver.minVersion(range)?.version ?? '0.0.0';\r\n const diff = diffVersions(currentClean, local);\r\n const tag = semver.prerelease(local) ? extractPreReleaseTag(local) ?? 'PRE' : undefined;\r\n\r\n return {\r\n coordinate: { identifier: dep.name, artifact: dep.name, ecosystem: 'npm' },\r\n currentRange: dep.range,\r\n currentClean,\r\n latest: local,\r\n newRange: `${protocol}${rangePrefix(range)}${local}`,\r\n diff,\r\n scope: dep.scope,\r\n selected: diff !== 'major',\r\n origin,\r\n action: 'align',\r\n availableVersions: [local],\r\n isPreRelease: tag !== undefined,\r\n preReleaseTag: tag,\r\n };\r\n}\r\n\r\n/** Ids of the other modules whose scanned sections refer to the same catalog entry. */\r\nfunction usersOfCatalogEntry(context: ScanContext, selfPath: string, name: string, catalogName: string): string[] {\r\n const users: string[] = [];\r\n for (const module of context.workspace.values()) {\r\n if (module.path === selfPath) continue;\r\n let pkg: any;\r\n try {\r\n pkg = JSON.parse(readFileSync(join(module.path, 'package.json'), 'utf8'));\r\n } catch {\r\n continue;\r\n }\r\n const dep = declaredDependencies(pkg).find((d) => d.name === name);\r\n if (!dep || splitRangeProtocol(dep.range).protocol !== 'catalog') continue;\r\n if ((splitRangeProtocol(dep.range).rest || 'default') !== catalogName) continue;\r\n users.push(module.id);\r\n }\r\n return users;\r\n}\r\n","/**\r\n * Elevate — bounded concurrency helper.\r\n */\r\n\r\n/**\r\n * Maps `items` through `fn` with at most `concurrency` calls in flight.\r\n * Results keep the input order. A rejected call rejects the whole pool, so\r\n * `fn` should handle expected failures itself.\r\n */\r\nexport async function mapPooled<T, R>(\r\n items: readonly T[],\r\n concurrency: number,\r\n fn: (item: T) => Promise<R>,\r\n): Promise<R[]> {\r\n const results = new Array<R>(items.length);\r\n let next = 0;\r\n\r\n async function worker(): Promise<void> {\r\n while (next < items.length) {\r\n const index = next++;\r\n results[index] = await fn(items[index]!);\r\n }\r\n }\r\n\r\n const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());\r\n await Promise.all(workers);\r\n return results;\r\n}\r\n","/**\r\n * Elevate — pnpm range protocols.\r\n *\r\n * `workspace:` and `catalog:` ranges are only interpreted in pnpm\r\n * repositories; in an npm repository they stay non-SemVer and are ignored.\r\n */\r\n\r\nexport interface SplitRange {\r\n protocol: 'workspace' | 'catalog' | undefined;\r\n /** What follows `workspace:` or `catalog:`; the whole range without a protocol. */\r\n rest: string;\r\n}\r\n\r\nexport function splitRangeProtocol(range: string): SplitRange {\r\n if (range.startsWith('workspace:')) return { protocol: 'workspace', rest: range.slice('workspace:'.length) };\r\n if (range.startsWith('catalog:')) return { protocol: 'catalog', rest: range.slice('catalog:'.length) };\r\n return { protocol: undefined, rest: range };\r\n}\r\n","/**\r\n * Elevate — npm updater.\r\n *\r\n * Writes new ranges to the module's package.json (keeping its indentation),\r\n * runs `npm install` at the repository root and verifies that aligned\r\n * workspace dependencies are linked rather than installed from a registry.\r\n */\r\n\r\nimport { readFileSync, writeFileSync } from 'node:fs';\r\nimport { join, relative } from 'node:path';\r\nimport { InstallError } from '../../domain/ports.js';\r\nimport type { ApplyOutcome, DependencyUpdaterPort } from '../../domain/ports.js';\r\nimport type { ProjectModule, UpdateCandidate } from '../../domain/models.js';\r\nimport { runCommand, tail } from '../shared/process.js';\r\nimport type { RunResult } from '../shared/process.js';\r\nimport {\r\n PackageManagerNotFoundError,\r\n UnsupportedPackageManagerError,\r\n detectPackageManager,\r\n prepareSupportedPackageManager,\r\n} from './npm-package-manager.js';\r\nimport { DEPENDENCY_SECTIONS } from './npm-scanner.js';\r\nimport { findUnlinkedWorkspaceDependencies, readLockfile } from './npm-lockfile.js';\r\nimport { commands } from './npm-commands.js';\r\nimport type { Driver } from './npm-commands.js';\r\nimport { AUDIT_TIMEOUT_MS, parsePnpmAudit, unavailable } from './pnpm-audit.js';\r\nimport type { AuditSummary } from './pnpm-audit.js';\r\nimport { findUnlinkedPnpmDependencies, readPnpmLockfile } from './pnpm-lockfile.js';\r\nimport { setCatalogRange } from './pnpm-workspace.js';\r\n\r\nconst INSTALL_TIMEOUT_MS = 10 * 60_000;\r\n\r\n/** pnpm prints errors on stdout (9 to 11) or stderr (12), so both are quoted; npm's go to stderr. */\r\nfunction failureDetails(manager: Driver, result: RunResult): string {\r\n return manager === 'pnpm' ? tail(`${result.stdout}\\n${result.stderr}`) : tail(result.stderr || result.stdout);\r\n}\r\n\r\nexport class NpmUpdaterAdapter implements DependencyUpdaterPort {\r\n affectedFiles(module: ProjectModule, rootDir: string): string[] {\r\n if (detectPackageManager(rootDir).name === 'pnpm') {\r\n return [\r\n join(module.path, 'package.json'),\r\n join(rootDir, 'package.json'),\r\n join(rootDir, 'pnpm-lock.yaml'),\r\n join(rootDir, 'pnpm-workspace.yaml'),\r\n ];\r\n }\r\n return [\r\n join(module.path, 'package.json'),\r\n join(rootDir, 'package.json'),\r\n join(rootDir, 'package-lock.json'),\r\n join(rootDir, 'npm-shrinkwrap.json'),\r\n ];\r\n }\r\n\r\n async applyUpdates(\r\n module: ProjectModule,\r\n rootDir: string,\r\n updates: UpdateCandidate[],\r\n onProgress: (stepMessage: string) => void,\r\n ): Promise<ApplyOutcome> {\r\n let manager: Driver;\r\n try {\r\n manager = await prepareSupportedPackageManager(rootDir);\r\n } catch (err) {\r\n if (err instanceof UnsupportedPackageManagerError || err instanceof PackageManagerNotFoundError) {\r\n throw new InstallError(err.message);\r\n }\r\n throw err;\r\n }\r\n\r\n // A catalog entry is written where it is declared; the module's package.json keeps its `catalog:` reference.\r\n const catalogUpdates = updates.filter((u) => u.declaration?.kind === 'catalog');\r\n const manifestUpdates = updates.filter((u) => u.declaration?.kind !== 'catalog');\r\n\r\n const pkgPath = join(module.path, 'package.json');\r\n let manifest: { source: string; pkg: any } | undefined;\r\n if (manifestUpdates.length > 0 || catalogUpdates.length === 0) {\r\n try {\r\n const source = readFileSync(pkgPath, 'utf8');\r\n manifest = { source, pkg: JSON.parse(source) };\r\n } catch {\r\n throw new InstallError(`Cannot read package.json in ${module.path}.`);\r\n }\r\n }\r\n\r\n if (manifest) {\r\n onProgress('Writing new versions to package.json…');\r\n for (const item of manifestUpdates) {\r\n const name = item.coordinate.artifact;\r\n // Every section that declares the name receives the range.\r\n for (const section of DEPENDENCY_SECTIONS) {\r\n if (typeof manifest.pkg[section]?.[name] === 'string') manifest.pkg[section][name] = item.newRange;\r\n }\r\n }\r\n writeFileSync(pkgPath, serializeLike(manifest.source, manifest.pkg), 'utf8');\r\n }\r\n\r\n if (catalogUpdates.length > 0) {\r\n onProgress('Writing new versions to pnpm-workspace.yaml…');\r\n writeCatalogRanges(catalogUpdates);\r\n }\r\n\r\n const install = commands.install(manager);\r\n onProgress(`Running ${manager} install…`);\r\n const result = await runCommand(install.command, install.args, { cwd: rootDir, timeoutMs: INSTALL_TIMEOUT_MS });\r\n if (result.exitCode !== 0) {\r\n const reason = result.timedOut ? `${manager} install timed out` : `${manager} install failed`;\r\n throw new InstallError(reason, failureDetails(manager, result));\r\n }\r\n\r\n const lockName = manager === 'pnpm' ? 'pnpm-lock.yaml' : 'package-lock.json';\r\n onProgress(`Checking workspace links in ${lockName}…`);\r\n const integrityViolations = verifyAlignedLinks(manager, module, rootDir, updates);\r\n\r\n if (manager === 'pnpm') {\r\n const audit = integrityViolations.length > 0 ? undefined : await runPnpmAudit(rootDir);\r\n return {\r\n updatedCount: updates.length,\r\n auditMessage: audit?.message ?? '',\r\n auditSeverity: audit?.severity ?? 'clean',\r\n fundingMessage: undefined,\r\n integrityViolations,\r\n };\r\n }\r\n\r\n const combined = `${result.stdout}\\n${result.stderr}`;\r\n const audit = parseAuditSummary(combined);\r\n const fundingMatch = combined.match(/(\\d+ packages? (?:is|are) looking for funding)/i);\r\n\r\n return {\r\n updatedCount: updates.length,\r\n auditMessage: audit.message,\r\n auditSeverity: audit.severity,\r\n fundingMessage: fundingMatch ? fundingMatch[0] : undefined,\r\n integrityViolations,\r\n };\r\n }\r\n\r\n async resync(_module: ProjectModule, rootDir: string, onProgress: (stepMessage: string) => void): Promise<void> {\r\n // Nothing was installed in a repository Elevate does not drive, so there is nothing to restore.\r\n const name = detectPackageManager(rootDir).name;\r\n if (name !== 'npm' && name !== 'pnpm') return;\r\n\r\n const restore = commands.restore(name);\r\n onProgress(`Restoring node_modules (${name} install)…`);\r\n const result = await runCommand(restore.command, restore.args, { cwd: rootDir, timeoutMs: INSTALL_TIMEOUT_MS });\r\n if (result.exitCode !== 0) {\r\n throw new InstallError(\r\n `${name} install failed while restoring the previous state`,\r\n name === 'pnpm' ? failureDetails(name, result) : tail(result.stderr),\r\n );\r\n }\r\n }\r\n}\r\n\r\n/** Replaces each catalog entry in the file that declares it, once per file. */\r\nfunction writeCatalogRanges(updates: UpdateCandidate[]): void {\r\n const sources = new Map<string, string>();\r\n for (const item of updates) {\r\n const declaration = item.declaration!;\r\n try {\r\n let source = sources.get(declaration.file) ?? readFileSync(declaration.file, 'utf8');\r\n source = setCatalogRange(source, declaration.catalogName ?? 'default', item.coordinate.artifact, item.newRange);\r\n sources.set(declaration.file, source);\r\n } catch (err) {\r\n throw new InstallError(err instanceof Error ? err.message : `Cannot update ${declaration.displayPath}.`);\r\n }\r\n }\r\n for (const [file, source] of sources) writeFileSync(file, source, 'utf8');\r\n}\r\n\r\n/** The vulnerability summary of pnpm; an audit that gives no result is a warning, never a failure. */\r\nasync function runPnpmAudit(rootDir: string): Promise<AuditSummary> {\r\n try {\r\n const result = await runCommand('pnpm', ['audit', '--json'], { cwd: rootDir, timeoutMs: AUDIT_TIMEOUT_MS });\r\n if (result.timedOut) return unavailable(`pnpm audit timed out after ${AUDIT_TIMEOUT_MS / 1000} seconds`);\r\n return parsePnpmAudit(result.stdout);\r\n } catch {\r\n return unavailable('pnpm audit returned no result');\r\n }\r\n}\r\n\r\n/**\r\n * A line of npm's vulnerability summary: `found 0 vulnerabilities`,\r\n * `1 high severity vulnerability`, `5 vulnerabilities (1 low, 2 moderate, 2 high)`\r\n * or npm 6's `found 3 vulnerabilities (1 low, 2 high)`. Anchored to the whole\r\n * line so other numbers in npm's output are not mistaken for a count.\r\n */\r\nconst VULNERABILITY_LINE = /^(?:found\\s+)?(\\d+)\\s+(?:(?:info|low|moderate|high|critical)\\s+severity\\s+)?vulnerabilit(?:y|ies)\\b.*$/i;\r\n\r\n/**\r\n * Reads the vulnerability summary from the output of `npm install`. Zero\r\n * vulnerabilities, or no summary at all, is clean; otherwise the result is a\r\n * warning that quotes npm's own line.\r\n */\r\nexport function parseAuditSummary(output: string): { message: string; severity: 'clean' | 'warn' } {\r\n for (const line of output.split(/\\r?\\n/)) {\r\n const match = line.trim().match(VULNERABILITY_LINE);\r\n if (match && Number(match[1]) > 0) return { message: line.trim(), severity: 'warn' };\r\n }\r\n return { message: 'No known vulnerabilities found.', severity: 'clean' };\r\n}\r\n\r\n/** Every aligned workspace dependency must now be linked to its workspace. */\r\nfunction verifyAlignedLinks(\r\n manager: Driver,\r\n module: ProjectModule,\r\n rootDir: string,\r\n updates: UpdateCandidate[],\r\n): string[] {\r\n const aligned = updates.filter((u) => u.origin.kind === 'workspace').map((u) => u.coordinate.identifier);\r\n if (aligned.length === 0) return [];\r\n\r\n const moduleRelPath = relative(rootDir, module.path).replace(/\\\\/g, '/');\r\n if (manager === 'pnpm') return findUnlinkedPnpmDependencies(readPnpmLockfile(rootDir), moduleRelPath, aligned);\r\n\r\n const lockfile = readLockfile(rootDir);\r\n if (!lockfile) return ['package-lock.json is missing; workspace links cannot be verified'];\r\n return findUnlinkedWorkspaceDependencies(lockfile, moduleRelPath, aligned);\r\n}\r\n\r\n/** Serialises JSON with the indentation and final newline of the original file. */\r\nfunction serializeLike(original: string, value: unknown): string {\r\n const indent = original.match(/^[ \\t]+(?=\")/m)?.[0] ?? ' ';\r\n const newline = original.includes('\\r\\n') ? '\\r\\n' : '\\n';\r\n const body = JSON.stringify(value, null, indent).replace(/\\n/g, newline);\r\n return original.endsWith('\\n') ? body + newline : body;\r\n}\r\n","/**\r\n * Elevate — domain ports (hexagonal architecture).\r\n *\r\n * Interfaces that decouple the domain logic from concrete package managers,\r\n * registries and file system operations.\r\n */\r\n\r\nimport type {\r\n ProjectModule,\r\n DependencyCoordinate,\r\n UpdateCandidate,\r\n UpdateSummary,\r\n ReleaseChannel,\r\n ScanResult,\r\n} from './models.js';\r\nimport type { WorkspaceIndex } from './origin.js';\r\n\r\n/** Port: finds all modules of an ecosystem in the repository. */\r\nexport interface ModuleDiscoveryPort {\r\n discover(rootDir: string): Promise<ProjectModule[]>;\r\n /**\r\n * Problems of the most recent `discover` run that did not stop it, e.g. one\r\n * workspace whose tool run failed while others were found. Empty when none.\r\n */\r\n diagnostics?(): string[];\r\n /**\r\n * Proposes the repository root this ecosystem would use when started in\r\n * `startDir`: the outermost directory it can relate `startDir` to. Only\r\n * `startDir` and its ancestors up to and including `boundaryDir` are\r\n * examined (without a boundary, up to the file-system root). Returns\r\n * `undefined` when the ecosystem has no opinion.\r\n */\r\n findRoot?(startDir: string, boundaryDir: string | undefined): string | undefined;\r\n}\r\n\r\n/** The registry a lookup would contact. */\r\nexport interface RegistryEndpoint {\r\n url: string;\r\n /** Whether the endpoint is a public registry such as npmjs.org or Maven Central. */\r\n isPublic: boolean;\r\n}\r\n\r\n/** Port: queries a registry for versions. */\r\nexport interface RegistryPort {\r\n /**\r\n * Resolves which registry a lookup for this coordinate would contact, using\r\n * the package manager's own configuration.\r\n *\r\n * @param cwd directory whose configuration applies (usually the repository root)\r\n */\r\n resolveEndpoint(coordinate: DependencyCoordinate, cwd: string): Promise<RegistryEndpoint>;\r\n getLatestVersion(\r\n coordinate: DependencyCoordinate,\r\n channel?: ReleaseChannel,\r\n cwd?: string,\r\n ): Promise<string | null>;\r\n /** All published versions, newest first. */\r\n getAllVersions(coordinate: DependencyCoordinate, cwd?: string): Promise<string[]>;\r\n}\r\n\r\n/** Everything a scan needs to know beyond the module itself. */\r\nexport interface ScanContext {\r\n rootDir: string;\r\n workspace: WorkspaceIndex;\r\n internalScopes: readonly string[];\r\n channel: ReleaseChannel;\r\n}\r\n\r\n/** Port: scans a module and returns update candidates plus skipped dependencies. */\r\nexport interface DependencyReaderPort {\r\n scan(module: ProjectModule, context: ScanContext): Promise<ScanResult>;\r\n /**\r\n * Optional batch scan for adapters whose tools are expensive to start\r\n * (Maven): several modules share the same tool runs.\r\n */\r\n scanMany?(modules: readonly ProjectModule[], context: ScanContext): Promise<Map<ProjectModule, ScanResult>>;\r\n}\r\n\r\n/** Outcome of writing updates and installing them. */\r\nexport type ApplyOutcome = Pick<\r\n UpdateSummary,\r\n 'updatedCount' | 'auditMessage' | 'auditSeverity' | 'fundingMessage'\r\n> & {\r\n /**\r\n * Integrity violations detected after installation, e.g. a workspace\r\n * dependency that npm installed from a registry instead of linking it.\r\n * Any violation makes the update fail and triggers a rollback.\r\n */\r\n integrityViolations: string[];\r\n};\r\n\r\n/** Thrown when the package manager fails to install or resolve the update. */\r\nexport class InstallError extends Error {\r\n constructor(message: string, readonly output?: string) {\r\n super(message);\r\n this.name = 'InstallError';\r\n }\r\n}\r\n\r\n/** Port: writes updates to manifests and installs them. */\r\nexport interface DependencyUpdaterPort {\r\n /**\r\n * Files the update may modify: manifests, lockfiles, parent POMs. They are\r\n * captured before the update so a failure can be rolled back.\r\n */\r\n affectedFiles(module: ProjectModule, rootDir: string, updates: UpdateCandidate[]): string[];\r\n\r\n /** Writes the updates and installs them. Throws `InstallError` on failure. */\r\n applyUpdates(\r\n module: ProjectModule,\r\n rootDir: string,\r\n updates: UpdateCandidate[],\r\n onProgress: (stepMessage: string) => void,\r\n ): Promise<ApplyOutcome>;\r\n\r\n /**\r\n * Brings the installed state back in line with the manifests after they were\r\n * restored by a rollback (e.g. re-running `npm install`).\r\n */\r\n resync(module: ProjectModule, rootDir: string, onProgress: (stepMessage: string) => void): Promise<void>;\r\n}\r\n\r\nexport interface VerificationOptions {\r\n /** User-defined verification command from `postUpdateScript`. */\r\n customScript?: string;\r\n customLabel?: string;\r\n /** Files changed by the update; used to select the modules to rebuild. */\r\n changedFiles?: string[];\r\n}\r\n\r\nexport interface VerificationResult {\r\n status: 'clean' | 'warn';\r\n details: string;\r\n label: string;\r\n}\r\n\r\n/** Port: verifies the project after an update (build, tests, consistency). */\r\nexport interface VerificationPort {\r\n verify(module: ProjectModule, rootDir: string, options?: VerificationOptions): Promise<VerificationResult>;\r\n}\r\n","/**\r\n * Elevate — package-lock.json integrity checks.\r\n *\r\n * When a dependency's range does not include the local version of a workspace\r\n * package, npm does not link the workspace but installs a package with the\r\n * same name from the registry. That copy may come from anyone who published\r\n * the name. This module verifies from the lockfile that every workspace\r\n * dependency that should be linked actually is.\r\n */\r\n\r\nimport { existsSync, readFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\n\r\ninterface LockEntry {\r\n link?: boolean;\r\n resolved?: string;\r\n version?: string;\r\n}\r\n\r\ninterface Lockfile {\r\n packages?: Record<string, LockEntry>;\r\n}\r\n\r\n/** Reads the root package-lock.json; undefined when absent or unreadable. */\r\nexport function readLockfile(rootDir: string): Lockfile | undefined {\r\n const file = join(rootDir, 'package-lock.json');\r\n if (!existsSync(file)) return undefined;\r\n try {\r\n return JSON.parse(readFileSync(file, 'utf8')) as Lockfile;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Returns one message per workspace dependency that is not linked.\r\n *\r\n * npm resolves a dependency of `packages/a` by looking in\r\n * `packages/a/node_modules` first and then in the hoisted root\r\n * `node_modules`, so the nearest lockfile entry decides.\r\n *\r\n * @param moduleRelPath module directory relative to the root ('' for the root)\r\n * @param names workspace packages the module is expected to link\r\n */\r\nexport function findUnlinkedWorkspaceDependencies(\r\n lockfile: Lockfile,\r\n moduleRelPath: string,\r\n names: readonly string[],\r\n): string[] {\r\n const packages = lockfile.packages ?? {};\r\n const prefix = moduleRelPath ? `${moduleRelPath}/` : '';\r\n const violations: string[] = [];\r\n\r\n for (const name of names) {\r\n const entry = packages[`${prefix}node_modules/${name}`] ?? packages[`node_modules/${name}`];\r\n if (!entry) {\r\n violations.push(`${name}: not present in package-lock.json`);\r\n } else if (!entry.link) {\r\n const source = entry.resolved ?? 'unknown source';\r\n violations.push(`${name}: installed from ${source} instead of linking the workspace package`);\r\n }\r\n }\r\n return violations;\r\n}\r\n","/**\r\n * Elevate — reading `pnpm audit --json`.\r\n */\r\n\r\nexport const AUDIT_TIMEOUT_MS = 60_000;\r\n\r\nconst LEVELS = ['info', 'low', 'moderate', 'high', 'critical'] as const;\r\n\r\nexport interface AuditSummary {\r\n message: string;\r\n severity: 'clean' | 'warn';\r\n}\r\n\r\nexport function unavailable(reason: string): AuditSummary {\r\n return { message: `Vulnerability check unavailable: ${reason}.`, severity: 'warn' };\r\n}\r\n\r\n/** Only `metadata.vulnerabilities` decides; the exit code does not. */\r\nexport function parsePnpmAudit(output: string): AuditSummary {\r\n let json: any;\r\n try {\r\n json = JSON.parse(output);\r\n } catch {\r\n return unavailable('pnpm audit returned no result');\r\n }\r\n const counts = json?.metadata?.vulnerabilities;\r\n if (counts && typeof counts === 'object') {\r\n const parts: string[] = [];\r\n let total = 0;\r\n for (const level of LEVELS) {\r\n const n = Number(counts[level]) || 0;\r\n total += n;\r\n if (n > 0) parts.push(`${n} ${level}`);\r\n }\r\n if (total === 0) return { message: 'No known vulnerabilities found.', severity: 'clean' };\r\n return {\r\n message: `${total} ${total === 1 ? 'vulnerability' : 'vulnerabilities'} (${parts.join(', ')})`,\r\n severity: 'warn',\r\n };\r\n }\r\n const errorMessage = json?.error?.message;\r\n if (typeof errorMessage === 'string' && errorMessage) return unavailable(errorMessage);\r\n return unavailable('pnpm audit returned no result');\r\n}\r\n","/**\r\n * Elevate — pnpm-lock.yaml integrity checks.\r\n *\r\n * pnpm links a workspace package only for a dependency written with the\r\n * `workspace:` protocol. After an update that aligned such dependencies, the\r\n * `importers` section of the lockfile (lockfileVersion 9.x, pnpm 9 to 12)\r\n * proves that they are linked and not installed from a registry.\r\n */\r\n\r\nimport { existsSync, readFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { parse } from 'yaml';\r\n\r\nexport interface PnpmImporterEntry {\r\n specifier: string;\r\n version: string;\r\n}\r\n\r\nexport type PnpmImporters = Record<string, Record<string, Record<string, PnpmImporterEntry>>>;\r\n\r\nexport type PnpmLockfile =\r\n | { kind: 'ok'; importers: PnpmImporters }\r\n | { kind: 'missing' }\r\n | { kind: 'unreadable' }\r\n | { kind: 'unsupported'; lockfileVersion: string };\r\n\r\nconst SECTIONS = ['dependencies', 'devDependencies', 'optionalDependencies'] as const;\r\n\r\nexport function readPnpmLockfile(rootDir: string): PnpmLockfile {\r\n const file = join(rootDir, 'pnpm-lock.yaml');\r\n if (!existsSync(file)) return { kind: 'missing' };\r\n let data: any;\r\n try {\r\n data = parse(readFileSync(file, 'utf8'));\r\n } catch {\r\n return { kind: 'unreadable' };\r\n }\r\n if (typeof data !== 'object' || data === null || Array.isArray(data)) return { kind: 'unreadable' };\r\n\r\n const lockfileVersion = String(data.lockfileVersion ?? '');\r\n if (!/^9(\\.|$)/.test(lockfileVersion)) return { kind: 'unsupported', lockfileVersion };\r\n const importers = data.importers ?? {};\r\n if (typeof importers !== 'object' || Array.isArray(importers)) return { kind: 'unreadable' };\r\n return { kind: 'ok', importers: importers as PnpmImporters };\r\n}\r\n\r\n/**\r\n * One message per aligned dependency that is not linked.\r\n *\r\n * @param moduleRelPath module directory relative to the root ('' for the root)\r\n */\r\nexport function findUnlinkedPnpmDependencies(\r\n lockfile: PnpmLockfile,\r\n moduleRelPath: string,\r\n names: readonly string[],\r\n): string[] {\r\n switch (lockfile.kind) {\r\n case 'missing':\r\n return ['pnpm-lock.yaml is missing; workspace links cannot be verified'];\r\n case 'unreadable':\r\n return ['pnpm-lock.yaml could not be read; workspace links cannot be verified'];\r\n case 'unsupported':\r\n return [\r\n `pnpm-lock.yaml has lockfileVersion '${lockfile.lockfileVersion}', which Elevate cannot read; workspace links cannot be verified`,\r\n ];\r\n }\r\n\r\n const importer = lockfile.importers[moduleRelPath === '' ? '.' : moduleRelPath] ?? {};\r\n const violations: string[] = [];\r\n for (const name of names) {\r\n let entry: PnpmImporterEntry | undefined;\r\n for (const section of SECTIONS) {\r\n entry = importer[section]?.[name];\r\n if (entry) break;\r\n }\r\n if (!entry) violations.push(`${name}: not present in pnpm-lock.yaml`);\r\n else if (!String(entry.version).startsWith('link:')) {\r\n violations.push(`${name}: resolved to ${entry.version} instead of linking the workspace package`);\r\n }\r\n }\r\n return violations;\r\n}\r\n","/**\r\n * Elevate — npm verification.\r\n *\r\n * Without a configured `postUpdateScript`, verification runs `npm ls` at the\r\n * repository root (npm) or `pnpm install --frozen-lockfile --lockfile-only`\r\n * (pnpm; `pnpm ls` exits 0 for missing dependencies, so it cannot judge).\r\n */\r\n\r\nimport type { VerificationOptions, VerificationPort, VerificationResult } from '../../domain/ports.js';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { runCommand, runShellScript, tail } from '../shared/process.js';\r\nimport {\r\n PackageManagerNotFoundError,\r\n UnsupportedPackageManagerError,\r\n prepareSupportedPackageManager,\r\n} from './npm-package-manager.js';\r\nimport { commands } from './npm-commands.js';\r\n\r\nconst VERIFY_TIMEOUT_MS = 10 * 60_000;\r\n\r\nexport class NpmVerificationAdapter implements VerificationPort {\r\n async verify(\r\n _module: ProjectModule,\r\n rootDir: string,\r\n options: VerificationOptions = {},\r\n ): Promise<VerificationResult> {\r\n let manager: 'npm' | 'pnpm' = 'npm';\r\n if (!options.customScript) {\r\n // Judging a tree a different package manager installed would be wrong.\r\n try {\r\n manager = await prepareSupportedPackageManager(rootDir);\r\n } catch (err) {\r\n if (err instanceof UnsupportedPackageManagerError || err instanceof PackageManagerNotFoundError) {\r\n return { status: 'warn', details: err.message, label: options.customLabel || 'Dependency verification' };\r\n }\r\n throw err;\r\n }\r\n }\r\n const defaultLabel =\r\n manager === 'pnpm'\r\n ? 'Lockfile consistency (pnpm install --frozen-lockfile)'\r\n : 'Dependency tree integrity (npm ls)';\r\n const label = options.customLabel || options.customScript || defaultLabel;\r\n\r\n const verify = commands.verify(manager);\r\n const result = options.customScript\r\n ? await runShellScript(options.customScript, { cwd: rootDir, timeoutMs: VERIFY_TIMEOUT_MS })\r\n : await runCommand(verify.command, verify.args, { cwd: rootDir, timeoutMs: VERIFY_TIMEOUT_MS });\r\n\r\n if (result.exitCode === 0) {\r\n const details =\r\n manager === 'pnpm' && !options.customScript\r\n ? 'pnpm-lock.yaml is up to date with all package.json files.'\r\n : 'All dependencies are installed and consistent.';\r\n return { status: 'clean', details, label };\r\n }\r\n const output =\r\n manager === 'pnpm' && !options.customScript\r\n ? tail(`${result.stdout}\\n${result.stderr}`)\r\n : tail(result.stderr || result.stdout);\r\n return { status: 'warn', details: result.timedOut ? 'Verification timed out.' : output, label };\r\n }\r\n}\r\n","/**\r\n * Elevate — npm ecosystem strategy: wires the npm adapters together.\r\n */\r\n\r\nimport type { EcosystemStrategy, TabLabels } from '../../domain/ecosystem-strategy.js';\r\nimport type { Ecosystem } from '../../domain/models.js';\r\nimport { npmVersionPolicy } from '../../domain/version-policy.js';\r\nimport { detectPackageManager } from './npm-package-manager.js';\r\nimport { NpmModuleDiscoveryAdapter } from './npm-discovery.js';\r\nimport { NpmRegistryAdapter } from './npm-registry.js';\r\nimport { NpmDependencyAdapter } from './npm-scanner.js';\r\nimport { NpmUpdaterAdapter } from './npm-updater.js';\r\nimport { NpmVerificationAdapter } from './npm-verifier.js';\r\n\r\nexport class NpmEcosystemStrategy implements EcosystemStrategy {\r\n readonly ecosystem: Ecosystem = 'npm';\r\n readonly displayName = 'Node / npm';\r\n\r\n packageManagerFor(rootDir: string): string {\r\n return detectPackageManager(rootDir).name;\r\n }\r\n\r\n displayNameFor(rootDir: string): string {\r\n return detectPackageManager(rootDir).name === 'pnpm' ? 'Node / pnpm' : 'Node / npm';\r\n }\r\n readonly icon = '📦';\r\n readonly manifestFile = 'package.json';\r\n readonly versioning = npmVersionPolicy;\r\n\r\n readonly discovery = new NpmModuleDiscoveryAdapter();\r\n readonly registry = new NpmRegistryAdapter();\r\n readonly reader = new NpmDependencyAdapter(this.registry, this.registry.config);\r\n readonly updater = new NpmUpdaterAdapter();\r\n readonly verifier = new NpmVerificationAdapter();\r\n\r\n getTabLabels(\r\n counts: { total: number; prodCount: number; devCount: number },\r\n t: any,\r\n ): TabLabels {\r\n return {\r\n all: t.tabs.all(counts.total),\r\n prod: t.tabs.dependencies(counts.prodCount),\r\n dev: t.tabs.devDependencies(counts.devCount),\r\n };\r\n }\r\n}\r\n","/**\r\n * Elevate — Cargo ecosystem strategy: wires the Cargo adapters together.\r\n */\r\n\r\nimport semver from 'semver';\r\nimport type { EcosystemStrategy, TabLabels } from '../../domain/ecosystem-strategy.js';\r\nimport type { Ecosystem } from '../../domain/models.js';\r\nimport type { VersionPolicy } from '../../domain/version-policy.js';\r\nimport { CargoModuleDiscoveryAdapter } from './cargo-discovery.js';\r\nimport { CargoConfigReader } from './cargo-config.js';\r\nimport { CargoIndexClient } from './cargo-index.js';\r\nimport { loadMetadata } from './cargo-metadata.js';\r\nimport { CargoRegistryAdapter } from './cargo-registry.js';\r\nimport { cargoDiff, rewriteRequirement } from './cargo-requirement.js';\r\nimport { CargoDependencyAdapter } from './cargo-scanner.js';\r\nimport { CargoUpdaterAdapter } from './cargo-updater.js';\r\nimport { CargoVerificationAdapter } from './cargo-verifier.js';\r\n\r\nexport const cargoVersionPolicy: VersionPolicy = {\r\n normalize: (v) => semver.valid(v),\r\n rewrite: rewriteRequirement,\r\n diff: (current, target) => (semver.valid(current) && semver.valid(target) ? (semver.eq(current, target) ? 'patch' : cargoDiff(current, target)) : 'minor'),\r\n // Updates are written where the scan found the declaration.\r\n allowsManualTargets: false,\r\n};\r\n\r\nexport class CargoEcosystemStrategy implements EcosystemStrategy {\r\n readonly ecosystem: Ecosystem = 'cargo';\r\n readonly displayName = 'Rust / Cargo';\r\n readonly icon = '🦀';\r\n readonly manifestFile = 'Cargo.toml';\r\n readonly versioning = cargoVersionPolicy;\r\n\r\n private readonly config = new CargoConfigReader();\r\n private readonly index = new CargoIndexClient();\r\n private readonly endpoint = (registry: string | undefined, cwd: string) => this.config.resolve(registry, cwd);\r\n\r\n readonly discovery = new CargoModuleDiscoveryAdapter();\r\n readonly registry = new CargoRegistryAdapter({ index: this.index, endpoint: this.endpoint });\r\n readonly reader = new CargoDependencyAdapter({ loadMetadata, index: this.index, endpoint: this.endpoint });\r\n readonly updater = new CargoUpdaterAdapter();\r\n readonly verifier = new CargoVerificationAdapter();\r\n\r\n getTabLabels(counts: { total: number; prodCount: number; devCount: number }, t: any): TabLabels {\r\n return {\r\n all: t.tabs.all(counts.total),\r\n prod: t.tabs.dependencies(counts.prodCount),\r\n dev: t.tabs.devDependencies(counts.devCount),\r\n };\r\n }\r\n}\r\n","/**\r\n * Elevate — Cargo workspace discovery.\r\n *\r\n * Finds every `Cargo.toml` in the repository (not only at the root, so a Rust\r\n * crate beside a JavaScript app is found) and lets Cargo itself report the\r\n * workspace members: one `cargo metadata` run per workspace.\r\n */\r\n\r\nimport { existsSync, readdirSync, readFileSync } from 'node:fs';\r\nimport { dirname, join, relative, resolve } from 'node:path';\r\nimport type { ModuleDiscoveryPort } from '../../domain/ports.js';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { CargoUnavailableError } from './cargo-command.js';\r\nimport { CargoMetadataError, loadMetadata } from './cargo-metadata.js';\r\n\r\n/** Directories that never hold modules. A manifest below `src` is a test fixture or template. */\r\nconst IGNORED = new Set(['target', 'node_modules', 'vendor', 'dist', 'build', 'out', 'src']);\r\n\r\nconst norm = (path: string) => resolve(path).replace(/\\\\/g, '/');\r\n\r\nfunction findManifests(root: string): string[] {\r\n const found: string[] = [];\r\n const walk = (dir: string, depth: number) => {\r\n let entries;\r\n try {\r\n entries = readdirSync(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n if (entries.some((e) => e.isFile() && e.name === 'Cargo.toml')) found.push(join(dir, 'Cargo.toml'));\r\n for (const entry of entries) {\r\n if (entry.isDirectory() && !entry.name.startsWith('.') && !IGNORED.has(entry.name)) walk(join(dir, entry.name), depth + 1);\r\n }\r\n };\r\n walk(root, 0);\r\n // Shallowest first, so a workspace root is read before the crates inside it.\r\n return found.sort((a, b) => a.split(/[\\\\/]/).length - b.split(/[\\\\/]/).length || a.localeCompare(b));\r\n}\r\n\r\nconst declaresWorkspace = (dir: string) => {\r\n try {\r\n return /^\\s*\\[workspace[\\].]/m.test(readFileSync(join(dir, 'Cargo.toml'), 'utf8'));\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nexport class CargoModuleDiscoveryAdapter implements ModuleDiscoveryPort {\r\n private problems: string[] = [];\r\n\r\n diagnostics(): string[] {\r\n return [...this.problems];\r\n }\r\n\r\n /** The nearest ancestor declaring `[workspace]`; failing that, the nearest directory with a manifest. */\r\n findRoot(startDir: string, boundaryDir: string | undefined): string | undefined {\r\n const boundary = boundaryDir ? resolve(boundaryDir) : undefined;\r\n const chain: string[] = [];\r\n for (let dir = resolve(startDir); ; ) {\r\n chain.push(dir);\r\n const parent = dirname(dir);\r\n if (dir === boundary || parent === dir) break;\r\n dir = parent;\r\n }\r\n return chain.find(declaresWorkspace) ?? chain.find((d) => existsSync(join(d, 'Cargo.toml')));\r\n }\r\n\r\n async discover(rootDir: string): Promise<ProjectModule[]> {\r\n const covered = new Set<string>();\r\n const modules: ProjectModule[] = [];\r\n const errors: CargoMetadataError[] = [];\r\n this.problems = [];\r\n\r\n for (const manifest of findManifests(rootDir)) {\r\n if (covered.has(norm(manifest))) continue;\r\n try {\r\n const metadata = await loadMetadata(dirname(manifest));\r\n for (const pkg of metadata.packages) {\r\n covered.add(norm(pkg.manifest_path));\r\n const path = dirname(pkg.manifest_path);\r\n const relPath = relative(rootDir, path).replace(/\\\\/g, '/');\r\n modules.push({\r\n id: pkg.name,\r\n name: pkg.name,\r\n path,\r\n relPath: relPath === '' ? 'Root' : relPath,\r\n ecosystem: 'cargo',\r\n isRoot: relPath === '',\r\n version: pkg.version,\r\n aggregatorDir: resolve(metadata.workspace_root),\r\n });\r\n }\r\n } catch (err) {\r\n if (err instanceof CargoUnavailableError) throw err;\r\n if (err instanceof CargoMetadataError) {\r\n errors.push(err);\r\n this.problems.push(err.message);\r\n }\r\n else throw err;\r\n }\r\n }\r\n\r\n // Failures are only fatal when they leave nothing to show.\r\n if (modules.length === 0 && errors.length > 0) throw errors[0]!;\r\n modules.sort((a, b) => (a.isRoot ? -1 : b.isRoot ? 1 : a.relPath.localeCompare(b.relPath)));\r\n\r\n // Independent workspaces may each hold a crate of the same name; ids must stay unique.\r\n const taken = new Set<string>();\r\n for (const module of modules) {\r\n if (taken.has(module.id)) module.id = `${module.name} (${module.relPath})`;\r\n taken.add(module.id);\r\n }\r\n return modules;\r\n }\r\n}\r\n","/**\r\n * Elevate — Cargo invocation.\r\n *\r\n * Runs `cargo` from the PATH in a given working directory. Without it, Cargo\r\n * features fail with `CargoUnavailableError` instead of silently degrading.\r\n */\r\n\r\nimport { runCommand } from '../shared/process.js';\r\nimport type { RunResult } from '../shared/process.js';\r\n\r\n/** Thrown when `cargo` cannot be started. */\r\nexport class CargoUnavailableError extends Error {\r\n constructor() {\r\n super('Cargo is not available: no `cargo` on the PATH. Install Rust (https://rustup.rs).');\r\n this.name = 'CargoUnavailableError';\r\n }\r\n}\r\n\r\nexport async function runCargo(args: string[], options: { cwd: string; timeoutMs?: number }): Promise<RunResult> {\r\n let result: RunResult;\r\n try {\r\n result = await runCommand('cargo', args, options);\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') throw new CargoUnavailableError();\r\n throw err;\r\n }\r\n if (looksLikeMissingCommand(result) && !(await cargoStarts(options.cwd))) throw new CargoUnavailableError();\r\n return result;\r\n}\r\n\r\n/**\r\n * On Windows the command runs through cmd.exe, which reports a missing program\r\n * as an ordinary failure (exit code 1 and a message in the user's language), not\r\n * as ENOENT. Cargo itself always prefixes its failures with \"error\", so a failure\r\n * without output on stdout and without that prefix is worth one `cargo --version`.\r\n */\r\nfunction looksLikeMissingCommand(result: RunResult): boolean {\r\n return (\r\n process.platform === 'win32' && result.exitCode !== 0 && !result.stdout.trim() && !/^error/m.test(result.stderr)\r\n );\r\n}\r\n\r\nasync function cargoStarts(cwd: string): Promise<boolean> {\r\n try {\r\n return (await runCommand('cargo', ['--version'], { cwd, timeoutMs: 30_000 })).exitCode === 0;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/** Cargo's error lines for a concise failure message. */\r\nexport function cargoErrors(output: string): string {\r\n const lines = output.split(/\\r?\\n/);\r\n const errors = lines.filter((l) => /^error(\\[E\\d+\\])?:/.test(l));\r\n const summary = (errors.length > 0 ? errors : lines.filter((l) => l.trim()).slice(-10)).slice(0, 12);\r\n if (/toolchain '.+' is not installed/.test(output)) {\r\n summary.push('Install it with `rustup toolchain install` (the project pins it in rust-toolchain.toml).');\r\n }\r\n return summary.join('\\n');\r\n}\r\n","/**\r\n * Elevate — `cargo metadata --no-deps`.\r\n *\r\n * Works without network access and without a Cargo.lock, resolves\r\n * `workspace = true` inheritance, and reports each dependency with its\r\n * normalised requirement, kind, target and source.\r\n */\r\n\r\nimport { runCargo, cargoErrors } from './cargo-command.js';\r\n\r\nexport interface MetadataDependency {\r\n name: string;\r\n req: string;\r\n kind: 'dev' | 'build' | null;\r\n rename: string | null;\r\n /** `registry+…crates.io-index`, `sparse+<url>`, `git+…`; null for path dependencies. */\r\n source: string | null;\r\n /** Index URL of an alternative registry. */\r\n registry?: string | null;\r\n path?: string;\r\n target: string | null;\r\n optional: boolean;\r\n}\r\n\r\nexport interface MetadataPackage {\r\n name: string;\r\n version: string;\r\n manifest_path: string;\r\n rust_version: string | null;\r\n dependencies: MetadataDependency[];\r\n}\r\n\r\nexport interface CargoMetadata {\r\n packages: MetadataPackage[];\r\n workspace_root: string;\r\n}\r\n\r\nexport class CargoMetadataError extends Error {\r\n constructor(message: string, readonly dir: string) {\r\n super(message);\r\n this.name = 'CargoMetadataError';\r\n }\r\n}\r\n\r\nexport async function loadMetadata(dir: string): Promise<CargoMetadata> {\r\n const result = await runCargo(['metadata', '--no-deps', '--format-version', '1'], { cwd: dir, timeoutMs: 60_000 });\r\n if (result.exitCode !== 0) {\r\n throw new CargoMetadataError(`cargo metadata failed in ${dir}: ${cargoErrors(result.stderr || result.stdout)}`, dir);\r\n }\r\n try {\r\n return JSON.parse(result.stdout) as CargoMetadata;\r\n } catch {\r\n throw new CargoMetadataError(`cargo metadata printed no JSON in ${dir}.`, dir);\r\n }\r\n}\r\n","/**\r\n * Elevate — Cargo registry configuration.\r\n *\r\n * `cargo metadata` does not show source replacement, and `cargo config get`\r\n * is nightly-only, so the few settings that decide where a lookup goes are\r\n * read from the configuration files and environment directly.\r\n *\r\n * The reader is deliberately narrow and fails closed: a replacement it cannot\r\n * interpret (a vendored directory, a local registry, a git source) is refused.\r\n * Falling back to crates.io would bypass the mirror or air gap the project\r\n * was set up with.\r\n */\r\n\r\nimport { existsSync, readFileSync } from 'node:fs';\r\nimport { homedir } from 'node:os';\r\nimport { dirname, isAbsolute, join, resolve } from 'node:path';\r\nimport { getStaticTOMLValue, parseTOML } from 'toml-eslint-parser';\r\n\r\nconst CRATES_IO = 'registry+https://github.com/rust-lang/crates.io-index';\r\nconst PUBLIC_HOSTS = new Set(['index.crates.io', 'static.crates.io', 'crates.io', 'github.com']);\r\n\r\nexport class UnsupportedSourceError extends Error {\r\n constructor(detail: string) {\r\n super(`Cargo is configured to use a package source Elevate cannot read (${detail}). No lookup was made.`);\r\n this.name = 'UnsupportedSourceError';\r\n }\r\n}\r\n\r\ntype Table = Record<string, any>;\r\n\r\nfunction isPublicIndex(index: string): boolean {\r\n try {\r\n const url = new URL(index.replace(/^(sparse|registry)\\+/, ''));\r\n return PUBLIC_HOSTS.has(url.hostname.toLowerCase()) && (url.hostname !== 'github.com' || url.pathname.includes('crates.io-index'));\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/** Overlays `top` onto `base` key by key. */\r\nfunction merge(base: Table, top: Table): Table {\r\n const out: Table = { ...base };\r\n for (const [key, value] of Object.entries(top)) {\r\n const existing = out[key];\r\n out[key] =\r\n value && typeof value === 'object' && !Array.isArray(value) && existing && typeof existing === 'object' && !Array.isArray(existing)\r\n ? merge(existing, value)\r\n : value;\r\n }\r\n return out;\r\n}\r\n\r\nfunction loadFile(file: string, depth = 0): Table {\r\n let table: Table;\r\n try {\r\n table = getStaticTOMLValue(parseTOML(readFileSync(file, 'utf8'))) as Table;\r\n } catch {\r\n return {};\r\n }\r\n const includes: unknown = table.include;\r\n delete table.include;\r\n if (!Array.isArray(includes) || depth > 4) return table;\r\n let included: Table = {};\r\n for (const entry of includes) {\r\n const path = typeof entry === 'string' ? entry : entry?.path;\r\n if (typeof path === 'string') included = merge(included, loadFile(isAbsolute(path) ? path : resolve(dirname(file), path), depth + 1));\r\n }\r\n return merge(included, table);\r\n}\r\n\r\nexport class CargoConfigReader {\r\n private readonly env: NodeJS.ProcessEnv;\r\n private readonly cache = new Map<string, Table>();\r\n\r\n constructor(options: { env?: NodeJS.ProcessEnv } = {}) {\r\n this.env = options.env ?? process.env;\r\n }\r\n\r\n /** The configuration as Cargo would merge it for `cwd`: nearest file first, CARGO_HOME last. */\r\n private config(cwd: string): Table {\r\n const start = resolve(cwd);\r\n let cached = this.cache.get(start);\r\n if (cached) return cached;\r\n const files: string[] = [];\r\n for (let dir = start; ; ) {\r\n for (const name of ['config.toml', 'config']) {\r\n const file = join(dir, '.cargo', name);\r\n if (existsSync(file)) {\r\n files.push(file);\r\n break;\r\n }\r\n }\r\n const parent = dirname(dir);\r\n if (parent === dir) break;\r\n dir = parent;\r\n }\r\n const home = this.env.CARGO_HOME ?? join(homedir(), '.cargo');\r\n for (const name of ['config.toml', 'config']) {\r\n const file = join(home, name);\r\n if (existsSync(file) && !files.includes(file)) {\r\n files.push(file);\r\n break;\r\n }\r\n }\r\n // Later entries have lower precedence, so apply them first.\r\n cached = files.reduceRight((acc, file) => merge(acc, loadFile(file)), {} as Table);\r\n this.cache.set(start, cached);\r\n return cached;\r\n }\r\n\r\n /** `[source.*]` comes from files only: Cargo ignores `CARGO_SOURCE_*` variables (checked with Cargo 1.97). */\r\n private sourceField(config: Table, source: string, field: string): string | undefined {\r\n const value = config.source?.[source]?.[field];\r\n return typeof value === 'string' ? value : undefined;\r\n }\r\n\r\n /**\r\n * The index a lookup goes to. `registry` is the index URL of an alternative\r\n * registry as Cargo reports it, or undefined for crates.io.\r\n */\r\n async resolve(registry: string | undefined, cwd: string): Promise<{ index: string; isPublic: boolean }> {\r\n const config = this.config(cwd);\r\n let name = registry === undefined ? 'crates-io' : this.sourceNamed(config, registry);\r\n let index = registry ?? CRATES_IO;\r\n const seen = new Set<string>();\r\n\r\n while (name !== undefined) {\r\n if (seen.has(name)) throw new UnsupportedSourceError(`replacement cycle at '${name}'`);\r\n seen.add(name);\r\n const next = this.sourceField(config, name, 'replace-with');\r\n if (next === undefined) break;\r\n for (const kind of ['directory', 'local-registry', 'git']) {\r\n if (this.sourceField(config, next, kind) !== undefined) throw new UnsupportedSourceError(`'${next}' is a ${kind} source`);\r\n }\r\n const target = this.sourceField(config, next, 'registry');\r\n if (target !== undefined) {\r\n index = target;\r\n name = next;\r\n // A source that is itself replaced continues the chain; one that is not ends it.\r\n if (this.sourceField(config, next, 'replace-with') === undefined) break;\r\n continue;\r\n }\r\n if (this.sourceField(config, next, 'replace-with') === undefined) {\r\n throw new UnsupportedSourceError(`'${next}' has no registry`);\r\n }\r\n name = next;\r\n }\r\n return { index, isPublic: isPublicIndex(index) };\r\n }\r\n\r\n /** Name of the `[source.*]` table whose registry is `url`, if any. */\r\n private sourceNamed(config: Table, url: string): string | undefined {\r\n return Object.keys(config.source ?? {}).find((n) => this.sourceField(config, n, 'registry') === url);\r\n }\r\n}\r\n","/**\r\n * Elevate — the product version.\r\n *\r\n * Bundled builds get it injected at build time (`__ELEVATE_VERSION__`), because\r\n * no package.json lies next to a bundle or a standalone binary. From source it\r\n * is read from package.json.\r\n */\r\n\r\nimport { createRequire } from 'node:module';\r\n\r\ndeclare const __ELEVATE_VERSION__: string | undefined;\r\n\r\nfunction fromPackage(): string {\r\n try {\r\n return (createRequire(import.meta.url)('../package.json') as { version: string }).version;\r\n } catch {\r\n return '0.0.0';\r\n }\r\n}\r\n\r\nexport const VERSION: string = typeof __ELEVATE_VERSION__ === 'string' ? __ELEVATE_VERSION__ : fromPackage();\r\n","/**\r\n * Elevate — Cargo sparse index client.\r\n *\r\n * Reads one index file per crate over HTTP. It sends no credentials: a\r\n * registry that asks for authentication is reported as such instead of being\r\n * served, so Elevate never handles registry tokens.\r\n */\r\n\r\nimport { VERSION } from '../../version.js';\r\n\r\nexport interface IndexVersion {\r\n version: string;\r\n yanked: boolean;\r\n /** Minimum supported Rust version the crate declares. */\r\n rustVersion: string | undefined;\r\n}\r\n\r\nexport class RegistryAuthRequiredError extends Error {\r\n constructor(readonly index: string) {\r\n super(`The registry ${index} requires authentication. Elevate does not handle registry credentials.`);\r\n this.name = 'RegistryAuthRequiredError';\r\n }\r\n}\r\n\r\nexport class CrateNotFoundError extends Error {\r\n constructor(readonly crate: string, readonly index: string) {\r\n super(`'${crate}' is not in the registry ${index}.`);\r\n this.name = 'CrateNotFoundError';\r\n }\r\n}\r\n\r\nexport class UnsupportedIndexError extends Error {\r\n constructor(readonly index: string) {\r\n super(`The registry index ${index} is not a sparse index; Elevate cannot read it.`);\r\n this.name = 'UnsupportedIndexError';\r\n }\r\n}\r\n\r\nconst CRATES_IO_SPARSE = 'https://index.crates.io/';\r\nconst CRATES_IO_GIT = 'registry+https://github.com/rust-lang/crates.io-index';\r\n\r\n/** Path of a crate's index file below the index root. */\r\nexport function indexPath(name: string): string {\r\n const n = name.toLowerCase();\r\n if (n.length <= 2) return `${n.length}/${n}`;\r\n if (n.length === 3) return `3/${n[0]}/${n}`;\r\n return `${n.slice(0, 2)}/${n.slice(2, 4)}/${n}`;\r\n}\r\n\r\nexport function parseIndex(text: string): IndexVersion[] {\r\n const versions: IndexVersion[] = [];\r\n for (const raw of text.split(/\\r?\\n/)) {\r\n if (!raw.trim()) continue;\r\n try {\r\n const entry = JSON.parse(raw);\r\n if (typeof entry.vers !== 'string') continue;\r\n versions.push({ version: entry.vers, yanked: entry.yanked === true, rustVersion: entry.rust_version });\r\n } catch {\r\n // A line that is not JSON says nothing about the others.\r\n }\r\n }\r\n return versions;\r\n}\r\n\r\n/** Turns an index URL as Cargo prints it into the root of a sparse index. */\r\nfunction sparseRoot(index: string): string {\r\n if (index === CRATES_IO_GIT) return CRATES_IO_SPARSE;\r\n if (index.startsWith('sparse+')) {\r\n const url = index.slice('sparse+'.length);\r\n return url.endsWith('/') ? url : `${url}/`;\r\n }\r\n throw new UnsupportedIndexError(index);\r\n}\r\n\r\nconst userAgent = () => `elevate/${VERSION} (+https://github.com/DennisRepa/Elevate)`;\r\n\r\nfunction networkReason(err: unknown): string {\r\n const cause = (err as { cause?: { message?: string } })?.cause?.message;\r\n return cause ?? (err instanceof Error ? err.message : String(err));\r\n}\r\n\r\nexport class CargoIndexClient {\r\n private readonly memo = new Map<string, Promise<IndexVersion[]>>();\r\n\r\n constructor(\r\n private readonly fetchFn: typeof fetch = fetch,\r\n private readonly env: NodeJS.ProcessEnv = process.env,\r\n ) {}\r\n\r\n /** All versions of a crate in oldest-first file order. Memoised per index and crate. */\r\n versions(index: string, crate: string): Promise<IndexVersion[]> {\r\n const key = `${index}\\n${crate.toLowerCase()}`;\r\n let pending = this.memo.get(key);\r\n if (!pending) {\r\n pending = this.load(index, crate);\r\n this.memo.set(key, pending);\r\n }\r\n return pending;\r\n }\r\n\r\n private async load(index: string, crate: string): Promise<IndexVersion[]> {\r\n const url = `${sparseRoot(index)}${indexPath(crate)}`;\r\n let response: Response;\r\n try {\r\n response = await this.fetchFn(url, { headers: { 'user-agent': userAgent() } });\r\n } catch (err) {\r\n throw new Error(`Cannot reach ${url}: ${networkReason(err)}${this.proxyHint()}`);\r\n }\r\n if (response.status === 401 || response.status === 403) throw new RegistryAuthRequiredError(index);\r\n if (response.status === 404) throw new CrateNotFoundError(crate, index);\r\n if (!response.ok) throw new Error(`Registry answered ${response.status} for ${url}.`);\r\n return parseIndex(await response.text());\r\n }\r\n\r\n /**\r\n * Node's fetch ignores HTTP(S)_PROXY unless NODE_USE_ENV_PROXY=1 is set when\r\n * the process starts (measured with Node 22.23; it cannot be switched on later).\r\n */\r\n private proxyHint(): string {\r\n const proxied = this.env.HTTPS_PROXY || this.env.https_proxy || this.env.HTTP_PROXY || this.env.http_proxy;\r\n if (!proxied || this.env.NODE_USE_ENV_PROXY === '1') return '';\r\n return ' A proxy is configured, but Node does not use it for registry lookups unless you start Elevate with NODE_USE_ENV_PROXY=1.';\r\n }\r\n}\r\n","/**\r\n * Elevate — Cargo registry adapter for ad-hoc version queries\r\n * (`elevate versions`, MCP `elevate_get_versions`, the version picker).\r\n */\r\n\r\nimport semver from 'semver';\r\nimport type { RegistryEndpoint, RegistryPort } from '../../domain/ports.js';\r\nimport type { DependencyCoordinate, ReleaseChannel } from '../../domain/models.js';\r\nimport type { IndexVersion } from './cargo-index.js';\r\nimport { selectVersion } from './cargo-versions.js';\r\n\r\nexport interface CargoRegistryDeps {\r\n index: { versions(index: string, crate: string): Promise<IndexVersion[]> };\r\n endpoint(registry: string | undefined, cwd: string): Promise<{ index: string; isPublic: boolean }>;\r\n}\r\n\r\nexport class CargoRegistryAdapter implements RegistryPort {\r\n constructor(private readonly deps: CargoRegistryDeps) {}\r\n\r\n async resolveEndpoint(coordinate: DependencyCoordinate, cwd: string): Promise<RegistryEndpoint> {\r\n const { index, isPublic } = await this.deps.endpoint(coordinate.registry, cwd);\r\n return { url: index, isPublic };\r\n }\r\n\r\n async getLatestVersion(\r\n coordinate: DependencyCoordinate,\r\n channel: ReleaseChannel = 'stable',\r\n cwd = process.cwd(),\r\n ): Promise<string | null> {\r\n return selectVersion(await this.load(coordinate, cwd), { channel }).version ?? null;\r\n }\r\n\r\n /** Published, not yanked, newest first. Lookup errors propagate so they are not mistaken for \"no versions\". */\r\n async getAllVersions(coordinate: DependencyCoordinate, cwd = process.cwd()): Promise<string[]> {\r\n return (await this.load(coordinate, cwd))\r\n .filter((v) => !v.yanked && semver.valid(v.version))\r\n .map((v) => v.version)\r\n .sort(semver.rcompare);\r\n }\r\n\r\n private async load(coordinate: DependencyCoordinate, cwd: string): Promise<IndexVersion[]> {\r\n const { index } = await this.deps.endpoint(coordinate.registry, cwd);\r\n return this.deps.index.versions(index, coordinate.artifact);\r\n }\r\n}\r\n","/**\r\n * Elevate — chooses the version to offer from a crate's index entries.\r\n */\r\n\r\nimport semver from 'semver';\r\nimport type { ReleaseChannel } from '../../domain/models.js';\r\nimport type { IndexVersion } from './cargo-index.js';\r\n\r\nexport interface Selection {\r\n version: string | undefined;\r\n /** The newest candidate that was passed over because it needs a newer rustc than the project declares. */\r\n blockedByMsrv?: { version: string; requires: string };\r\n}\r\n\r\nconst rust = (v: string) => semver.coerce(v)?.version;\r\n\r\n/** Versions the project could take, newest first: not yanked, in the channel, and not needing a newer Rust than declared. */\r\nexport function eligibleVersions(\r\n versions: readonly IndexVersion[],\r\n options: { channel: ReleaseChannel; rustVersion?: string },\r\n): string[] {\r\n const project = options.rustVersion ? rust(options.rustVersion) : undefined;\r\n return versions\r\n .filter((v) => !v.yanked && semver.valid(v.version))\r\n .filter((v) => options.channel === 'all' || semver.prerelease(v.version) === null)\r\n .filter((v) => {\r\n const needs = v.rustVersion ? rust(v.rustVersion) : undefined;\r\n return !(project && needs && semver.gt(needs, project));\r\n })\r\n .map((v) => v.version)\r\n .sort(semver.rcompare);\r\n}\r\n\r\nexport function selectVersion(\r\n versions: readonly IndexVersion[],\r\n options: { channel: ReleaseChannel; rustVersion?: string },\r\n): Selection {\r\n const candidates = versions\r\n .filter((v) => !v.yanked && semver.valid(v.version))\r\n .filter((v) => options.channel === 'all' || semver.prerelease(v.version) === null)\r\n .sort((a, b) => semver.rcompare(a.version, b.version));\r\n\r\n const project = options.rustVersion ? rust(options.rustVersion) : undefined;\r\n let blocked: Selection['blockedByMsrv'];\r\n for (const candidate of candidates) {\r\n const needs = candidate.rustVersion ? rust(candidate.rustVersion) : undefined;\r\n if (project && needs && semver.gt(needs, project)) {\r\n blocked ??= { version: candidate.version, requires: candidate.rustVersion! };\r\n continue;\r\n }\r\n return { version: candidate.version, ...(blocked ? { blockedByMsrv: blocked } : {}) };\r\n }\r\n return { version: undefined, ...(blocked ? { blockedByMsrv: blocked } : {}) };\r\n}\r\n","/**\r\n * Elevate — Cargo version requirements.\r\n *\r\n * Cargo's syntax differs from npm's where it matters: a bare `1.2.3` means\r\n * `^1.2.3` (npm's `semver` reads it as exact), and `0.x` versions break at the\r\n * first non-zero component. Everything that touches a Cargo requirement goes\r\n * through this module so the `semver` package is never handed a raw Cargo string.\r\n */\r\n\r\nimport semver from 'semver';\r\nimport type { VersionDiff } from '../../domain/models.js';\r\n\r\n/** One comparator, operator bare/`^`/`~`/`=`, one to three numeric components. */\r\nconst SIMPLE = /^(\\^|~|=)?\\s*(\\d+(?:\\.\\d+){0,2})$/;\r\n\r\n/** Translates a Cargo requirement into a range the `semver` package understands. */\r\nexport function toSemverRange(requirement: string): string | null {\r\n const parts = requirement.split(',').map((p) => p.trim());\r\n if (parts.some((p) => p === '')) return null;\r\n const converted = parts.map((part) => {\r\n const bare = part.match(/^\\d/);\r\n return bare ? `^${part}` : part;\r\n });\r\n return semver.validRange(converted.join(' ')) ? converted.join(' ') : null;\r\n}\r\n\r\n/** Whether `version` satisfies the Cargo requirement. */\r\nexport function satisfiesRequirement(requirement: string, version: string): boolean {\r\n const range = toSemverRange(requirement);\r\n return range !== null && semver.satisfies(version, range, { includePrerelease: false });\r\n}\r\n\r\n/** Only a single plain comparator can be rewritten; wildcards and compound requirements are left alone. */\r\nexport function isUpgradableRequirement(requirement: string): boolean {\r\n return SIMPLE.test(requirement.trim());\r\n}\r\n\r\n/** The lowest version the requirement allows, or null if it is not a valid requirement. */\r\nexport function requirementFloor(requirement: string): string | null {\r\n const range = toSemverRange(requirement);\r\n return range ? (semver.minVersion(range)?.version ?? null) : null;\r\n}\r\n\r\n/**\r\n * Writes `target` in the style of `current`: same operator, same number of\r\n * components (`1` -> `2`, `1.0` -> `2.3`, `1.0.100` -> `1.0.229`). A pre-release\r\n * target is written in full. When the result still allows the target and equals\r\n * `current`, there is nothing to change.\r\n */\r\nexport function rewriteRequirement(current: string, target: string): string {\r\n const match = current.trim().match(SIMPLE);\r\n if (!match) return target;\r\n if (semver.prerelease(target)) return `${match[1] ?? ''}${target}`;\r\n const precision = match[2]!.split('.').length;\r\n const [major, minor, patch] = target.split(/[-+]/)[0]!.split('.');\r\n const written = [major, minor, patch].slice(0, precision).join('.');\r\n return `${match[1] ?? ''}${written}`;\r\n}\r\n\r\n/** Difference of two versions by Cargo's compatibility rule (leftmost non-zero component breaks). */\r\nexport function cargoDiff(from: string, to: string): VersionDiff {\r\n const a = semver.parse(from);\r\n const b = semver.parse(to);\r\n if (!a || !b) return 'minor';\r\n if (a.major > 0 || b.major > a.major) {\r\n if (b.major !== a.major) return 'major';\r\n return b.minor !== a.minor ? 'minor' : 'patch';\r\n }\r\n if (a.minor > 0) {\r\n if (b.minor !== a.minor) return 'major';\r\n return 'minor';\r\n }\r\n return 'major';\r\n}\r\n","/**\r\n * Elevate — Cargo dependency scanner.\r\n *\r\n * `cargo metadata` says which dependencies a crate has and where each comes\r\n * from; the Cargo.toml text says where the version is written. Both are\r\n * combined: a dependency becomes a candidate only when its declaration was\r\n * found and agrees with what Cargo resolved.\r\n *\r\n * - workspace: a path dependency on a member. Cargo refuses a `version` that\r\n * excludes the member's version, so such a literal is offered for alignment.\r\n * - private: a crate from an alternative registry, or named by `internalScopes`.\r\n * It is looked up only in its own registry, never on a public one.\r\n * - public: everything else, looked up in the registry Cargo would use.\r\n */\r\n\r\nimport { readFileSync } from 'node:fs';\r\nimport { join, relative } from 'node:path';\r\nimport semver from 'semver';\r\nimport type { DependencyReaderPort, ScanContext } from '../../domain/ports.js';\r\nimport type {\r\n DependencyOrigin,\r\n ProjectModule,\r\n ScanResult,\r\n SkippedDependency,\r\n UpdateCandidate,\r\n VersionDeclaration,\r\n} from '../../domain/models.js';\r\nimport { matchesInternalScope } from '../../domain/origin.js';\r\nimport { extractPreReleaseTag } from '../../domain/versions.js';\r\nimport { mapPooled } from '../shared/pool.js';\r\nimport type { IndexVersion } from './cargo-index.js';\r\nimport type { CargoMetadata, MetadataDependency, MetadataPackage } from './cargo-metadata.js';\r\nimport {\r\n cargoDiff,\r\n isUpgradableRequirement,\r\n requirementFloor,\r\n rewriteRequirement,\r\n satisfiesRequirement,\r\n toSemverRange,\r\n} from './cargo-requirement.js';\r\nimport { parseCargoManifest } from './cargo-toml.js';\r\nimport type { DependencyDeclaration, DependencySection } from './cargo-toml.js';\r\nimport { readLockedVersions } from './cargo-lockfile.js';\r\nimport { eligibleVersions, selectVersion } from './cargo-versions.js';\r\n\r\nconst CONCURRENCY = 6;\r\nconst DIFF_ORDER: Record<string, number> = { major: 0, minor: 1, patch: 2 };\r\n\r\nexport interface CargoScannerDeps {\r\n loadMetadata(dir: string): Promise<CargoMetadata>;\r\n index: { versions(index: string, crate: string): Promise<IndexVersion[]> };\r\n /** The index a lookup goes to: the alternative registry's, or the one Cargo uses for crates.io. */\r\n endpoint(registry: string | undefined, cwd: string): Promise<{ index: string; isPublic: boolean }>;\r\n}\r\n\r\ntype Outcome = { candidate: UpdateCandidate; note?: SkippedDependency } | { skipped: SkippedDependency } | null;\r\n\r\nexport class CargoDependencyAdapter implements DependencyReaderPort {\r\n constructor(private readonly deps: CargoScannerDeps) {}\r\n\r\n async scan(module: ProjectModule, context: ScanContext): Promise<ScanResult> {\r\n const metadata = await this.deps.loadMetadata(module.aggregatorDir ?? module.path);\r\n const pkg = metadata.packages.find((p) => samePath(join(p.manifest_path, '..'), module.path));\r\n if (!pkg) return { candidates: [], skipped: [] };\r\n\r\n const own = readDeclarations(pkg.manifest_path);\r\n const locks = readLockedVersions(join(metadata.workspace_root, 'Cargo.lock'));\r\n const rootManifest = join(metadata.workspace_root, 'Cargo.toml');\r\n const root = readDeclarations(rootManifest);\r\n const groups = groupDependencies(pkg.dependencies);\r\n\r\n const outcomes = await mapPooled(groups, CONCURRENCY, async (group): Promise<Outcome> => {\r\n const primary = group.find((d) => d.kind === null) ?? group[0]!;\r\n const key = primary.rename ?? primary.name;\r\n const decl = findDeclaration(own, key, primary);\r\n const located = locate(decl, root, key, context.rootDir, pkg.manifest_path, rootManifest);\r\n const scope = group.every((d) => d.kind === 'dev') ? 'dev' : 'prod';\r\n const qualifier = primary.target ?? (primary.kind === 'build' ? 'build' : undefined);\r\n const common = { scope, qualifier } as const;\r\n\r\n if (primary.source === null && primary.path) {\r\n // Matched by location: a path dependency elsewhere that shares a member's name is not that member.\r\n const target = [...context.workspace.values()].find((m) => samePath(m.path, primary.path!));\r\n return target ? alignment(primary, target, located, common) : null;\r\n }\r\n if (!primary.source || primary.source.startsWith('git+')) return null;\r\n const outcome = await this.registryOutcome(primary, located, pkg, metadata, locks, common, context);\r\n const other = group.find((d) => d !== primary && !sameRequirement(d.req, primary.req));\r\n if (outcome && 'candidate' in outcome && other) {\r\n // Only the declarations that match the scanned requirement are rewritten; say what is left.\r\n outcome.note = {\r\n identifier: primary.name,\r\n origin: outcome.candidate.origin.kind,\r\n reason: 'declaration-mismatch',\r\n detail: `${sectionOf(other)} requires ${other.req}; it is not changed`,\r\n };\r\n }\r\n return outcome;\r\n });\r\n\r\n const candidates: UpdateCandidate[] = [];\r\n const skipped: SkippedDependency[] = [];\r\n for (const outcome of outcomes) {\r\n if (!outcome) continue;\r\n if ('candidate' in outcome) {\r\n candidates.push(outcome.candidate);\r\n if (outcome.note) skipped.push(outcome.note);\r\n }\r\n else skipped.push(outcome.skipped);\r\n }\r\n candidates.sort((a, b) => (DIFF_ORDER[a.diff] ?? 3) - (DIFF_ORDER[b.diff] ?? 3));\r\n return { candidates, skipped };\r\n }\r\n\r\n private async registryOutcome(\r\n dep: MetadataDependency,\r\n located: Located | undefined,\r\n pkg: MetadataPackage,\r\n metadata: CargoMetadata,\r\n locks: Map<string, string[]>,\r\n common: { scope: 'prod' | 'dev'; qualifier: string | undefined },\r\n context: ScanContext,\r\n ): Promise<Outcome> {\r\n const literal = located?.version.value ?? dep.req;\r\n if (!isUpgradableRequirement(literal)) return null;\r\n\r\n if (!located || !sameRequirement(located.version.value, dep.req)) {\r\n return { skipped: { identifier: dep.name, origin: 'public', reason: 'declaration-mismatch', detail: `${literal} in the manifest, ${dep.req} for Cargo` } };\r\n }\r\n\r\n let origin: DependencyOrigin = { kind: 'public' };\r\n if (dep.registry) origin = { kind: 'private', matchedBy: 'scoped-registry', registry: dep.registry };\r\n else if (matchesInternalScope(dep.name, 'cargo', context.internalScopes)) origin = { kind: 'private', matchedBy: 'internal-scope' };\r\n\r\n const endpoint = await this.deps.endpoint(dep.registry ?? undefined, context.rootDir);\r\n if (origin.kind === 'private' && endpoint.isPublic) {\r\n // Asking a public registry about an internal name is what dependency confusion exploits.\r\n return { skipped: { identifier: dep.name, origin: 'private', reason: 'private-on-public-registry', detail: endpoint.index } };\r\n }\r\n\r\n let versions: IndexVersion[];\r\n try {\r\n versions = await this.deps.index.versions(endpoint.index, dep.name);\r\n } catch (err) {\r\n return { skipped: { identifier: dep.name, origin: origin.kind, reason: 'lookup-failed', detail: err instanceof Error ? err.message : String(err) } };\r\n }\r\n\r\n const chosen = selectVersion(versions, { channel: context.channel, rustVersion: pkg.rust_version ?? undefined });\r\n const floor = requirementFloor(literal);\r\n if (!chosen.version) {\r\n if (chosen.blockedByMsrv && floor) {\r\n const { version, requires } = chosen.blockedByMsrv;\r\n return { skipped: { identifier: dep.name, origin: origin.kind, reason: 'incompatible-rust-version', detail: ` (${version} needs Rust ${requires})` } };\r\n }\r\n return { skipped: { identifier: dep.name, origin: origin.kind, reason: 'lookup-failed', detail: 'no usable version in the registry' } };\r\n }\r\n\r\n const latest = chosen.version;\r\n if (!floor || !semver.gt(latest, floor)) {\r\n // Nothing usable is newer, but a release held back by the project's Rust version is worth a note.\r\n const held = chosen.blockedByMsrv;\r\n if (floor && held && semver.gt(held.version, floor)) {\r\n return { skipped: { identifier: dep.name, origin: origin.kind, reason: 'incompatible-rust-version', detail: ` (${held.version} needs Rust ${held.requires})` } };\r\n }\r\n return yankedLock(dep, literal, origin, versions, locks);\r\n }\r\n const newRange = rewriteRequirement(literal, latest);\r\n // The requirement already allows the newest release: only the lock file can be behind.\r\n if (newRange === literal) return lockOutcome(dep, literal, origin, versions, pkg, metadata, locks, common, context);\r\n\r\n const tag = semver.prerelease(latest) ? (extractPreReleaseTag(latest) ?? 'PRE') : undefined;\r\n const diff = cargoDiff(floor, latest);\r\n const candidate: UpdateCandidate = {\r\n coordinate: { identifier: dep.name, artifact: dep.name, ecosystem: 'cargo', ...(dep.registry ? { registry: dep.registry } : {}) },\r\n currentRange: literal,\r\n currentClean: floor,\r\n latest,\r\n newRange,\r\n diff,\r\n scope: common.scope,\r\n selected: diff !== 'major',\r\n origin,\r\n action: 'update',\r\n declaration: located.declaration,\r\n isPreRelease: tag !== undefined,\r\n preReleaseTag: tag,\r\n ...(common.qualifier ? { qualifier: common.qualifier } : {}),\r\n ...(located.inherited ? { sharedWith: sharersOf(metadata, pkg, dep.rename ?? dep.name) } : {}),\r\n };\r\n return { candidate };\r\n }\r\n}\r\n\r\n/**\r\n * The lock file holds an older version than the requirement allows. Offered only when the\r\n * requirement itself needs no change, so a crate never appears twice.\r\n */\r\nfunction lockOutcome(\r\n dep: MetadataDependency,\r\n requirement: string,\r\n origin: DependencyOrigin,\r\n versions: IndexVersion[],\r\n pkg: MetadataPackage,\r\n metadata: CargoMetadata,\r\n locks: Map<string, string[]>,\r\n common: { scope: 'prod' | 'dev'; qualifier: string | undefined },\r\n context: ScanContext,\r\n): Outcome {\r\n const locked = (locks.get(dep.name) ?? []).filter((v) => satisfiesRequirement(requirement, v)).sort(semver.rcompare)[0];\r\n if (!locked) return null;\r\n\r\n const options = { channel: context.channel, rustVersion: pkg.rust_version ?? undefined };\r\n const allowed = versions.filter((v) => satisfiesRequirement(requirement, v.version));\r\n const newer = eligibleVersions(allowed, options).filter((v) => semver.gt(v, locked));\r\n const latest = newer[0];\r\n if (!latest) return yankedLock(dep, requirement, origin, versions, locks);\r\n\r\n const lockFile = join(metadata.workspace_root, 'Cargo.lock');\r\n return {\r\n candidate: {\r\n coordinate: { identifier: dep.name, artifact: dep.name, ecosystem: 'cargo', ...(dep.registry ? { registry: dep.registry } : {}) },\r\n currentRange: locked,\r\n currentClean: locked,\r\n latest,\r\n newRange: latest,\r\n diff: cargoDiff(locked, latest),\r\n scope: common.scope,\r\n // A release the requirement allows is compatible by definition, so it is safe to preselect.\r\n selected: true,\r\n origin,\r\n action: 'lock',\r\n declaration: { file: lockFile, kind: 'lockfile', displayPath: display(context.rootDir, lockFile) },\r\n availableVersions: newer,\r\n ...(common.qualifier ? { qualifier: common.qualifier } : {}),\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * The locked release was yanked and nothing the requirement allows can replace it. Cargo still\r\n * builds from the lock file, so this is a warning rather than an update.\r\n */\r\nfunction yankedLock(\r\n dep: MetadataDependency,\r\n requirement: string,\r\n origin: DependencyOrigin,\r\n versions: IndexVersion[],\r\n locks: Map<string, string[]>,\r\n): Outcome {\r\n const locked = (locks.get(dep.name) ?? []).filter((v) => satisfiesRequirement(requirement, v)).sort(semver.rcompare)[0];\r\n if (!locked || !versions.some((v) => v.yanked && v.version === locked)) return null;\r\n return { skipped: { identifier: dep.name, origin: origin.kind, reason: 'locked-version-yanked', detail: locked } };\r\n}\r\n\r\ninterface Located {\r\n version: { value: string; start: number; end: number };\r\n declaration: VersionDeclaration;\r\n inherited: boolean;\r\n}\r\n\r\nfunction alignment(\r\n dep: MetadataDependency,\r\n target: ProjectModule,\r\n located: Located | undefined,\r\n common: { scope: 'prod' | 'dev'; qualifier: string | undefined },\r\n): Outcome {\r\n const local = target.version;\r\n if (!located || !local || !semver.valid(local)) return null;\r\n const literal = located.version.value;\r\n if (!isUpgradableRequirement(literal) || satisfiesRequirement(literal, local)) return null;\r\n\r\n const floor = requirementFloor(literal) ?? '0.0.0';\r\n const diff = cargoDiff(floor, local);\r\n const tag = semver.prerelease(local) ? (extractPreReleaseTag(local) ?? 'PRE') : undefined;\r\n return {\r\n candidate: {\r\n coordinate: { identifier: dep.name, artifact: dep.name, ecosystem: 'cargo' },\r\n currentRange: literal,\r\n currentClean: floor,\r\n latest: local,\r\n newRange: rewriteRequirement(literal, local),\r\n diff,\r\n scope: common.scope,\r\n selected: diff !== 'major',\r\n origin: { kind: 'workspace', moduleId: target.id, moduleRelPath: target.relPath },\r\n action: 'align',\r\n declaration: located.declaration,\r\n availableVersions: [local],\r\n isPreRelease: tag !== undefined,\r\n preReleaseTag: tag,\r\n ...(common.qualifier ? { qualifier: common.qualifier } : {}),\r\n },\r\n };\r\n}\r\n\r\nfunction groupDependencies(deps: MetadataDependency[]): MetadataDependency[][] {\r\n const groups = new Map<string, MetadataDependency[]>();\r\n for (const dep of deps) {\r\n const id = `${dep.rename ?? dep.name}`;\r\n groups.set(id, [...(groups.get(id) ?? []), dep]);\r\n }\r\n return [...groups.values()];\r\n}\r\n\r\nfunction readDeclarations(manifestPath: string): DependencyDeclaration[] {\r\n try {\r\n return parseCargoManifest(readFileSync(manifestPath, 'utf8'));\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\nconst sectionOf = (dep: MetadataDependency): DependencySection =>\r\n dep.kind === 'dev' ? 'dev-dependencies' : dep.kind === 'build' ? 'build-dependencies' : 'dependencies';\r\n\r\nfunction findDeclaration(decls: DependencyDeclaration[], key: string, dep: MetadataDependency) {\r\n const candidates = decls.filter((d) => !d.inWorkspace && d.key === key);\r\n return (\r\n candidates.find((d) => d.section === sectionOf(dep) && (d.target ?? null) === dep.target) ?? candidates[0]\r\n );\r\n}\r\n\r\nfunction locate(\r\n decl: DependencyDeclaration | undefined,\r\n root: DependencyDeclaration[],\r\n key: string,\r\n repoRoot: string,\r\n manifestPath: string,\r\n rootManifest: string,\r\n): Located | undefined {\r\n if (!decl) return undefined;\r\n if (decl.inherited) {\r\n const shared = root.find((d) => d.inWorkspace && d.key === key);\r\n if (!shared?.version) return undefined;\r\n return {\r\n version: shared.version,\r\n inherited: true,\r\n declaration: { file: rootManifest, kind: 'dependency-management', displayPath: display(repoRoot, rootManifest) },\r\n };\r\n }\r\n if (!decl.version) return undefined;\r\n return {\r\n version: decl.version,\r\n inherited: false,\r\n declaration: { file: manifestPath, kind: 'dependency', displayPath: display(repoRoot, manifestPath) },\r\n };\r\n}\r\n\r\n/** Other members that inherit the same workspace dependency. */\r\nfunction sharersOf(metadata: CargoMetadata, self: MetadataPackage, key: string): string[] {\r\n return metadata.packages\r\n .filter((p) => p !== self)\r\n .filter((p) => readDeclarations(p.manifest_path).some((d) => d.key === key && d.inherited))\r\n .map((p) => p.name);\r\n}\r\n\r\nconst display = (repoRoot: string, file: string) => relative(repoRoot, file).replace(/\\\\/g, '/');\r\nconst samePath = (a: string, b: string) => relative(a, b) === '';\r\n\r\nfunction sameRequirement(literal: string, req: string): boolean {\r\n const a = toSemverRange(literal);\r\n const b = toSemverRange(req);\r\n return a !== null && b !== null && semver.validRange(a) === semver.validRange(b);\r\n}\r\n","/**\r\n * Elevate — Cargo.toml dependency declarations.\r\n *\r\n * Finds, for every dependency of a manifest, where its version is written.\r\n * The parser reports exact source ranges, so an update can replace just the\r\n * characters inside the quotes and leave comments, quote style and line\r\n * endings alone.\r\n */\r\n\r\nimport { parseTOML } from 'toml-eslint-parser';\r\n\r\nexport type DependencySection = 'dependencies' | 'dev-dependencies' | 'build-dependencies';\r\n\r\nexport interface VersionLiteral {\r\n value: string;\r\n /** Offsets of the text between the quotes. */\r\n start: number;\r\n end: number;\r\n}\r\n\r\nexport interface DependencyDeclaration {\r\n /** Table key: the crate name, or its rename when `package = \"…\"` is used. */\r\n key: string;\r\n section: DependencySection;\r\n /** `cfg(…)` or target triple of a `[target.*]` table. */\r\n target?: string;\r\n /** Declared in `[workspace.dependencies]`. */\r\n inWorkspace: boolean;\r\n /** `workspace = true`: the version lives in the workspace root. */\r\n inherited: boolean;\r\n /** `package = \"…\"`: the real crate name behind a rename. */\r\n package?: string;\r\n version?: VersionLiteral;\r\n}\r\n\r\nconst SECTIONS: Record<string, DependencySection> = {\r\n dependencies: 'dependencies',\r\n 'dev-dependencies': 'dev-dependencies',\r\n dev_dependencies: 'dev-dependencies',\r\n 'build-dependencies': 'build-dependencies',\r\n build_dependencies: 'build-dependencies',\r\n};\r\n\r\ninterface Leaf {\r\n path: string[];\r\n node: any;\r\n}\r\n\r\nexport function parseCargoManifest(source: string): DependencyDeclaration[] {\r\n const root = parseTOML(source).body[0] as any;\r\n const leaves: Leaf[] = [];\r\n\r\n const keyPath = (key: any): string[] => key.keys.map((k: any) => (k.type === 'TOMLBare' ? k.name : k.value));\r\n const visitPair = (prefix: string[], pair: any): void => {\r\n const path = [...prefix, ...keyPath(pair.key)];\r\n leaves.push({ path, node: pair.value });\r\n if (pair.value.type === 'TOMLInlineTable') for (const inner of pair.value.body) visitPair(path, inner);\r\n };\r\n\r\n for (const element of root.body) {\r\n if (element.type === 'TOMLKeyValue') visitPair([], element);\r\n else if (element.type === 'TOMLTable') {\r\n const header = keyPath(element.key);\r\n for (const pair of element.body) visitPair(header, pair);\r\n leaves.push({ path: header, node: element });\r\n }\r\n }\r\n\r\n const byKey = new Map<string, DependencyDeclaration>();\r\n for (const { path, node } of leaves) {\r\n const located = locateSection(path);\r\n if (!located || located.rest.length === 0) continue;\r\n const [key, field] = located.rest;\r\n const id = `${located.inWorkspace}|${located.target ?? ''}|${located.section}|${key}`;\r\n let decl = byKey.get(id);\r\n if (!decl) {\r\n decl = { key: key!, section: located.section, target: located.target, inWorkspace: located.inWorkspace, inherited: false };\r\n byKey.set(id, decl);\r\n }\r\n if (located.rest.length === 1 && node.type === 'TOMLValue' && node.kind === 'string') {\r\n decl.version = literalOf(node);\r\n } else if (field === 'version' && located.rest.length === 2 && node.type === 'TOMLValue' && node.kind === 'string') {\r\n decl.version = literalOf(node);\r\n } else if (field === 'workspace' && located.rest.length === 2 && node.value === true) {\r\n decl.inherited = true;\r\n } else if (field === 'package' && located.rest.length === 2 && node.type === 'TOMLValue') {\r\n decl.package = String(node.value);\r\n }\r\n }\r\n return [...byKey.values()];\r\n}\r\n\r\nfunction literalOf(node: any): VersionLiteral {\r\n return { value: node.value, start: node.range[0] + 1, end: node.range[1] - 1 };\r\n}\r\n\r\n/** Splits a table path into dependency section, target and the keys below it. */\r\nfunction locateSection(path: string[]) {\r\n let i = 0;\r\n let target: string | undefined;\r\n let inWorkspace = false;\r\n if (path[0] === 'workspace' && path[1] === 'dependencies') {\r\n return { section: 'dependencies' as const, inWorkspace: true, target, rest: path.slice(2) };\r\n }\r\n if (path[0] === 'target' && path.length >= 3) {\r\n target = path[1];\r\n i = 2;\r\n }\r\n const section = SECTIONS[path[i] ?? ''];\r\n if (!section) return undefined;\r\n return { section, inWorkspace, target, rest: path.slice(i + 1) };\r\n}\r\n","/**\r\n * Elevate — Cargo.lock reader.\r\n *\r\n * Only the locked versions per crate are needed. A crate can be locked in\r\n * several versions at once, which makes a bare `-p name` ambiguous.\r\n */\r\n\r\nimport { existsSync, readFileSync } from 'node:fs';\r\nimport { getStaticTOMLValue, parseTOML } from 'toml-eslint-parser';\r\n\r\n/** Locked versions per crate name; empty when the file is missing or unreadable. */\r\nexport function readLockedVersions(lockFile: string): Map<string, string[]> {\r\n const locked = new Map<string, string[]>();\r\n if (!existsSync(lockFile)) return locked;\r\n try {\r\n const data = getStaticTOMLValue(parseTOML(readFileSync(lockFile, 'utf8'))) as { package?: { name: string; version: string }[] };\r\n for (const pkg of data.package ?? []) locked.set(pkg.name, [...(locked.get(pkg.name) ?? []), pkg.version]);\r\n } catch {\r\n // An unreadable lockfile is left for cargo to complain about.\r\n }\r\n return locked;\r\n}\r\n","/**\r\n * Elevate — Cargo updater.\r\n *\r\n * Writes each new requirement to the literal that declares it — in the\r\n * member's Cargo.toml or, for `workspace = true`, in the workspace root —\r\n * splicing only the version text. Then it brings Cargo.lock in line:\r\n *\r\n * 1. `cargo update -p name@old` re-resolves to the newest allowed version\r\n * 2. `cargo update -p name@new --precise <target>` only if the chosen version is older\r\n *\r\n * Step 2 is needed because `--precise` is ignored while the old lock entry no\r\n * longer fits the manifest (verified with Cargo 1.97). A repository without a\r\n * Cargo.lock gets none.\r\n */\r\n\r\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\r\nimport { join, resolve } from 'node:path';\r\nimport semver from 'semver';\r\nimport { InstallError } from '../../domain/ports.js';\r\nimport type { ApplyOutcome, DependencyUpdaterPort } from '../../domain/ports.js';\r\nimport type { ProjectModule, UpdateCandidate } from '../../domain/models.js';\r\nimport { runCommand, tail } from '../shared/process.js';\r\nimport { applyRangeEdits } from '../shared/text-edit.js';\r\nimport type { RangeEdit } from '../shared/text-edit.js';\r\nimport { StaleEditError } from '../shared/xml.js';\r\nimport { readLockedVersions } from './cargo-lockfile.js';\r\nimport { satisfiesRequirement } from './cargo-requirement.js';\r\nimport { parseCargoManifest } from './cargo-toml.js';\r\n\r\nconst UPDATE_TIMEOUT_MS = 10 * 60_000;\r\n\r\nconst workspaceDir = (module: ProjectModule, rootDir: string) => module.aggregatorDir ?? module.path ?? rootDir;\r\n\r\nexport class CargoUpdaterAdapter implements DependencyUpdaterPort {\r\n affectedFiles(module: ProjectModule, rootDir: string, updates: UpdateCandidate[]): string[] {\r\n const files = new Set(updates.map((u) => resolve(u.declaration?.file ?? join(module.path, 'Cargo.toml'))));\r\n files.add(join(workspaceDir(module, rootDir), 'Cargo.lock'));\r\n return [...files];\r\n }\r\n\r\n async applyUpdates(\r\n module: ProjectModule,\r\n rootDir: string,\r\n updates: UpdateCandidate[],\r\n onProgress: (stepMessage: string) => void,\r\n ): Promise<ApplyOutcome> {\r\n const dir = workspaceDir(module, rootDir);\r\n const lockFile = join(dir, 'Cargo.lock');\r\n const lockedBefore = readLockedVersions(lockFile);\r\n\r\n // Updates of the lock file alone leave every manifest as it is. They are checked first, so a\r\n // missing or changed lock file stops the run before anything is written.\r\n const lockUpdates = updates.filter((u) => u.action === 'lock');\r\n updates = updates.filter((u) => u.action !== 'lock');\r\n this.checkLockUpdates(lockUpdates, lockFile, lockedBefore);\r\n\r\n // Every edit is computed before the first write, so a stale file leaves nothing half-updated.\r\n const byFile = new Map<string, UpdateCandidate[]>();\r\n for (const update of updates) {\r\n const file = resolve(update.declaration?.file ?? join(module.path, 'Cargo.toml'));\r\n byFile.set(file, [...(byFile.get(file) ?? []), update]);\r\n }\r\n const writes: { file: string; content: string }[] = [];\r\n for (const [file, fileUpdates] of byFile) {\r\n onProgress(`Preparing ${fileUpdates.length} change(s) in ${file}…`);\r\n const source = readFileSync(file, 'utf8');\r\n const decls = parseCargoManifest(source);\r\n const edits: RangeEdit[] = [];\r\n for (const update of fileUpdates) {\r\n const inWorkspace = update.declaration?.kind === 'dependency-management';\r\n const name = update.coordinate.identifier;\r\n const found = decls.filter(\r\n (d) => d.inWorkspace === inWorkspace && (d.package ?? d.key) === name && d.version?.value === update.currentRange,\r\n );\r\n if (found.length === 0) {\r\n throw new InstallError(`${file}: cannot find the version of ${name} (${update.currentRange}) any more; rescan the module.`);\r\n }\r\n for (const d of found) {\r\n edits.push({ start: d.version!.start, end: d.version!.end, expected: d.version!.value, replacement: update.newRange });\r\n }\r\n }\r\n try {\r\n writes.push({ file, content: applyRangeEdits(source, edits) });\r\n } catch (err) {\r\n if (err instanceof StaleEditError) throw new InstallError(`${file}: ${err.message}`);\r\n throw err;\r\n }\r\n }\r\n onProgress('Writing Cargo.toml files…');\r\n for (const write of writes) writeFileSync(write.file, write.content, 'utf8');\r\n\r\n const registryUpdates = updates.filter((u) => u.action === 'update');\r\n if (existsSync(lockFile) && registryUpdates.length > 0) {\r\n await this.refreshLock(dir, lockFile, lockedBefore, registryUpdates, onProgress);\r\n }\r\n\r\n for (const update of lockUpdates) {\r\n const name = update.coordinate.identifier;\r\n onProgress(`Locking ${name} at ${update.latest}…`);\r\n await this.cargoUpdate(dir, ['-p', `${name}@${update.currentClean}`, '--precise', update.latest]);\r\n }\r\n\r\n const parts: string[] = [];\r\n if (updates.length > 0) {\r\n parts.push(`Updated ${updates.length} requirement(s) in ${writes.length} Cargo.toml file(s)${existsSync(lockFile) ? '; Cargo.lock refreshed' : ''}`);\r\n }\r\n if (lockUpdates.length > 0) parts.push(`locked ${lockUpdates.length} crate(s) at a newer version in Cargo.lock`);\r\n const message = parts.join('; ');\r\n\r\n return {\r\n updatedCount: updates.length + lockUpdates.length,\r\n auditMessage: `${message.charAt(0).toUpperCase()}${message.slice(1)}.`,\r\n auditSeverity: 'clean',\r\n integrityViolations: [],\r\n };\r\n }\r\n\r\n /** A lock-only update needs a lock file that still holds the version the scan saw. */\r\n private checkLockUpdates(lockUpdates: UpdateCandidate[], lockFile: string, locked: Map<string, string[]>): void {\r\n if (lockUpdates.length === 0) return;\r\n if (!existsSync(lockFile)) {\r\n throw new InstallError(`${lockFile} does not exist any more; rescan the module.`);\r\n }\r\n for (const update of lockUpdates) {\r\n const name = update.coordinate.identifier;\r\n if (!(locked.get(name) ?? []).includes(update.currentClean)) {\r\n throw new InstallError(`Cargo.lock no longer locks ${name} at ${update.currentClean}; rescan the module.`);\r\n }\r\n }\r\n }\r\n\r\n async resync(): Promise<void> {\r\n // Cargo keeps no installed state next to the manifests; restoring them and Cargo.lock suffices.\r\n }\r\n\r\n private async refreshLock(\r\n dir: string,\r\n lockFile: string,\r\n before: Map<string, string[]>,\r\n updates: UpdateCandidate[],\r\n onProgress: (stepMessage: string) => void,\r\n ): Promise<void> {\r\n const specs: string[] = [];\r\n for (const update of updates) {\r\n const name = update.coordinate.identifier;\r\n const versions = before.get(name) ?? [];\r\n // The entry the old requirement resolved to; a crate locked twice is told apart by that.\r\n const old = versions.find((v) => satisfiesRequirement(update.currentRange, v)) ?? versions[0];\r\n if (old) specs.push(`${name}@${old}`);\r\n }\r\n if (specs.length === 0) return;\r\n\r\n onProgress('Updating Cargo.lock…');\r\n await this.cargoUpdate(dir, specs.flatMap((s) => ['-p', s]));\r\n\r\n const after = readLockedVersions(lockFile);\r\n for (const update of updates) {\r\n const name = update.coordinate.identifier;\r\n const locked = (after.get(name) ?? []).find((v) => satisfiesRequirement(update.newRange, v));\r\n if (locked && semver.valid(update.latest) && locked !== update.latest) {\r\n onProgress(`Pinning ${name} to ${update.latest}…`);\r\n await this.cargoUpdate(dir, ['-p', `${name}@${locked}`, '--precise', update.latest]);\r\n }\r\n }\r\n }\r\n\r\n private async cargoUpdate(dir: string, args: string[]): Promise<void> {\r\n const result = await runCommand('cargo', ['update', ...args], { cwd: dir, timeoutMs: UPDATE_TIMEOUT_MS });\r\n if (result.exitCode !== 0) {\r\n const reason = result.timedOut ? 'cargo update timed out' : 'cargo update failed';\r\n throw new InstallError(reason, tail(result.stderr || result.stdout));\r\n }\r\n }\r\n}\r\n","/**\r\n * Elevate — position-aware XML reader for manifest files.\r\n *\r\n * Builds a lightweight element tree on top of the `saxes` streaming parser and\r\n * records, for every element, the exact source range of its text content. The\r\n * ranges make it possible to rewrite a single value (e.g. a `<version>`) by\r\n * splicing the original string, which preserves formatting, comments and\r\n * line endings byte for byte — something a parse/serialize round trip cannot.\r\n *\r\n * Commented-out markup is never part of the tree, so it can never be matched\r\n * or edited by accident.\r\n */\r\n\r\nimport { SaxesParser } from 'saxes';\r\n\r\n/** An XML element with its children and the source range of its text. */\r\nexport interface XmlElement {\r\n /** Local element name without namespace prefix. */\r\n name: string;\r\n attributes: Record<string, string>;\r\n children: XmlElement[];\r\n /** Concatenated, entity-decoded character data directly inside this element. */\r\n text: string;\r\n /**\r\n * Source range `[start, end)` between the end of the opening tag and the\r\n * start of the closing tag. Undefined for self-closing elements.\r\n */\r\n contentRange?: { start: number; end: number };\r\n}\r\n\r\n/** Thrown when a manifest cannot be parsed as well-formed XML. */\r\nexport class XmlParseError extends Error {\r\n constructor(message: string, readonly file?: string) {\r\n super(file ? `${file}: ${message}` : message);\r\n this.name = 'XmlParseError';\r\n }\r\n}\r\n\r\n/**\r\n * Parses an XML document and returns its root element.\r\n *\r\n * @param source the complete document text\r\n * @param file optional file name used in error messages\r\n */\r\nexport function parseXml(source: string, file?: string): XmlElement {\r\n const parser = new SaxesParser({ position: true });\r\n const stack: XmlElement[] = [];\r\n const openEnds: number[] = [];\r\n let root: XmlElement | undefined;\r\n let failure: Error | undefined;\r\n\r\n parser.on('error', (err) => {\r\n failure ??= err;\r\n });\r\n\r\n parser.on('opentag', (tag) => {\r\n const attributes: Record<string, string> = {};\r\n for (const [key, value] of Object.entries(tag.attributes)) {\r\n attributes[key] = typeof value === 'string' ? value : value.value;\r\n }\r\n const element: XmlElement = {\r\n name: localName(tag.name),\r\n attributes,\r\n children: [],\r\n text: '',\r\n };\r\n const parent = stack[stack.length - 1];\r\n if (parent) parent.children.push(element);\r\n else root ??= element;\r\n\r\n stack.push(element);\r\n // `position` points just past the `>` of the opening tag.\r\n openEnds.push(parser.position);\r\n });\r\n\r\n parser.on('closetag', (tag) => {\r\n const element = stack.pop();\r\n const openEnd = openEnds.pop();\r\n if (!element || openEnd === undefined || tag.isSelfClosing) return;\r\n\r\n // `position` points just past the `>` of the closing tag. A closing tag is\r\n // `</name>` unless it contains whitespace before `>`, which we detect by\r\n // searching backwards for its `</` instead of assuming its length.\r\n const closeEnd = parser.position;\r\n const closeStart = source.lastIndexOf('</', closeEnd - 1);\r\n if (closeStart >= openEnd) {\r\n element.contentRange = { start: openEnd, end: closeStart };\r\n }\r\n });\r\n\r\n parser.on('text', (text) => {\r\n const current = stack[stack.length - 1];\r\n if (current) current.text += text;\r\n });\r\n\r\n parser.on('cdata', (data) => {\r\n const current = stack[stack.length - 1];\r\n if (current) current.text += data;\r\n });\r\n\r\n try {\r\n parser.write(source).close();\r\n } catch (err) {\r\n failure ??= err as Error;\r\n }\r\n\r\n if (failure) throw new XmlParseError(failure.message, file);\r\n if (!root) throw new XmlParseError('document has no root element', file);\r\n return root;\r\n}\r\n\r\n/** Returns the first direct child with the given name. */\r\nexport function child(element: XmlElement | undefined, name: string): XmlElement | undefined {\r\n return element?.children.find((c) => c.name === name);\r\n}\r\n\r\n/** Returns all direct children with the given name. */\r\nexport function children(element: XmlElement | undefined, name: string): XmlElement[] {\r\n return element ? element.children.filter((c) => c.name === name) : [];\r\n}\r\n\r\n/** Follows a path of direct child names, e.g. `childAt(project, 'parent', 'version')`. */\r\nexport function childAt(element: XmlElement | undefined, ...path: string[]): XmlElement | undefined {\r\n let current = element;\r\n for (const name of path) current = child(current, name);\r\n return current;\r\n}\r\n\r\n/** Returns the trimmed text of a direct child, or undefined when absent or empty. */\r\nexport function childText(element: XmlElement | undefined, name: string): string | undefined {\r\n const value = child(element, name)?.text.trim();\r\n return value ? value : undefined;\r\n}\r\n\r\n/** A replacement of an element's text content. */\r\nexport interface TextEdit {\r\n element: XmlElement;\r\n /** The value the element is expected to contain; guards against stale edits. */\r\n expected: string;\r\n replacement: string;\r\n}\r\n\r\n/** Thrown when an edit no longer matches the file it is applied to. */\r\nexport class StaleEditError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'StaleEditError';\r\n }\r\n}\r\n\r\n/**\r\n * Applies text replacements to the original source.\r\n *\r\n * Only the trimmed value inside each element is replaced; surrounding\r\n * whitespace stays untouched. Every edit verifies that the element still holds\r\n * the expected value, so an edit computed from an outdated scan fails loudly\r\n * instead of overwriting a change made in the meantime.\r\n */\r\nexport function applyTextEdits(source: string, edits: TextEdit[]): string {\r\n const splices = edits.map((edit) => {\r\n const range = edit.element.contentRange;\r\n if (!range) {\r\n throw new StaleEditError(`<${edit.element.name}> has no editable text content.`);\r\n }\r\n const raw = source.slice(range.start, range.end);\r\n const leading = raw.length - raw.trimStart().length;\r\n const value = raw.trim();\r\n if (value !== edit.expected) {\r\n throw new StaleEditError(\r\n `<${edit.element.name}> contains '${value}', expected '${edit.expected}'. The file changed since it was scanned.`,\r\n );\r\n }\r\n const start = range.start + leading;\r\n return { start, end: start + value.length, replacement: edit.replacement };\r\n });\r\n\r\n // Apply from the end of the document so earlier offsets stay valid.\r\n splices.sort((a, b) => b.start - a.start);\r\n for (let i = 1; i < splices.length; i++) {\r\n if (splices[i]!.end > splices[i - 1]!.start) {\r\n throw new StaleEditError('Overlapping edits on the same element.');\r\n }\r\n }\r\n\r\n let result = source;\r\n for (const splice of splices) {\r\n result = result.slice(0, splice.start) + splice.replacement + result.slice(splice.end);\r\n }\r\n return result;\r\n}\r\n\r\n/** Escapes text for use as XML character data. */\r\nexport function escapeXml(value: string): string {\r\n return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\r\n}\r\n\r\n/**\r\n * Serialises an element subtree. Intended for generating throw-away documents\r\n * (e.g. probe POMs); it does not preserve the original formatting.\r\n */\r\nexport function serializeXml(element: XmlElement, indent = ''): string {\r\n const attrs = Object.entries(element.attributes)\r\n .map(([key, value]) => ` ${key}=\"${escapeXml(value).replace(/\"/g, '"')}\"`)\r\n .join('');\r\n if (element.children.length === 0) {\r\n return `${indent}<${element.name}${attrs}>${escapeXml(element.text.trim())}</${element.name}>`;\r\n }\r\n const inner = element.children.map((c) => serializeXml(c, `${indent} `)).join('\\n');\r\n return `${indent}<${element.name}${attrs}>\\n${inner}\\n${indent}</${element.name}>`;\r\n}\r\n\r\nfunction localName(qualified: string): string {\r\n const colon = qualified.indexOf(':');\r\n return colon >= 0 ? qualified.slice(colon + 1) : qualified;\r\n}\r\n","/**\r\n * Elevate — range based text edits.\r\n *\r\n * Replaces exact character ranges of a source text, so everything around them\r\n * (comments, quotes, indentation, line endings) stays byte-identical. Every\r\n * edit states the text it expects to replace; a mismatch means the file\r\n * changed since it was scanned.\r\n */\r\n\r\nimport { StaleEditError } from './xml.js';\r\n\r\nexport interface RangeEdit {\r\n start: number;\r\n end: number;\r\n /** The text currently at `start..end`. */\r\n expected: string;\r\n replacement: string;\r\n}\r\n\r\nexport function applyRangeEdits(source: string, edits: readonly RangeEdit[]): string {\r\n for (const edit of edits) {\r\n const found = source.slice(edit.start, edit.end);\r\n if (found !== edit.expected) {\r\n throw new StaleEditError(`Found '${found}', expected '${edit.expected}'. The file changed since it was scanned.`);\r\n }\r\n }\r\n const ordered = [...edits].sort((a, b) => b.start - a.start);\r\n for (let i = 1; i < ordered.length; i++) {\r\n if (ordered[i]!.end > ordered[i - 1]!.start) throw new StaleEditError('Overlapping edits on the same text.');\r\n }\r\n let result = source;\r\n for (const edit of ordered) result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\r\n return result;\r\n}\r\n","/**\r\n * Elevate — Cargo verification.\r\n *\r\n * `cargo check --all-targets` type-checks libraries, binaries, tests, benches\r\n * and examples without generating code — the counterpart of `mvn test-compile`.\r\n * It covers the members whose manifests changed plus every member that depends\r\n * on them by path, because a change in a library breaks its consumers. A\r\n * changed workspace root manifest (shared `[workspace.dependencies]`) checks\r\n * the whole workspace, and so does a change to Cargo.lock alone (a lock-only\r\n * update reaches every crate that uses the dependency).\r\n *\r\n * Doctests, non-default features and other targets are not covered; a\r\n * `postUpdateScript` is the way to add them.\r\n */\r\n\r\nimport { existsSync } from 'node:fs';\r\nimport { join, relative, resolve } from 'node:path';\r\nimport type { VerificationOptions, VerificationPort, VerificationResult } from '../../domain/ports.js';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { runShellScript, tail } from '../shared/process.js';\r\nimport { cargoErrors, runCargo } from './cargo-command.js';\r\nimport { loadMetadata } from './cargo-metadata.js';\r\nimport type { CargoMetadata } from './cargo-metadata.js';\r\n\r\nconst VERIFY_TIMEOUT_MS = 30 * 60_000;\r\n\r\nconst same = (a: string, b: string) => relative(resolve(a), resolve(b)) === '';\r\n\r\n/** The arguments of the `cargo check` that covers the change. */\r\nexport function planCheck(metadata: CargoMetadata, module: ProjectModule, changedFiles: readonly string[], locked: boolean): string[] {\r\n const args = ['check', '--all-targets', ...(locked ? ['--locked'] : [])];\r\n const rootManifest = join(metadata.workspace_root, 'Cargo.toml');\r\n const lockFile = join(metadata.workspace_root, 'Cargo.lock');\r\n const memberManifests = new Set(metadata.packages.map((p) => resolve(p.manifest_path)));\r\n\r\n if (changedFiles.some((f) => same(f, rootManifest))) {\r\n // A root manifest that is itself a member only matters when it holds workspace-wide settings.\r\n const isVirtualRoot = !memberManifests.has(resolve(rootManifest));\r\n if (isVirtualRoot || metadata.packages.length > 1) return [...args, '--workspace'];\r\n }\r\n\r\n // A new version in Cargo.lock reaches every crate that uses the dependency, and no manifest says which.\r\n if (changedFiles.length > 0 && changedFiles.every((f) => same(f, lockFile))) return [...args, '--workspace'];\r\n\r\n const changed = new Set(\r\n metadata.packages.filter((p) => changedFiles.some((f) => same(f, p.manifest_path))).map((p) => p.name),\r\n );\r\n if (changed.size === 0) changed.add(module.id);\r\n\r\n // Everything that reaches a changed member through path dependencies.\r\n for (let grew = true; grew; ) {\r\n grew = false;\r\n for (const p of metadata.packages) {\r\n if (changed.has(p.name)) continue;\r\n if (p.dependencies.some((d) => d.source === null && d.path && changed.has(d.name))) {\r\n changed.add(p.name);\r\n grew = true;\r\n }\r\n }\r\n }\r\n const ordered = metadata.packages.filter((p) => changed.has(p.name)).map((p) => p.name);\r\n return [...args, ...ordered.flatMap((name) => ['-p', name])];\r\n}\r\n\r\nexport interface CargoVerifierDeps {\r\n loadMetadata(dir: string): Promise<CargoMetadata>;\r\n hasLock(dir: string): boolean;\r\n}\r\n\r\nexport class CargoVerificationAdapter implements VerificationPort {\r\n constructor(\r\n private readonly deps: CargoVerifierDeps = { loadMetadata, hasLock: (dir) => existsSync(join(dir, 'Cargo.lock')) },\r\n ) {}\r\n\r\n async verify(module: ProjectModule, rootDir: string, options: VerificationOptions = {}): Promise<VerificationResult> {\r\n const dir = module.aggregatorDir ?? module.path ?? rootDir;\r\n\r\n if (options.customScript) {\r\n const label = options.customLabel || options.customScript;\r\n const result = await runShellScript(options.customScript, { cwd: dir, timeoutMs: VERIFY_TIMEOUT_MS });\r\n return result.exitCode === 0\r\n ? { status: 'clean', details: 'Verification script succeeded.', label }\r\n : { status: 'warn', details: tail(result.stderr || result.stdout), label };\r\n }\r\n\r\n const metadata = await this.deps.loadMetadata(dir);\r\n const args = planCheck(metadata, module, options.changedFiles ?? [], this.deps.hasLock(dir));\r\n const label = `Cargo build (cargo ${args.join(' ')})`;\r\n const result = await runCargo(args, { cwd: dir, timeoutMs: VERIFY_TIMEOUT_MS });\r\n if (result.exitCode === 0) return { status: 'clean', details: 'All affected crates type-check, including tests.', label };\r\n return {\r\n status: 'warn',\r\n details: result.timedOut ? 'cargo check timed out.' : cargoErrors(`${result.stderr}\\n${result.stdout}`),\r\n label,\r\n };\r\n }\r\n}\r\n","/**\r\n * Elevate — Maven module discovery.\r\n *\r\n * Reports every Maven project in the repository, including the root POM,\r\n * with its coordinates, its version (inherited and interpolated where\r\n * possible) and the aggregator whose reactor builds it.\r\n */\r\n\r\nimport { existsSync } from 'node:fs';\r\nimport { dirname, join, relative, resolve } from 'node:path';\r\nimport type { ModuleDiscoveryPort } from '../../domain/ports.js';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { MavenProject } from './maven-project.js';\r\nimport { interpolate, parentPomFile, readPom } from './maven-pom.js';\r\nimport type { PomModel } from './maven-pom.js';\r\n\r\nexport class MavenModuleDiscoveryAdapter implements ModuleDiscoveryPort {\r\n /**\r\n * Proposes a root only when `startDir` holds a pom.xml, and then climbs to\r\n * the POM above until there is none: the top of the connected POM chain.\r\n */\r\n findRoot(startDir: string, boundaryDir: string | undefined): string | undefined {\r\n let dir = resolve(startDir);\r\n if (!existsSync(join(dir, 'pom.xml'))) return undefined;\r\n const boundary = boundaryDir ? resolve(boundaryDir) : undefined;\r\n for (;;) {\r\n const above = pomAbove(dir, boundary);\r\n if (!above) return dir;\r\n dir = above;\r\n }\r\n }\r\n\r\n async discover(rootDir: string): Promise<ProjectModule[]> {\r\n const project = MavenProject.load(rootDir);\r\n\r\n const modules = project.poms.map((pom): ProjectModule => {\r\n const coordinates = project.coordinatesOf(pom);\r\n const relPath = relative(rootDir, pom.dir).replace(/\\\\/g, '/');\r\n return {\r\n id: coordinates.groupId ? `${coordinates.groupId}:${coordinates.artifactId}` : coordinates.artifactId,\r\n name: pom.name ? interpolate(pom.name, project.chainOf(pom).poms) : pom.artifactId,\r\n path: pom.dir,\r\n relPath: relPath || 'Root',\r\n ecosystem: 'maven',\r\n isRoot: relPath === '',\r\n version: coordinates.version,\r\n aggregatorDir: project.aggregatorDirOf(pom),\r\n };\r\n });\r\n\r\n modules.sort((a, b) => (a.isRoot ? -1 : b.isRoot ? 1 : a.relPath.localeCompare(b.relPath)));\r\n return modules;\r\n }\r\n}\r\n\r\n/** Reads a POM, treating a missing or malformed file as absent. */\r\nfunction tryReadPom(file: string): PomModel | undefined {\r\n try {\r\n return readPom(file);\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/** Strict ancestors of `dir`, nearest first, up to and including the boundary. */\r\nfunction ancestorsWithin(dir: string, boundary: string | undefined): string[] {\r\n const result: string[] = [];\r\n let current = dir;\r\n while (current !== boundary) {\r\n const parent = dirname(current);\r\n if (parent === current) break;\r\n result.push(parent);\r\n current = parent;\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * The directory of the POM above the project in `dir`: the outermost of its\r\n * local parent and the nearest aggregator that lists it as a module.\r\n */\r\nfunction pomAbove(dir: string, boundary: string | undefined): string | undefined {\r\n const pom = tryReadPom(join(dir, 'pom.xml'));\r\n if (!pom) return undefined;\r\n const ancestors = ancestorsWithin(dir, boundary);\r\n const found: string[] = [];\r\n\r\n const parentFile = parentPomFile(pom);\r\n if (parentFile && pom.parent && ancestors.includes(dirname(parentFile))) {\r\n const parent = tryReadPom(parentFile);\r\n const groupId = parent?.groupId ?? parent?.parent?.groupId;\r\n if (parent && parent.artifactId === pom.parent.artifactId && groupId === pom.parent.groupId) {\r\n found.push(dirname(parentFile));\r\n }\r\n }\r\n\r\n const ownFile = join(dir, 'pom.xml');\r\n const aggregator = ancestors.find((ancestor) =>\r\n tryReadPom(join(ancestor, 'pom.xml'))?.modules.some((entry) => {\r\n const target = resolve(ancestor, entry);\r\n return target === dir || target === ownFile;\r\n }),\r\n );\r\n if (aggregator) found.push(aggregator);\r\n\r\n // The outermost has the shortest path: all candidates are ancestors of `dir`.\r\n return found.sort((a, b) => a.length - b.length)[0];\r\n}\r\n","/**\r\n * Elevate — the set of POM files in a repository.\r\n *\r\n * Indexes every pom.xml below the repository root (including the root POM),\r\n * resolves parent chains between them and determines which aggregator's\r\n * reactor builds each project.\r\n */\r\n\r\nimport { existsSync, readdirSync, statSync } from 'node:fs';\r\nimport { join, resolve } from 'node:path';\r\nimport { interpolate, parentPomFile, readPom } from './maven-pom.js';\r\nimport type { PomModel, PomParent } from './maven-pom.js';\r\n\r\nconst MAX_DEPTH = 6;\r\nconst SKIPPED_DIRS = new Set(['node_modules', 'target', 'build', 'dist', 'out']);\r\n\r\nexport interface PomCoordinates {\r\n groupId: string;\r\n artifactId: string;\r\n version?: string;\r\n}\r\n\r\nexport interface PomChain {\r\n /** The project first, followed by its parents that live in this repository. */\r\n poms: PomModel[];\r\n /** The first parent that is not part of this repository, if any. */\r\n externalParent?: PomParent;\r\n}\r\n\r\nexport class MavenProject {\r\n private readonly byFile = new Map<string, PomModel>();\r\n private readonly aggregators = new Map<string, string>();\r\n\r\n private constructor(\r\n readonly rootDir: string,\r\n readonly poms: PomModel[],\r\n ) {\r\n for (const pom of poms) this.byFile.set(pom.file, pom);\r\n this.assignAggregators();\r\n }\r\n\r\n /**\r\n * Loads every readable pom.xml below `rootDir`, plus every module listed in\r\n * a `<modules>` section, even in directories the file walk skips (such as\r\n * `build/` or `dist/`). Malformed files are skipped.\r\n */\r\n static load(rootDir: string): MavenProject {\r\n const poms: PomModel[] = [];\r\n const queue = findPomFiles(rootDir);\r\n const seen = new Set(queue);\r\n while (queue.length > 0) {\r\n const file = queue.shift()!;\r\n let pom: PomModel;\r\n try {\r\n pom = readPom(file);\r\n } catch {\r\n // A malformed or missing POM cannot be built by Maven either; it is not a module.\r\n continue;\r\n }\r\n poms.push(pom);\r\n for (const entry of pom.modules) {\r\n const target = resolve(pom.dir, entry);\r\n const moduleFile = target.endsWith('.xml') ? target : join(target, 'pom.xml');\r\n if (!seen.has(moduleFile) && existsSync(moduleFile)) {\r\n seen.add(moduleFile);\r\n queue.push(moduleFile);\r\n }\r\n }\r\n }\r\n return new MavenProject(rootDir, poms);\r\n }\r\n\r\n pomAt(file: string): PomModel | undefined {\r\n return this.byFile.get(resolve(file));\r\n }\r\n\r\n /** The project followed by its local parents, stopping at the first external parent. */\r\n chainOf(pom: PomModel): PomChain {\r\n const poms: PomModel[] = [pom];\r\n let current = pom;\r\n while (current.parent) {\r\n const parent = this.localParentOf(current);\r\n if (!parent || poms.includes(parent)) {\r\n return { poms, externalParent: parent ? undefined : current.parent };\r\n }\r\n poms.push(parent);\r\n current = parent;\r\n }\r\n return { poms };\r\n }\r\n\r\n /** Coordinates of a project with inherited groupId/version and interpolated values. */\r\n coordinatesOf(pom: PomModel): PomCoordinates {\r\n const chain = this.chainOf(pom).poms;\r\n const groupId = pom.groupId ?? pom.parent?.groupId ?? '';\r\n const rawVersion = pom.version ?? pom.parent?.version;\r\n const version = rawVersion ? interpolate(rawVersion, chain) : undefined;\r\n return {\r\n groupId: interpolate(groupId, chain),\r\n artifactId: pom.artifactId,\r\n version: version && !version.includes('${') ? version : undefined,\r\n };\r\n }\r\n\r\n /** Directory of the outermost aggregator whose reactor includes this project. */\r\n aggregatorDirOf(pom: PomModel): string | undefined {\r\n return this.aggregators.get(pom.file);\r\n }\r\n\r\n private localParentOf(pom: PomModel): PomModel | undefined {\r\n const parent = pom.parent;\r\n if (!parent) return undefined;\r\n\r\n // Compares against the candidate's own declarations only, interpolated with\r\n // its own properties. Resolving the candidate's full chain here would\r\n // recurse endlessly on (invalid) cyclic parent declarations.\r\n const matches = (candidate: PomModel | undefined) => {\r\n if (!candidate) return false;\r\n const groupId = interpolate(candidate.groupId ?? candidate.parent?.groupId ?? '', [candidate]);\r\n const version = interpolate(candidate.version ?? candidate.parent?.version ?? '', [candidate]);\r\n const expected = interpolate(parent.version, [pom]);\r\n return (\r\n groupId === parent.groupId &&\r\n candidate.artifactId === parent.artifactId &&\r\n (version.includes('${') || expected.includes('${') || version === expected)\r\n );\r\n };\r\n\r\n // Maven uses the POM at <relativePath> (default ../pom.xml) when its\r\n // coordinates match; otherwise the parent comes from a repository.\r\n const file = parentPomFile(pom);\r\n const byPath = file ? this.byFile.get(resolve(file)) : undefined;\r\n return matches(byPath) ? byPath : undefined;\r\n }\r\n\r\n /**\r\n * Walks `<modules>` from every aggregator, outermost first, and records for\r\n * each reached project the aggregator that builds it.\r\n */\r\n private assignAggregators(): void {\r\n const aggregatorPoms = this.poms\r\n .filter((pom) => pom.modules.length > 0)\r\n .sort((a, b) => a.dir.length - b.dir.length);\r\n\r\n for (const aggregator of aggregatorPoms) {\r\n if (this.aggregators.has(aggregator.file)) continue;\r\n const queue: PomModel[] = [aggregator];\r\n while (queue.length > 0) {\r\n const pom = queue.shift()!;\r\n if (this.aggregators.has(pom.file)) continue;\r\n this.aggregators.set(pom.file, aggregator.dir);\r\n for (const entry of pom.modules) {\r\n const target = resolve(pom.dir, entry);\r\n const file = target.endsWith('.xml') ? target : join(target, 'pom.xml');\r\n const modulePom = this.byFile.get(file);\r\n if (modulePom) queue.push(modulePom);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Finds pom.xml files: the root POM and every POM in subdirectories, except\r\n * below build output, dependency directories and the `src` of a project.\r\n */\r\nfunction findPomFiles(rootDir: string): string[] {\r\n const results: string[] = [];\r\n const rootPom = join(rootDir, 'pom.xml');\r\n if (existsSync(rootPom)) results.push(resolve(rootPom));\r\n\r\n const walk = (dir: string, depth: number) => {\r\n if (depth > MAX_DEPTH) return;\r\n let entries;\r\n try {\r\n entries = readdirSync(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n const isProject = existsSync(join(dir, 'pom.xml'));\r\n for (const entry of entries) {\r\n if (!entry.isDirectory() || entry.name.startsWith('.') || SKIPPED_DIRS.has(entry.name)) continue;\r\n // Maven reserves `<project>/src` for sources, resources and test\r\n // projects (fixtures, invoker ITs, archetype templates), not modules.\r\n if (isProject && entry.name === 'src') continue;\r\n const subDir = join(dir, entry.name);\r\n const pom = join(subDir, 'pom.xml');\r\n if (existsSync(pom) && statSync(pom).isFile()) results.push(resolve(pom));\r\n walk(subDir, depth + 1);\r\n }\r\n };\r\n\r\n walk(rootDir, 1);\r\n return results;\r\n}\r\n","/**\r\n * Elevate — raw POM model.\r\n *\r\n * Reads a pom.xml exactly as written, without inheritance or interpolation,\r\n * and keeps references to the XML elements so versions can later be edited in\r\n * place. Elements inside `<profiles>` are deliberately ignored: whether a\r\n * profile is active depends on the build environment, and every location\r\n * found here is cross-checked against Maven's effective POM before editing.\r\n */\r\n\r\nimport { existsSync, readFileSync, statSync } from 'node:fs';\r\nimport { dirname, join, resolve } from 'node:path';\r\nimport { child, childAt, childText, children, parseXml } from '../shared/xml.js';\r\nimport type { XmlElement } from '../shared/xml.js';\r\n\r\nexport interface PomDependency {\r\n groupId: string;\r\n artifactId: string;\r\n version?: string;\r\n type?: string;\r\n classifier?: string;\r\n scope?: string;\r\n /** The `<version>` element, when present. */\r\n versionElement?: XmlElement;\r\n}\r\n\r\nexport interface PomParent {\r\n groupId: string;\r\n artifactId: string;\r\n version: string;\r\n relativePath?: string;\r\n versionElement?: XmlElement;\r\n}\r\n\r\nexport interface PomProperty {\r\n value: string;\r\n element: XmlElement;\r\n}\r\n\r\nexport interface PomModel {\r\n /** Absolute path of the pom.xml. */\r\n file: string;\r\n /** Directory containing the pom.xml. */\r\n dir: string;\r\n /** Own groupId, if declared (otherwise inherited from the parent). */\r\n groupId?: string;\r\n artifactId: string;\r\n /** Own version, if declared (otherwise inherited from the parent). */\r\n version?: string;\r\n versionElement?: XmlElement;\r\n name?: string;\r\n packaging: string;\r\n parent?: PomParent;\r\n properties: Map<string, PomProperty>;\r\n dependencies: PomDependency[];\r\n managedDependencies: PomDependency[];\r\n /** Entries of `<modules>`, as written. */\r\n modules: string[];\r\n}\r\n\r\n/** Parses a pom.xml file. Throws `XmlParseError` for malformed XML. */\r\nexport function readPom(file: string): PomModel {\r\n const source = readFileSync(file, 'utf8');\r\n return parsePom(source, file);\r\n}\r\n\r\n/** Parses POM source text. */\r\nexport function parsePom(source: string, file: string): PomModel {\r\n const project = parseXml(source, file);\r\n\r\n const parentElement = child(project, 'parent');\r\n const parent: PomParent | undefined = parentElement\r\n ? {\r\n groupId: childText(parentElement, 'groupId') ?? '',\r\n artifactId: childText(parentElement, 'artifactId') ?? '',\r\n version: childText(parentElement, 'version') ?? '',\r\n relativePath: child(parentElement, 'relativePath')?.text.trim(),\r\n versionElement: child(parentElement, 'version'),\r\n }\r\n : undefined;\r\n\r\n const properties = new Map<string, PomProperty>();\r\n for (const element of child(project, 'properties')?.children ?? []) {\r\n properties.set(element.name, { value: element.text.trim(), element });\r\n }\r\n\r\n return {\r\n file,\r\n dir: dirname(file),\r\n groupId: childText(project, 'groupId'),\r\n artifactId: childText(project, 'artifactId') ?? 'unknown',\r\n version: childText(project, 'version'),\r\n versionElement: child(project, 'version'),\r\n name: childText(project, 'name'),\r\n packaging: childText(project, 'packaging') ?? 'jar',\r\n parent,\r\n properties,\r\n dependencies: readDependencies(child(project, 'dependencies')),\r\n managedDependencies: readDependencies(childAt(project, 'dependencyManagement', 'dependencies')),\r\n modules: children(child(project, 'modules'), 'module').map((m) => m.text.trim()).filter(Boolean),\r\n };\r\n}\r\n\r\nfunction readDependencies(container: XmlElement | undefined): PomDependency[] {\r\n return children(container, 'dependency').map((element) => ({\r\n groupId: childText(element, 'groupId') ?? '',\r\n artifactId: childText(element, 'artifactId') ?? '',\r\n version: childText(element, 'version'),\r\n type: childText(element, 'type'),\r\n classifier: childText(element, 'classifier'),\r\n scope: childText(element, 'scope'),\r\n versionElement: child(element, 'version'),\r\n }));\r\n}\r\n\r\n/**\r\n * Resolves the pom.xml that `<parent><relativePath>` points to, following\r\n * Maven's default of `../pom.xml`. An empty `<relativePath/>` explicitly\r\n * disables the lookup.\r\n */\r\nexport function parentPomFile(pom: PomModel): string | undefined {\r\n if (!pom.parent) return undefined;\r\n const relativePath = pom.parent.relativePath ?? '../pom.xml';\r\n if (relativePath === '') return undefined;\r\n let candidate = resolve(pom.dir, relativePath);\r\n if (existsSync(candidate) && statSync(candidate).isDirectory()) candidate = join(candidate, 'pom.xml');\r\n return existsSync(candidate) ? candidate : undefined;\r\n}\r\n\r\n/** Built-in `project.*` expressions resolvable without running Maven. */\r\nfunction builtinProperty(name: string, module: PomModel): string | undefined {\r\n switch (name) {\r\n case 'project.groupId':\r\n case 'pom.groupId':\r\n return module.groupId ?? module.parent?.groupId;\r\n case 'project.artifactId':\r\n case 'pom.artifactId':\r\n return module.artifactId;\r\n case 'project.version':\r\n case 'pom.version':\r\n return module.version ?? module.parent?.version;\r\n case 'project.parent.groupId':\r\n return module.parent?.groupId;\r\n case 'project.parent.version':\r\n return module.parent?.version;\r\n default:\r\n return undefined;\r\n }\r\n}\r\n\r\n/** Finds the nearest definition of a property, searching the module first. */\r\nexport function findProperty(\r\n name: string,\r\n chain: readonly PomModel[],\r\n): { pom: PomModel; property: PomProperty } | undefined {\r\n for (const pom of chain) {\r\n const property = pom.properties.get(name);\r\n if (property) return { pom, property };\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Interpolates `${...}` expressions with properties from the inheritance\r\n * chain (module first, as in Maven) and the built-in `project.*` values of\r\n * the module. Unresolvable expressions are left in place.\r\n */\r\nexport function interpolate(text: string, chain: readonly PomModel[], depth = 0): string {\r\n if (depth > 10 || !text.includes('${')) return text;\r\n const module = chain[0];\r\n const replaced = text.replace(/\\$\\{([^}]+)\\}/g, (expression, name: string) => {\r\n const builtin = module ? builtinProperty(name, module) : undefined;\r\n if (builtin !== undefined) return builtin;\r\n return findProperty(name, chain)?.property.value ?? expression;\r\n });\r\n return replaced === text ? text : interpolate(replaced, chain, depth + 1);\r\n}\r\n\r\n/** Matches a whole-value property reference such as `${guava.version}`. */\r\nexport function propertyReference(text: string): string | undefined {\r\n return text.match(/^\\$\\{([^}]+)\\}$/)?.[1];\r\n}\r\n","/**\r\n * Elevate — Maven registry adapter for ad-hoc version queries\r\n * (`elevate versions`, MCP `elevate_get_versions`).\r\n *\r\n * Like the scanner, it asks Maven itself instead of a fixed repository URL:\r\n * the versions-maven-plugin lists every version newer than `0` through the\r\n * repositories, mirrors and credentials of the user's `settings.xml` and of the\r\n * repository's root POM. Any Nexus or Artifactory therefore works without\r\n * Elevate-specific configuration.\r\n */\r\n\r\nimport { existsSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport type { RegistryEndpoint, RegistryPort } from '../../domain/ports.js';\r\nimport type { DependencyCoordinate, ReleaseChannel } from '../../domain/models.js';\r\nimport { isPreReleaseVersion } from '../../domain/versions.js';\r\nimport { MavenCommandError } from './maven-command.js';\r\nimport { DEFAULT_MAVEN_PLUGINS, ScratchDirectory, queryNewerVersions, readEffectivePoms } from './maven-resolution.js';\r\nimport type { EffectiveModel, MavenPluginVersions } from './maven-resolution.js';\r\n\r\n/** A version lower than any real one, so the report lists all versions as newer. */\r\nconst PROBE_VERSION = '0';\r\n\r\nconst NO_REPOSITORIES: EffectiveModel = { dependencies: [], managedDependencies: [] };\r\n\r\nexport class MavenRegistryAdapter implements RegistryPort {\r\n constructor(private readonly plugins: MavenPluginVersions = DEFAULT_MAVEN_PLUGINS) {}\r\n\r\n /**\r\n * The repositories come from Maven's own configuration, which Elevate does\r\n * not interpret. They are reported as non-public: the lookup goes exactly\r\n * where the project's build would go.\r\n */\r\n async resolveEndpoint(): Promise<RegistryEndpoint> {\r\n return { url: 'repositories configured for Maven (settings.xml, POM)', isPublic: false };\r\n }\r\n\r\n async getLatestVersion(\r\n coordinate: DependencyCoordinate,\r\n channel: ReleaseChannel = 'stable',\r\n cwd = process.cwd(),\r\n ): Promise<string | null> {\r\n const versions = await this.getAllVersions(coordinate, cwd);\r\n return versions.find((v) => channel === 'all' || !isPreReleaseVersion(v)) ?? null;\r\n }\r\n\r\n /**\r\n * All versions available in the configured repositories, newest first.\r\n * Throws `MavenCommandError` when Maven fails or a repository could not be\r\n * read, so an error is never mistaken for \"no versions\".\r\n */\r\n async getAllVersions(coordinate: DependencyCoordinate, cwd = process.cwd()): Promise<string[]> {\r\n if (!coordinate.group || !coordinate.artifact) return [];\r\n const key = `${coordinate.group}:${coordinate.artifact}`;\r\n\r\n const scratch = new ScratchDirectory(cwd);\r\n try {\r\n const repositories = await projectRepositories(cwd, scratch, this.plugins);\r\n const report = await queryNewerVersions(\r\n [{ groupId: coordinate.group, artifactId: coordinate.artifact, version: PROBE_VERSION }],\r\n repositories,\r\n cwd,\r\n cwd,\r\n scratch,\r\n this.plugins,\r\n );\r\n const versions = report.newerVersions.get(key) ?? [];\r\n if (versions.length === 0 && report.failedLookups.has(key)) {\r\n throw new MavenCommandError(`A Maven repository failed to deliver the versions of ${key}.`, '');\r\n }\r\n return [...versions].reverse();\r\n } finally {\r\n scratch.dispose();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Repositories declared in the root POM (including its parents), so projects\r\n * that declare their repositories in the POM rather than in settings.xml are\r\n * covered too. Without a root POM, settings.xml alone applies.\r\n */\r\nasync function projectRepositories(\r\n cwd: string,\r\n scratch: ScratchDirectory,\r\n plugins: MavenPluginVersions,\r\n): Promise<EffectiveModel> {\r\n const rootPom = join(cwd, 'pom.xml');\r\n if (!existsSync(rootPom)) return NO_REPOSITORIES;\r\n const models = await readEffectivePoms(rootPom, cwd, cwd, scratch, plugins);\r\n return [...models.values()][0] ?? NO_REPOSITORIES;\r\n}\r\n","/**\r\n * Elevate — Maven invocation.\r\n *\r\n * Prefers the project's Maven Wrapper (`mvnw` / `mvnw.cmd`), which pins the\r\n * Maven version the project is built with, and falls back to `mvn` on the\r\n * PATH. Without either, Maven features fail with `MavenUnavailableError`\r\n * instead of silently degrading: Elevate cannot verify Maven updates without\r\n * Maven, so offering them would be unsafe.\r\n */\r\n\r\nimport { existsSync } from 'node:fs';\r\nimport { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';\r\nimport { relativeToCwd, runCommand } from '../shared/process.js';\r\n\r\n// Re-exported so existing importers keep working (WIN contract).\r\nexport { relativeToCwd };\r\nimport type { RunResult } from '../shared/process.js';\r\n\r\n/** Thrown when neither a Maven Wrapper nor `mvn` is available. */\r\nexport class MavenUnavailableError extends Error {\r\n constructor() {\r\n super('Maven is not available: no Maven Wrapper (mvnw) in the project and no `mvn` on the PATH.');\r\n this.name = 'MavenUnavailableError';\r\n }\r\n}\r\n\r\n/** Thrown when a Maven invocation fails. */\r\nexport class MavenCommandError extends Error {\r\n constructor(message: string, readonly output: string) {\r\n super(message);\r\n this.name = 'MavenCommandError';\r\n }\r\n}\r\n\r\nconst IS_WINDOWS = process.platform === 'win32';\r\nconst WRAPPER = IS_WINDOWS ? 'mvnw.cmd' : 'mvnw';\r\n\r\n/** Arguments for non-interactive, log-friendly output. */\r\nconst BATCH_ARGS = ['-B', '--no-transfer-progress'];\r\n\r\nlet mvnOnPath: Promise<boolean> | undefined;\r\n\r\n/**\r\n * Finds the Maven Wrapper closest to `fromDir`, searching upwards but never\r\n * above `rootDir`.\r\n */\r\nexport function findMavenWrapper(fromDir: string, rootDir: string): string | undefined {\r\n let dir = resolve(fromDir);\r\n const root = resolve(rootDir);\r\n for (;;) {\r\n const candidate = join(dir, WRAPPER);\r\n if (existsSync(candidate)) return candidate;\r\n if (dir === root || relative(root, dir).startsWith('..')) return undefined;\r\n const parent = dirname(dir);\r\n if (parent === dir) return undefined;\r\n dir = parent;\r\n }\r\n}\r\n\r\n\r\nexport interface MavenRunOptions {\r\n /** Working directory; also the starting point of the wrapper lookup. */\r\n cwd: string;\r\n /** Repository root; the wrapper lookup does not go above it. */\r\n rootDir: string;\r\n timeoutMs?: number;\r\n}\r\n\r\n/** Runs Maven in batch mode. Resolves with the result even for a failed build. */\r\nexport async function runMaven(args: string[], options: MavenRunOptions): Promise<RunResult> {\r\n const wrapper = findMavenWrapper(options.cwd, options.rootDir);\r\n const run = { cwd: options.cwd, timeoutMs: options.timeoutMs };\r\n\r\n if (wrapper) {\r\n // Addressed by its relative path like every other file; a wrapper in the\r\n // working directory itself needs an explicit `.` so it is not searched on the PATH.\r\n const relativeWrapper = relativeToCwd(options.cwd, wrapper);\r\n const path = isAbsolute(relativeWrapper) || relativeWrapper.includes(sep) ? relativeWrapper : `.${sep}${relativeWrapper}`;\r\n // On POSIX the wrapper may lack the executable bit after a checkout.\r\n return IS_WINDOWS\r\n ? runCommand(path, [...BATCH_ARGS, ...args], run)\r\n : runCommand('sh', [path, ...BATCH_ARGS, ...args], run);\r\n }\r\n\r\n mvnOnPath ??= runCommand('mvn', ['-v'], { cwd: options.cwd, timeoutMs: 30_000 }).then(\r\n (result) => result.exitCode === 0,\r\n () => false,\r\n );\r\n if (!(await mvnOnPath)) throw new MavenUnavailableError();\r\n\r\n return runCommand('mvn', [...BATCH_ARGS, ...args], run);\r\n}\r\n\r\n/** Extracts Maven's error lines for a concise failure message. */\r\nexport function mavenErrors(output: string): string {\r\n const errors = output\r\n .split(/\\r?\\n/)\r\n .filter((line) => line.startsWith('[ERROR]'))\r\n .map((line) => line.replace(/^\\[ERROR\\]\\s?/, ''))\r\n .filter((line) => line.trim() && !line.startsWith('->') && !line.includes('Re-run Maven'));\r\n return (errors.length > 0 ? errors : output.trim().split(/\\r?\\n/).slice(-10)).slice(0, 12).join('\\n');\r\n}\r\n","/**\r\n * Elevate — Maven-based dependency resolution.\r\n *\r\n * Two questions are answered by Maven itself instead of by parsing POMs:\r\n *\r\n * 1. Which version of each dependency applies? — `help:effective-pom` resolves\r\n * parents, imported BOMs, properties and dependency management.\r\n * 2. Which newer versions exist? — the versions-maven-plugin queries the\r\n * repositories exactly as the build does: mirrors, private repositories\r\n * and credentials from settings.xml all apply.\r\n *\r\n * The plugin report runs against a generated probe POM rather than the real\r\n * project: the probe lists only the artifacts of interest, so inherited\r\n * management sections (often hundreds of BOM entries) are not queried, and the\r\n * report's generated site lands in Elevate's scratch directory instead of the\r\n * project's build output. The scratch directory lives below the module's\r\n * `target/` so the project's `.mvn/` configuration (maven.config, extensions)\r\n * still applies.\r\n */\r\n\r\nimport { randomUUID } from 'node:crypto';\r\nimport { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { childText, children, childAt, escapeXml, parseXml, serializeXml, child } from '../shared/xml.js';\r\nimport type { XmlElement } from '../shared/xml.js';\r\nimport { MavenCommandError, mavenErrors, relativeToCwd, runMaven } from './maven-command.js';\r\n\r\n/** Versions of the two Maven plugins Elevate runs. */\r\nexport interface MavenPluginVersions {\r\n /** maven-help-plugin: reads the effective POM. */\r\n help: string;\r\n /** versions-maven-plugin: looks up newer versions. */\r\n versions: string;\r\n}\r\n\r\n/** Pinned plugin versions for reproducible results; replaceable per repository. */\r\nexport const DEFAULT_MAVEN_PLUGINS: MavenPluginVersions = { help: '3.5.2', versions: '2.22.0' };\r\n\r\nconst HELP_PLUGIN_ID = 'org.apache.maven.plugins:maven-help-plugin';\r\nconst VERSIONS_PLUGIN_ID = 'org.codehaus.mojo:versions-maven-plugin';\r\n\r\n/** What Maven prints when it cannot download an artifact (matched case-insensitively). */\r\nconst DOWNLOAD_FAILURES = [\r\n 'could not be resolved',\r\n 'could not find artifact',\r\n 'failed to read artifact descriptor',\r\n 'could not transfer artifact',\r\n];\r\n\r\n/** Thrown when Maven could not download one of the plugins Elevate runs. */\r\nexport class MavenPluginUnavailableError extends MavenCommandError {\r\n constructor(\r\n plugin: { id: string; version: string; key: keyof MavenPluginVersions; purpose: string },\r\n output: string,\r\n ) {\r\n super(\r\n `Maven could not download ${plugin.id}:${plugin.version}, which Elevate uses to ${plugin.purpose}. ` +\r\n 'Make this plugin available in the repository or mirror your Maven is configured with, ' +\r\n `or choose a version that is available there with \"mavenPlugins\": { \"${plugin.key}\": \"<version>\" } ` +\r\n `in elevate.config.json.\\n${mavenErrors(output)}`,\r\n output,\r\n );\r\n this.name = 'MavenPluginUnavailableError';\r\n }\r\n}\r\n\r\n/** Whether a failed Maven run failed because it could not download the plugin. */\r\nfunction isPluginUnavailable(output: string, pluginId: string): boolean {\r\n return output.split(/\\r?\\n/).some((line) => {\r\n const lower = line.toLowerCase();\r\n return line.includes(pluginId) && DOWNLOAD_FAILURES.some((phrase) => lower.includes(phrase));\r\n });\r\n}\r\n\r\nconst MAVEN_TIMEOUT_MS = 5 * 60_000;\r\n\r\nexport interface EffectiveDependency {\r\n groupId: string;\r\n artifactId: string;\r\n version: string;\r\n scope: string;\r\n type: string;\r\n classifier?: string;\r\n}\r\n\r\nexport interface EffectiveModel {\r\n dependencies: EffectiveDependency[];\r\n managedDependencies: EffectiveDependency[];\r\n repositories?: XmlElement;\r\n pluginRepositories?: XmlElement;\r\n}\r\n\r\n/** An artifact whose newer versions should be looked up. */\r\nexport interface ProbeArtifact {\r\n groupId: string;\r\n artifactId: string;\r\n version: string;\r\n type?: string;\r\n classifier?: string;\r\n}\r\n\r\nexport interface VersionReport {\r\n /** Newer versions per `groupId:artifactId`, in ascending order. */\r\n newerVersions: Map<string, string[]>;\r\n /** Artifacts whose metadata could not be downloaded from some repository. */\r\n failedLookups: Set<string>;\r\n}\r\n\r\n/**\r\n * A scratch directory below the module's `target/`, unique per scan so\r\n * concurrent scans never share files. `dispose()` removes it again, together\r\n * with `target/` if the scan created that and left it empty.\r\n */\r\nexport class ScratchDirectory {\r\n readonly path: string;\r\n private readonly target: string;\r\n private readonly createdTarget: boolean;\r\n\r\n constructor(moduleDir: string) {\r\n this.target = join(moduleDir, 'target');\r\n this.createdTarget = !existsSync(this.target);\r\n this.path = join(this.target, `.elevate-${randomUUID().slice(0, 8)}`);\r\n mkdirSync(this.path, { recursive: true });\r\n }\r\n\r\n dispose(): void {\r\n rmSync(this.path, { recursive: true, force: true });\r\n try {\r\n if (this.createdTarget && readdirSync(this.target).length === 0) rmSync(this.target, { recursive: true });\r\n } catch {\r\n // Another process may be using target/ concurrently; leaving it is harmless.\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Runs `help:effective-pom` once and returns the model of every project it\r\n * covers, keyed by `groupId:artifactId`. With `recursive` the whole reactor of\r\n * an aggregator POM is resolved in a single Maven run; otherwise only the\r\n * given project (`-N`).\r\n */\r\nexport async function readEffectivePoms(\r\n pomFile: string,\r\n moduleDir: string,\r\n rootDir: string,\r\n scratch: ScratchDirectory,\r\n plugins: MavenPluginVersions,\r\n recursive = false,\r\n): Promise<Map<string, EffectiveModel>> {\r\n const output = join(scratch.path, 'effective-pom.xml');\r\n // The files are named relative to the working directory (`moduleDir`), so the\r\n // directory the project lives in never appears on the command line.\r\n const args = [\r\n '-f',\r\n relativeToCwd(moduleDir, pomFile),\r\n `${HELP_PLUGIN_ID}:${plugins.help}:effective-pom`,\r\n `-Doutput=${relativeToCwd(moduleDir, output)}`,\r\n ];\r\n const result = await runMaven(recursive ? args : ['-N', ...args], {\r\n cwd: moduleDir,\r\n rootDir,\r\n timeoutMs: MAVEN_TIMEOUT_MS,\r\n });\r\n\r\n if (result.exitCode !== 0 || !existsSync(output)) {\r\n const text = `${result.stdout}\\n${result.stderr}`;\r\n if (isPluginUnavailable(text, HELP_PLUGIN_ID)) {\r\n throw new MavenPluginUnavailableError(\r\n { id: HELP_PLUGIN_ID, version: plugins.help, key: 'help', purpose: 'read the effective POM' },\r\n text,\r\n );\r\n }\r\n throw new MavenCommandError(`Maven could not build the effective POM:\\n${mavenErrors(text)}`, text);\r\n }\r\n return parseEffectivePoms(readFileSync(output, 'utf8'));\r\n}\r\n\r\n/** Parses `help:effective-pom` output: one `<project>` or a reactor's `<projects>`. */\r\nexport function parseEffectivePoms(source: string): Map<string, EffectiveModel> {\r\n const root = parseXml(source);\r\n const projects = root.name === 'projects' ? children(root, 'project') : [root];\r\n const models = new Map<string, EffectiveModel>();\r\n for (const project of projects) {\r\n models.set(`${childText(project, 'groupId')}:${childText(project, 'artifactId')}`, toEffectiveModel(project));\r\n }\r\n return models;\r\n}\r\n\r\n/** Parses the output of `help:effective-pom` for a single project. */\r\nexport function parseEffectivePom(source: string): EffectiveModel {\r\n let project = parseXml(source);\r\n if (project.name === 'projects') project = child(project, 'project') ?? project;\r\n return toEffectiveModel(project);\r\n}\r\n\r\n/** Combines the repository declarations of several models; the first declaration per id wins. */\r\nexport function mergeRepositories(models: readonly EffectiveModel[]): EffectiveModel {\r\n const merge = (name: string, pick: (m: EffectiveModel) => XmlElement | undefined): XmlElement | undefined => {\r\n const byId = new Map<string, XmlElement>();\r\n for (const element of models.map(pick)) {\r\n for (const repository of element?.children ?? []) {\r\n const id = childText(repository, 'id') ?? childText(repository, 'url') ?? '';\r\n if (!byId.has(id)) byId.set(id, repository);\r\n }\r\n }\r\n return byId.size > 0 ? { name, attributes: {}, children: [...byId.values()], text: '' } : undefined;\r\n };\r\n return {\r\n dependencies: [],\r\n managedDependencies: [],\r\n repositories: merge('repositories', (m) => m.repositories),\r\n pluginRepositories: merge('pluginRepositories', (m) => m.pluginRepositories),\r\n };\r\n}\r\n\r\nfunction toEffectiveModel(project: XmlElement): EffectiveModel {\r\n return {\r\n dependencies: readEffectiveDependencies(child(project, 'dependencies')),\r\n managedDependencies: readEffectiveDependencies(childAt(project, 'dependencyManagement', 'dependencies')),\r\n repositories: child(project, 'repositories'),\r\n pluginRepositories: child(project, 'pluginRepositories'),\r\n };\r\n}\r\n\r\nfunction readEffectiveDependencies(container: XmlElement | undefined): EffectiveDependency[] {\r\n return children(container, 'dependency').map((element) => ({\r\n groupId: childText(element, 'groupId') ?? '',\r\n artifactId: childText(element, 'artifactId') ?? '',\r\n version: childText(element, 'version') ?? '',\r\n scope: childText(element, 'scope') ?? 'compile',\r\n type: childText(element, 'type') ?? 'jar',\r\n classifier: childText(element, 'classifier'),\r\n }));\r\n}\r\n\r\n/** Builds a minimal POM that manages exactly the given artifacts. */\r\nexport function buildProbePom(artifacts: readonly ProbeArtifact[], model: EffectiveModel): string {\r\n const seen = new Set<string>();\r\n const entries: string[] = [];\r\n for (const artifact of artifacts) {\r\n const key = `${artifact.groupId}:${artifact.artifactId}:${artifact.type ?? 'jar'}:${artifact.classifier ?? ''}`;\r\n if (seen.has(key)) continue;\r\n seen.add(key);\r\n const fields = [\r\n `<groupId>${escapeXml(artifact.groupId)}</groupId>`,\r\n `<artifactId>${escapeXml(artifact.artifactId)}</artifactId>`,\r\n `<version>${escapeXml(artifact.version)}</version>`,\r\n artifact.type && artifact.type !== 'jar' ? `<type>${escapeXml(artifact.type)}</type>` : '',\r\n artifact.classifier ? `<classifier>${escapeXml(artifact.classifier)}</classifier>` : '',\r\n ].filter(Boolean);\r\n entries.push(` <dependency>${fields.join('')}</dependency>`);\r\n }\r\n\r\n const repositories = [model.repositories, model.pluginRepositories]\r\n .filter((element): element is XmlElement => element !== undefined)\r\n .map((element) => serializeXml(element, ' '))\r\n .join('\\n');\r\n\r\n return [\r\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\r\n '<project xmlns=\"http://maven.apache.org/POM/4.0.0\">',\r\n ' <modelVersion>4.0.0</modelVersion>',\r\n ' <groupId>elevate.probe</groupId>',\r\n ' <artifactId>elevate-probe</artifactId>',\r\n ' <version>0</version>',\r\n ' <packaging>pom</packaging>',\r\n repositories,\r\n ' <dependencyManagement>',\r\n ' <dependencies>',\r\n ...entries,\r\n ' </dependencies>',\r\n ' </dependencyManagement>',\r\n '</project>',\r\n '',\r\n ]\r\n .filter((line) => line !== '')\r\n .join('\\n');\r\n}\r\n\r\n/** Looks up newer versions for the given artifacts with the versions-maven-plugin. */\r\nexport async function queryNewerVersions(\r\n artifacts: readonly ProbeArtifact[],\r\n model: EffectiveModel,\r\n moduleDir: string,\r\n rootDir: string,\r\n scratch: ScratchDirectory,\r\n plugins: MavenPluginVersions,\r\n): Promise<VersionReport> {\r\n if (artifacts.length === 0) return { newerVersions: new Map(), failedLookups: new Set() };\r\n\r\n const probeDir = join(scratch.path, 'probe');\r\n mkdirSync(probeDir, { recursive: true });\r\n const probePom = join(probeDir, 'pom.xml');\r\n writeFileSync(probePom, buildProbePom(artifacts, model), 'utf8');\r\n\r\n const result = await runMaven(\r\n [\r\n '-N',\r\n '-f',\r\n relativeToCwd(moduleDir, probePom),\r\n `${VERSIONS_PLUGIN_ID}:${plugins.versions}:dependency-updates-report`,\r\n '-DdependencyUpdatesReportFormats=xml',\r\n '-DprocessDependencyManagementTransitive=false',\r\n ],\r\n { cwd: moduleDir, rootDir, timeoutMs: MAVEN_TIMEOUT_MS },\r\n );\r\n\r\n const log = `${result.stdout}\\n${result.stderr}`;\r\n const reportFile = join(probeDir, 'target', 'dependency-updates-report.xml');\r\n if (result.exitCode !== 0 || !existsSync(reportFile)) {\r\n if (isPluginUnavailable(log, VERSIONS_PLUGIN_ID)) {\r\n throw new MavenPluginUnavailableError(\r\n { id: VERSIONS_PLUGIN_ID, version: plugins.versions, key: 'versions', purpose: 'look up newer versions' },\r\n log,\r\n );\r\n }\r\n throw new MavenCommandError(`Maven could not look up newer versions:\\n${mavenErrors(log)}`, log);\r\n }\r\n\r\n return {\r\n newerVersions: parseUpdatesReport(readFileSync(reportFile, 'utf8')),\r\n failedLookups: parseFailedLookups(log),\r\n };\r\n}\r\n\r\n/** Collects the newer versions per artifact from the plugin's XML report. */\r\nexport function parseUpdatesReport(source: string): Map<string, string[]> {\r\n const report = parseXml(source);\r\n const sections = [\r\n ...children(child(report, 'dependencyManagements'), 'dependencyManagement'),\r\n ...children(child(report, 'dependencies'), 'dependency'),\r\n ];\r\n\r\n const result = new Map<string, string[]>();\r\n for (const entry of sections) {\r\n const key = `${childText(entry, 'groupId')}:${childText(entry, 'artifactId')}`;\r\n const versions = [\r\n ...collect(entry, 'subIncrementals', 'subIncremental'),\r\n ...collect(entry, 'incrementals', 'incremental'),\r\n ...collect(entry, 'minors', 'minor'),\r\n ...collect(entry, 'majors', 'major'),\r\n ];\r\n const known = result.get(key) ?? [];\r\n for (const version of versions) if (!known.includes(version)) known.push(version);\r\n result.set(key, known);\r\n }\r\n return result;\r\n}\r\n\r\nfunction collect(entry: XmlElement, container: string, item: string): string[] {\r\n return children(child(entry, container), item)\r\n .map((element) => element.text.trim())\r\n .filter(Boolean);\r\n}\r\n\r\n/**\r\n * The plugin downgrades repository errors to warnings and then reports the\r\n * artifact as up to date. Those warnings are the only trace of a failed\r\n * lookup, so they are surfaced instead of trusting the \"no update\" result.\r\n */\r\nexport function parseFailedLookups(log: string): Set<string> {\r\n const failed = new Set<string>();\r\n const pattern = /Could not (?:transfer|read) metadata ([^:\\s/]+):([^:\\s/]+)(?::[^\\s/]+)?\\/maven-metadata\\.xml/g;\r\n for (const match of log.matchAll(pattern)) failed.add(`${match[1]}:${match[2]}`);\r\n return failed;\r\n}\r\n","/**\r\n * Elevate — Maven dependency scanner.\r\n *\r\n * For each module:\r\n * 1. Maven builds the effective POM: the versions that actually apply.\r\n * 2. Each dependency is classified by origin. Modules of the same reactor are\r\n * compared with their local version (alignment); all others, modules of\r\n * other reactors included, are looked up with the versions-maven-plugin\r\n * through the build's own repositories.\r\n * 3. For every offered change the declaring literal is located, so the\r\n * update edits the right file — possibly a parent POM's property.\r\n *\r\n * Offered per module: its effective dependencies, the dependency management\r\n * entries it declares itself (including imported BOMs) and its parent when\r\n * that parent is not part of the repository.\r\n *\r\n * Maven runs are expensive (a JVM start each), so `scanMany` batches modules\r\n * of one reactor: one effective POM for the whole reactor and one version\r\n * report for all artifacts of all requested modules.\r\n */\r\n\r\nimport { join } from 'node:path';\r\nimport type { DependencyReaderPort, ScanContext } from '../../domain/ports.js';\r\nimport type {\r\n DependencyOrigin,\r\n ProjectModule,\r\n ReleaseChannel,\r\n ScanResult,\r\n SkippedDependency,\r\n UpdateCandidate,\r\n} from '../../domain/models.js';\r\nimport { classifyOrigin } from '../../domain/origin.js';\r\nimport semver from 'semver';\r\nimport { cleanJavaVersion, diffVersions, extractPreReleaseTag, isPreReleaseVersion } from '../../domain/versions.js';\r\nimport { MavenProject } from './maven-project.js';\r\nimport { interpolate } from './maven-pom.js';\r\nimport type { PomModel } from './maven-pom.js';\r\nimport { locateDependencyVersion, locateManagedVersion, locateParentVersion } from './maven-locator.js';\r\nimport type { DeclarationLookup } from './maven-locator.js';\r\nimport { ScratchDirectory, mergeRepositories, queryNewerVersions, readEffectivePoms } from './maven-resolution.js';\r\nimport { DEFAULT_MAVEN_PLUGINS } from './maven-resolution.js';\r\nimport type { EffectiveModel, MavenPluginVersions, VersionReport } from './maven-resolution.js';\r\n\r\nconst DIFF_ORDER: Record<string, number> = { major: 0, minor: 1, patch: 2 };\r\n\r\n/** A dependency of the module together with how its version is located. */\r\ninterface Subject {\r\n groupId: string;\r\n artifactId: string;\r\n version: string;\r\n type?: string;\r\n classifier?: string;\r\n scope: UpdateCandidate['scope'];\r\n locate: (effectiveVersion: string) => DeclarationLookup;\r\n}\r\n\r\n/** A module whose dependencies are known but not yet looked up in the repositories. */\r\ninterface ModulePlan {\r\n module: ProjectModule;\r\n effective: EffectiveModel;\r\n candidates: UpdateCandidate[];\r\n skipped: SkippedDependency[];\r\n lookups: { subject: Subject; origin: DependencyOrigin }[];\r\n}\r\n\r\n/** Modules scanned with the same Maven runs. */\r\ninterface ScanGroup {\r\n /** Directory Maven runs in and the scratch directory lives below. */\r\n dir: string;\r\n /** Aggregator POM resolved recursively, when the group is a reactor batch. */\r\n aggregatorPom?: string;\r\n members: { module: ProjectModule; pom: PomModel }[];\r\n}\r\n\r\nexport class MavenDependencyAdapter implements DependencyReaderPort {\r\n constructor(private readonly plugins: MavenPluginVersions = DEFAULT_MAVEN_PLUGINS) {}\r\n\r\n async scan(module: ProjectModule, context: ScanContext): Promise<ScanResult> {\r\n const results = await this.scanMany([module], context);\r\n return results.get(module) ?? { candidates: [], skipped: [] };\r\n }\r\n\r\n async scanMany(modules: readonly ProjectModule[], context: ScanContext): Promise<Map<ProjectModule, ScanResult>> {\r\n const project = MavenProject.load(context.rootDir);\r\n const results = new Map<ProjectModule, ScanResult>();\r\n\r\n for (const group of groupModules(project, modules)) {\r\n const scratch = new ScratchDirectory(group.dir);\r\n try {\r\n for (const [module, result] of await this.scanGroup(project, group, context, scratch)) {\r\n results.set(module, result);\r\n }\r\n } finally {\r\n scratch.dispose();\r\n }\r\n }\r\n return results;\r\n }\r\n\r\n private async scanGroup(\r\n project: MavenProject,\r\n group: ScanGroup,\r\n context: ScanContext,\r\n scratch: ScratchDirectory,\r\n ): Promise<Map<ProjectModule, ScanResult>> {\r\n const rootDir = context.rootDir;\r\n const effectiveModels = group.aggregatorPom\r\n ? await readEffectivePoms(group.aggregatorPom, group.dir, rootDir, scratch, this.plugins, true)\r\n : await readEffectivePoms(group.members[0]!.pom.file, group.dir, rootDir, scratch, this.plugins);\r\n\r\n const plans: ModulePlan[] = [];\r\n for (const { module, pom } of group.members) {\r\n const coordinates = project.coordinatesOf(pom);\r\n // A module the reactor run did not cover (e.g. only listed in a profile)\r\n // is resolved on its own.\r\n const effective =\r\n effectiveModels.get(`${coordinates.groupId}:${coordinates.artifactId}`) ??\r\n (group.aggregatorPom\r\n ? [...(await readEffectivePoms(pom.file, module.path, rootDir, scratch, this.plugins)).values()][0]\r\n : [...effectiveModels.values()][0]);\r\n if (!effective) continue;\r\n plans.push(planModule(project, pom, module, effective, context));\r\n }\r\n\r\n const probe = plans.flatMap((plan) => plan.lookups.map(({ subject }) => subject));\r\n const report = await queryNewerVersions(\r\n probe,\r\n mergeRepositories(plans.map((plan) => plan.effective)),\r\n group.dir,\r\n rootDir,\r\n scratch,\r\n this.plugins,\r\n );\r\n\r\n return new Map(plans.map((plan) => [plan.module, finishModule(plan, report, context.channel)]));\r\n }\r\n}\r\n\r\n/**\r\n * Batches requested modules by reactor. A single module, or a module outside\r\n * any reactor, is resolved on its own (`-N`), which is cheaper than resolving\r\n * a whole reactor for it.\r\n */\r\nfunction groupModules(project: MavenProject, modules: readonly ProjectModule[]): ScanGroup[] {\r\n const groups = new Map<string, ScanGroup>();\r\n const reactorSizes = new Map<string, number>();\r\n for (const module of modules) {\r\n if (module.aggregatorDir) reactorSizes.set(module.aggregatorDir, (reactorSizes.get(module.aggregatorDir) ?? 0) + 1);\r\n }\r\n\r\n for (const module of modules) {\r\n const pom = project.pomAt(join(module.path, 'pom.xml'));\r\n if (!pom) continue;\r\n const reactor = module.aggregatorDir;\r\n const batched = reactor !== undefined && (reactorSizes.get(reactor) ?? 0) > 1;\r\n const key = batched ? `reactor:${reactor}` : `module:${module.path}`;\r\n const group = groups.get(key) ?? {\r\n dir: batched ? reactor : module.path,\r\n aggregatorPom: batched ? join(reactor, 'pom.xml') : undefined,\r\n members: [],\r\n };\r\n group.members.push({ module, pom });\r\n groups.set(key, group);\r\n }\r\n return [...groups.values()];\r\n}\r\n\r\n/** Collects the module's subjects, aligns workspace dependencies and lists the lookups. */\r\nfunction planModule(\r\n project: MavenProject,\r\n pom: PomModel,\r\n module: ProjectModule,\r\n effective: EffectiveModel,\r\n context: ScanContext,\r\n): ModulePlan {\r\n const { poms: chain, externalParent } = project.chainOf(pom);\r\n const rootDir = context.rootDir;\r\n const subjects = new Map<string, Subject>();\r\n\r\n for (const dep of effective.dependencies) {\r\n const key = `${dep.groupId}:${dep.artifactId}`;\r\n if (subjects.has(key)) continue;\r\n const target = { groupId: dep.groupId, artifactId: dep.artifactId };\r\n subjects.set(key, {\r\n ...dep,\r\n scope: dep.scope === 'test' ? 'test' : 'prod',\r\n locate: (effectiveVersion) => locateDependencyVersion(chain, { ...target, effectiveVersion }, rootDir),\r\n });\r\n }\r\n\r\n // Management entries declared by this module itself, including BOM imports.\r\n for (const managed of pom.managedDependencies) {\r\n const groupId = interpolate(managed.groupId, chain);\r\n const artifactId = interpolate(managed.artifactId, chain);\r\n const key = `${groupId}:${artifactId}`;\r\n if (subjects.has(key) || !managed.version) continue;\r\n\r\n const isImport = managed.scope === 'import';\r\n const version = isImport\r\n ? interpolate(managed.version, chain)\r\n : effective.managedDependencies.find((m) => m.groupId === groupId && m.artifactId === artifactId)?.version;\r\n if (!version || version.includes('${')) continue;\r\n\r\n const target = { groupId, artifactId };\r\n subjects.set(key, {\r\n groupId,\r\n artifactId,\r\n version,\r\n type: isImport ? 'pom' : managed.type,\r\n classifier: managed.classifier,\r\n scope: 'prod',\r\n locate: (effectiveVersion) => locateManagedVersion(chain, { ...target, effectiveVersion }, rootDir),\r\n });\r\n }\r\n\r\n // An external parent POM (e.g. spring-boot-starter-parent) declared here.\r\n if (pom.parent && externalParent === pom.parent) {\r\n const { groupId, artifactId } = pom.parent;\r\n const version = interpolate(pom.parent.version, chain);\r\n subjects.set(`${groupId}:${artifactId}`, {\r\n groupId,\r\n artifactId,\r\n version,\r\n type: 'pom',\r\n scope: 'prod',\r\n locate: (effectiveVersion) => locateParentVersion(pom, { groupId, artifactId, effectiveVersion }, rootDir),\r\n });\r\n }\r\n\r\n const plan: ModulePlan = { module, effective, candidates: [], skipped: [], lookups: [] };\r\n for (const [key, subject] of subjects) {\r\n const origin = classifyOrigin(key, 'maven', context);\r\n if (origin.kind !== 'workspace') {\r\n plan.lookups.push({ subject, origin });\r\n continue;\r\n }\r\n\r\n const target = context.workspace.get(key);\r\n if (target && inSameReactor(module, target)) {\r\n if (target.version && target.version !== subject.version) {\r\n collect(alignmentCandidate(subject, target.version, origin), plan.candidates, plan.skipped);\r\n }\r\n } else {\r\n // Maven resolves a project outside the reactor from a repository, like\r\n // any other artifact, so a local module with the same coordinates says\r\n // nothing about the version the build uses.\r\n plan.lookups.push({ subject, origin: classifyOrigin(key, 'maven', { ...context, workspace: new Map() }) });\r\n }\r\n }\r\n return plan;\r\n}\r\n\r\n/** Two modules are in the same reactor when both are built by the same outermost aggregator. */\r\nfunction inSameReactor(a: ProjectModule, b: ProjectModule): boolean {\r\n return a.aggregatorDir !== undefined && a.aggregatorDir === b.aggregatorDir;\r\n}\r\n\r\n/** Turns the version report into the module's candidates. */\r\nfunction finishModule(plan: ModulePlan, report: VersionReport, channel: ReleaseChannel): ScanResult {\r\n const { candidates, skipped } = plan;\r\n for (const { subject, origin } of plan.lookups) {\r\n const key = `${subject.groupId}:${subject.artifactId}`;\r\n const newer = newerThan(subject.version, report.newerVersions.get(key) ?? []);\r\n const latest = pickLatest(subject.version, newer, channel);\r\n if (!latest) {\r\n if (report.failedLookups.has(key)) {\r\n skipped.push({ identifier: key, origin: origin.kind, reason: 'lookup-failed', detail: 'repository error' });\r\n }\r\n continue;\r\n }\r\n collect(updateCandidate(subject, latest, newer, origin), candidates, skipped);\r\n }\r\n\r\n markSharedDeclarations(candidates);\r\n candidates.sort((a, b) => (DIFF_ORDER[a.diff] ?? 3) - (DIFF_ORDER[b.diff] ?? 3));\r\n return { candidates, skipped };\r\n}\r\n\r\n/**\r\n * In a batched report an artifact appears once, with the newer versions of\r\n * the first module that uses it. For a module on a later version, only the\r\n * part of that ascending list after its own version is newer.\r\n */\r\nexport function newerThan(current: string, ascending: readonly string[]): string[] {\r\n const index = ascending.indexOf(current);\r\n return index >= 0 ? ascending.slice(index + 1) : [...ascending];\r\n}\r\n\r\ntype Built = { candidate: UpdateCandidate } | { skipped: SkippedDependency };\r\n\r\nfunction collect(built: Built, candidates: UpdateCandidate[], skipped: SkippedDependency[]): void {\r\n if ('candidate' in built) candidates.push(built.candidate);\r\n else skipped.push(built.skipped);\r\n}\r\n\r\nfunction updateCandidate(subject: Subject, latest: string, newer: string[], origin: DependencyOrigin): Built {\r\n const base = buildCandidate(subject, latest, origin, 'update');\r\n if ('candidate' in base) {\r\n base.candidate.availableVersions = [...newer].reverse().concat(subject.version);\r\n }\r\n return base;\r\n}\r\n\r\nfunction alignmentCandidate(subject: Subject, localVersion: string, origin: DependencyOrigin): Built {\r\n const built = buildCandidate(subject, localVersion, origin, 'align');\r\n if ('candidate' in built) built.candidate.availableVersions = [localVersion];\r\n return built;\r\n}\r\n\r\nfunction buildCandidate(\r\n subject: Subject,\r\n target: string,\r\n origin: DependencyOrigin,\r\n action: UpdateCandidate['action'],\r\n): Built {\r\n const identifier = `${subject.groupId}:${subject.artifactId}`;\r\n const location = subject.locate(subject.version);\r\n if (!location.found) {\r\n return { skipped: { identifier, origin: origin.kind, reason: location.reason, detail: location.detail } };\r\n }\r\n\r\n const currentClean = cleanJavaVersion(subject.version) ?? '0.0.0';\r\n const targetClean = cleanJavaVersion(target) ?? currentClean;\r\n const diff = semver.eq(currentClean, targetClean) ? 'patch' : diffVersions(currentClean, targetClean);\r\n const isPreRelease = isPreReleaseVersion(target);\r\n\r\n return {\r\n candidate: {\r\n coordinate: { identifier, group: subject.groupId, artifact: subject.artifactId, ecosystem: 'maven' },\r\n currentRange: subject.version,\r\n currentClean,\r\n latest: target,\r\n newRange: target,\r\n diff,\r\n scope: subject.scope,\r\n selected: diff !== 'major',\r\n origin,\r\n action,\r\n declaration: location.declaration,\r\n isPreRelease,\r\n preReleaseTag: isPreRelease ? extractPreReleaseTag(target) : undefined,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Picks the newest version allowed by the channel. Newer versions arrive in\r\n * ascending order from the report. A flavour suffix such as `-jre` or\r\n * `-android` (Guava) is kept when a newer version with the same flavour\r\n * exists, so a JRE build is not replaced by an Android build.\r\n */\r\nexport function pickLatest(current: string, newer: readonly string[], channel: ReleaseChannel): string | undefined {\r\n const allowed = newer.filter((v) => channel === 'all' || !isPreReleaseVersion(v));\r\n const flavour = flavourOf(current);\r\n const sameFlavour = flavour ? allowed.filter((v) => flavourOf(v) === flavour) : [];\r\n const pool = sameFlavour.length > 0 ? sameFlavour : allowed;\r\n return pool[pool.length - 1];\r\n}\r\n\r\nfunction flavourOf(version: string): string | undefined {\r\n const suffix = version.match(/-([A-Za-z]+)$/)?.[1];\r\n return suffix && !isPreReleaseVersion(version) ? suffix.toLowerCase() : undefined;\r\n}\r\n\r\n/**\r\n * Several artifacts often share one version property (e.g. all Jackson\r\n * modules). Updating one updates all of them, which the UI must show.\r\n */\r\nfunction markSharedDeclarations(candidates: UpdateCandidate[]): void {\r\n const groups = new Map<string, UpdateCandidate[]>();\r\n for (const candidate of candidates) {\r\n const declaration = candidate.declaration;\r\n if (declaration?.kind !== 'property') continue;\r\n const key = `${declaration.file}#${declaration.propertyName}`;\r\n groups.set(key, [...(groups.get(key) ?? []), candidate]);\r\n }\r\n for (const group of groups.values()) {\r\n if (group.length < 2) continue;\r\n for (const candidate of group) {\r\n candidate.sharedWith = group\r\n .filter((other) => other !== candidate)\r\n .map((other) => other.coordinate.identifier);\r\n }\r\n }\r\n}\r\n\r\n","/**\r\n * Elevate — locates where a Maven dependency's version is declared.\r\n *\r\n * Maven's effective POM says which version applies, not where it is written.\r\n * An update must change the declaring literal: a `<version>` in the module,\r\n * a `<dependencyManagement>` entry or a property — possibly in a parent POM.\r\n *\r\n * The lookup follows Maven's rules on the raw POMs of the inheritance chain\r\n * and then cross-checks the literal against the effective version. If they\r\n * differ (active profiles, command-line properties, unusual inheritance) the\r\n * location is reported as a mismatch instead of guessed. Declarations outside\r\n * the repository (external parent POMs, imported BOMs) are reported as such:\r\n * they cannot be edited here; the parent or BOM itself has to be updated.\r\n */\r\n\r\nimport { relative } from 'node:path';\r\nimport type { VersionDeclaration } from '../../domain/models.js';\r\nimport type { XmlElement } from '../shared/xml.js';\r\nimport { findProperty, interpolate, propertyReference } from './maven-pom.js';\r\nimport type { PomDependency, PomModel } from './maven-pom.js';\r\n\r\nexport type DeclarationLookup =\r\n | { found: true; declaration: VersionDeclaration; element: XmlElement; value: string }\r\n | { found: false; reason: 'managed-externally' | 'declaration-mismatch'; detail: string };\r\n\r\ninterface Target {\r\n groupId: string;\r\n artifactId: string;\r\n /** The version Maven resolved for this dependency. */\r\n effectiveVersion: string;\r\n}\r\n\r\n/**\r\n * Locates the version of a dependency used by the first POM of `chain`.\r\n *\r\n * Search order, as Maven applies it: an explicit `<version>` in the module's\r\n * own dependency, then one inherited from a parent's `<dependencies>`, then\r\n * `<dependencyManagement>` from the module upwards.\r\n */\r\nexport function locateDependencyVersion(\r\n chain: readonly PomModel[],\r\n target: Target,\r\n rootDir: string,\r\n): DeclarationLookup {\r\n for (const pom of chain) {\r\n const dependency = findDependency(pom.dependencies, target, chain);\r\n if (!dependency) continue;\r\n // The nearest declaration wins entirely; without a version it is managed.\r\n if (!dependency.versionElement) break;\r\n return resolveLiteral(pom, 'dependency', dependency.versionElement, chain, target, rootDir);\r\n }\r\n return locateManagedVersion(chain, target, rootDir);\r\n}\r\n\r\n/** Locates a `<dependencyManagement>` version, searching from the module upwards. */\r\nexport function locateManagedVersion(\r\n chain: readonly PomModel[],\r\n target: Target,\r\n rootDir: string,\r\n): DeclarationLookup {\r\n for (const pom of chain) {\r\n const managed = findDependency(pom.managedDependencies, target, chain);\r\n if (managed?.versionElement) {\r\n return resolveLiteral(pom, 'dependency-management', managed.versionElement, chain, target, rootDir);\r\n }\r\n }\r\n return {\r\n found: false,\r\n reason: 'managed-externally',\r\n detail: 'version is managed outside this repository (external parent POM or imported BOM)',\r\n };\r\n}\r\n\r\n/** Locates the `<parent>` version of the module (for external parents). */\r\nexport function locateParentVersion(module: PomModel, target: Target, rootDir: string): DeclarationLookup {\r\n const element = module.parent?.versionElement;\r\n if (!element) {\r\n return { found: false, reason: 'declaration-mismatch', detail: 'parent has no <version> element' };\r\n }\r\n return resolveLiteral(module, 'parent', element, [module], target, rootDir);\r\n}\r\n\r\nfunction findDependency(\r\n dependencies: readonly PomDependency[],\r\n target: Target,\r\n chain: readonly PomModel[],\r\n): PomDependency | undefined {\r\n return dependencies.find(\r\n (dep) =>\r\n dep.scope !== 'import' &&\r\n interpolate(dep.groupId, chain) === target.groupId &&\r\n interpolate(dep.artifactId, chain) === target.artifactId,\r\n );\r\n}\r\n\r\n/**\r\n * Follows property references from a `<version>` element to the literal that\r\n * finally holds the value. Properties resolve from the module upwards — a\r\n * child's definition overrides the parent's, even for a version written in\r\n * the parent.\r\n */\r\nfunction resolveLiteral(\r\n pom: PomModel,\r\n kind: 'dependency' | 'dependency-management' | 'parent',\r\n versionElement: XmlElement,\r\n chain: readonly PomModel[],\r\n target: Target,\r\n rootDir: string,\r\n): DeclarationLookup {\r\n let file = pom.file;\r\n let element = versionElement;\r\n let value = versionElement.text.trim();\r\n let propertyName: string | undefined;\r\n\r\n for (let depth = 0; depth < 10; depth++) {\r\n const reference = propertyReference(value);\r\n if (!reference) break;\r\n if (reference.startsWith('project.') || reference.startsWith('pom.')) {\r\n return {\r\n found: false,\r\n reason: 'declaration-mismatch',\r\n detail: `version is the expression \\${${reference}}, not an editable value`,\r\n };\r\n }\r\n const definition = findProperty(reference, chain);\r\n if (!definition) {\r\n return {\r\n found: false,\r\n reason: 'managed-externally',\r\n detail: `property \\${${reference}} is defined outside this repository`,\r\n };\r\n }\r\n file = definition.pom.file;\r\n element = definition.property.element;\r\n value = definition.property.value;\r\n propertyName = reference;\r\n }\r\n\r\n if (value.includes('${')) {\r\n return {\r\n found: false,\r\n reason: 'declaration-mismatch',\r\n detail: `version '${value}' combines several expressions`,\r\n };\r\n }\r\n\r\n if (value !== target.effectiveVersion) {\r\n return {\r\n found: false,\r\n reason: 'declaration-mismatch',\r\n detail: `declared '${value}' but Maven resolves '${target.effectiveVersion}' (profile or command-line override?)`,\r\n };\r\n }\r\n\r\n const declaration: VersionDeclaration = {\r\n file,\r\n kind: propertyName ? 'property' : kind,\r\n propertyName,\r\n displayPath: relative(rootDir, file).replace(/\\\\/g, '/'),\r\n };\r\n return { found: true, declaration, element, value };\r\n}\r\n","/**\r\n * Elevate — Maven updater.\r\n *\r\n * Writes each new version to the literal that declares it — a dependency's\r\n * `<version>`, a `<dependencyManagement>` entry, a `<parent>` version or a\r\n * property, possibly in a parent POM. Edits splice the original text, so\r\n * formatting and comments stay intact, and each edit checks that the file\r\n * still holds the value seen during the scan.\r\n *\r\n * Dependency resolution is left to the verification step, which builds the\r\n * affected modules.\r\n */\r\n\r\nimport { readFileSync, writeFileSync } from 'node:fs';\r\nimport { join, resolve } from 'node:path';\r\nimport { InstallError } from '../../domain/ports.js';\r\nimport type { ApplyOutcome, DependencyUpdaterPort } from '../../domain/ports.js';\r\nimport type { ProjectModule, UpdateCandidate, VersionDeclaration } from '../../domain/models.js';\r\nimport { StaleEditError, applyTextEdits } from '../shared/xml.js';\r\nimport type { TextEdit, XmlElement } from '../shared/xml.js';\r\nimport { interpolate, parsePom } from './maven-pom.js';\r\nimport type { PomDependency, PomModel } from './maven-pom.js';\r\nimport { MavenProject } from './maven-project.js';\r\n\r\nexport class MavenUpdaterAdapter implements DependencyUpdaterPort {\r\n affectedFiles(module: ProjectModule, _rootDir: string, updates: UpdateCandidate[]): string[] {\r\n const files = new Set(updates.map((u) => resolve(u.declaration?.file ?? join(module.path, 'pom.xml'))));\r\n return [...files];\r\n }\r\n\r\n async applyUpdates(\r\n module: ProjectModule,\r\n rootDir: string,\r\n updates: UpdateCandidate[],\r\n onProgress: (stepMessage: string) => void,\r\n ): Promise<ApplyOutcome> {\r\n const project = MavenProject.load(rootDir);\r\n const byFile = new Map<string, UpdateCandidate[]>();\r\n for (const update of updates) {\r\n if (!update.declaration) {\r\n throw new InstallError(`No version declaration known for ${update.coordinate.identifier}; rescan the module.`);\r\n }\r\n const file = resolve(update.declaration.file);\r\n byFile.set(file, [...(byFile.get(file) ?? []), update]);\r\n }\r\n\r\n // Compute every edit before writing anything, so a stale or conflicting\r\n // edit in the second file does not leave the first one half-updated.\r\n const writes: { file: string; content: string }[] = [];\r\n for (const [file, fileUpdates] of byFile) {\r\n onProgress(`Preparing ${fileUpdates.length} change(s) in ${fileUpdates[0]!.declaration!.displayPath}…`);\r\n const source = readFileSync(file, 'utf8');\r\n const pom = parsePom(source, file);\r\n const chain = project.pomAt(file) ? project.chainOf(project.pomAt(file)!).poms : [pom];\r\n const edits = collectEdits(pom, [pom, ...chain.slice(1)], fileUpdates);\r\n try {\r\n writes.push({ file, content: applyTextEdits(source, edits) });\r\n } catch (err) {\r\n if (err instanceof StaleEditError) throw new InstallError(`${file}: ${err.message}`);\r\n throw err;\r\n }\r\n }\r\n\r\n onProgress('Writing POM files…');\r\n for (const write of writes) writeFileSync(write.file, write.content, 'utf8');\r\n\r\n return {\r\n updatedCount: updates.length,\r\n auditMessage: `Updated ${updates.length} version declaration(s) in ${writes.length} POM file(s).`,\r\n auditSeverity: 'clean',\r\n integrityViolations: [],\r\n };\r\n }\r\n\r\n async resync(): Promise<void> {\r\n // Maven keeps no installed state next to the POMs; restoring them suffices.\r\n }\r\n}\r\n\r\n/** Maps updates to text edits; updates sharing one literal must agree on the version. */\r\nfunction collectEdits(pom: PomModel, chain: readonly PomModel[], updates: UpdateCandidate[]): TextEdit[] {\r\n const edits = new Map<XmlElement, TextEdit & { identifier: string }>();\r\n\r\n for (const update of updates) {\r\n const element = findDeclarationElement(pom, chain, update);\r\n if (!element) {\r\n throw new InstallError(\r\n `${update.declaration!.displayPath}: cannot find the version of ${update.coordinate.identifier} any more; rescan the module.`,\r\n );\r\n }\r\n\r\n const existing = edits.get(element);\r\n if (existing) {\r\n if (existing.replacement !== update.newRange) {\r\n throw new InstallError(\r\n `${update.coordinate.identifier} and ${existing.identifier} share ${describe(update.declaration!)} ` +\r\n `but target different versions (${update.newRange} vs ${existing.replacement}).`,\r\n );\r\n }\r\n continue;\r\n }\r\n edits.set(element, {\r\n element,\r\n expected: update.currentRange,\r\n replacement: update.newRange,\r\n identifier: update.coordinate.identifier,\r\n });\r\n }\r\n return [...edits.values()];\r\n}\r\n\r\nfunction findDeclarationElement(\r\n pom: PomModel,\r\n chain: readonly PomModel[],\r\n update: UpdateCandidate,\r\n): XmlElement | undefined {\r\n const declaration = update.declaration!;\r\n const { group, artifact } = update.coordinate;\r\n\r\n const matches = (dep: PomDependency) =>\r\n interpolate(dep.groupId, chain) === group && interpolate(dep.artifactId, chain) === artifact;\r\n\r\n switch (declaration.kind) {\r\n case 'property':\r\n return declaration.propertyName ? pom.properties.get(declaration.propertyName)?.element : undefined;\r\n case 'parent':\r\n return pom.parent?.versionElement;\r\n case 'dependency':\r\n return pom.dependencies.find(matches)?.versionElement;\r\n case 'dependency-management':\r\n return pom.managedDependencies.find(matches)?.versionElement;\r\n }\r\n}\r\n\r\nfunction describe(declaration: VersionDeclaration): string {\r\n return declaration.kind === 'property'\r\n ? `the property \\${${declaration.propertyName}} in ${declaration.displayPath}`\r\n : `a version in ${declaration.displayPath}`;\r\n}\r\n","/**\r\n * Elevate — Maven verification.\r\n *\r\n * Compiles main and test sources of every module affected by the update.\r\n * Within a reactor this is `-pl <changed modules> -amd`: the modules whose\r\n * POMs changed plus all modules that depend on them, because a version change\r\n * in an internal library breaks its consumers, not the library itself.\r\n * A change to the aggregator POM, or to a POM outside the reactor, rebuilds\r\n * the whole reactor.\r\n */\r\n\r\nimport { dirname, join, relative, resolve } from 'node:path';\r\nimport type { VerificationOptions, VerificationPort, VerificationResult } from '../../domain/ports.js';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { runShellScript } from '../shared/process.js';\r\nimport type { RunResult } from '../shared/process.js';\r\nimport { MavenUnavailableError, mavenErrors, runMaven } from './maven-command.js';\r\nimport { MavenProject } from './maven-project.js';\r\n\r\nconst VERIFY_TIMEOUT_MS = 30 * 60_000;\r\n\r\nexport class MavenVerificationAdapter implements VerificationPort {\r\n async verify(module: ProjectModule, rootDir: string, options: VerificationOptions = {}): Promise<VerificationResult> {\r\n if (options.customScript) {\r\n const label = options.customLabel || options.customScript;\r\n const result = await runShellScript(options.customScript, { cwd: module.path, timeoutMs: VERIFY_TIMEOUT_MS });\r\n return result.exitCode === 0\r\n ? { status: 'clean', details: 'Verification script succeeded.', label }\r\n : { status: 'warn', details: failureDetails(result), label };\r\n }\r\n\r\n const plan = planBuild(module, rootDir, options.changedFiles ?? []);\r\n const label = `Maven build (${['test-compile', ...plan.args].join(' ')})`;\r\n\r\n try {\r\n const result = await runMaven(['-q', 'test-compile', ...plan.args], {\r\n cwd: plan.cwd,\r\n rootDir,\r\n timeoutMs: VERIFY_TIMEOUT_MS,\r\n });\r\n if (result.exitCode === 0) {\r\n return { status: 'clean', details: 'All affected modules compile, including tests.', label };\r\n }\r\n const details = result.timedOut ? 'Maven build timed out.' : failureDetails(result);\r\n return { status: 'warn', details, label };\r\n } catch (err) {\r\n if (err instanceof MavenUnavailableError) return { status: 'warn', details: err.message, label };\r\n throw err;\r\n }\r\n }\r\n}\r\n\r\n/** Maven's error lines, or the exit code when the command printed nothing. */\r\nfunction failureDetails(result: RunResult): string {\r\n const output = `${result.stdout}\\n${result.stderr}`.trim();\r\n return output ? mavenErrors(output) : `Exited with code ${result.exitCode}.`;\r\n}\r\n\r\ninterface BuildPlan {\r\n cwd: string;\r\n args: string[];\r\n}\r\n\r\n/** Chooses where to run Maven and which reactor modules to build. */\r\nexport function planBuild(module: ProjectModule, rootDir: string, changedFiles: readonly string[]): BuildPlan {\r\n const aggregatorDir = module.aggregatorDir;\r\n if (!aggregatorDir) return { cwd: module.path, args: [] };\r\n\r\n const project = MavenProject.load(rootDir);\r\n const files = changedFiles.length > 0 ? changedFiles : [join(module.path, 'pom.xml')];\r\n const selected = new Set<string>();\r\n\r\n for (const file of files) {\r\n const pom = project.pomAt(file);\r\n const dir = resolve(dirname(file));\r\n // Not part of this reactor, or the aggregator itself: everything may be affected.\r\n if (!pom || project.aggregatorDirOf(pom) !== aggregatorDir || dir === resolve(aggregatorDir)) {\r\n return { cwd: aggregatorDir, args: [] };\r\n }\r\n selected.add(relative(aggregatorDir, dir).replace(/\\\\/g, '/'));\r\n }\r\n\r\n return { cwd: aggregatorDir, args: ['-pl', [...selected].join(','), '-amd'] };\r\n}\r\n","/**\r\n * Elevate — Maven ecosystem strategy: wires the Maven adapters together.\r\n */\r\n\r\nimport type { EcosystemStrategy, TabLabels } from '../../domain/ecosystem-strategy.js';\r\nimport type { Ecosystem } from '../../domain/models.js';\r\nimport { mavenVersionPolicy } from '../../domain/version-policy.js';\r\nimport { MavenModuleDiscoveryAdapter } from './maven-discovery.js';\r\nimport { MavenRegistryAdapter } from './maven-registry.js';\r\nimport { MavenDependencyAdapter } from './maven-scanner.js';\r\nimport { MavenUpdaterAdapter } from './maven-updater.js';\r\nimport { MavenVerificationAdapter } from './maven-verifier.js';\r\nimport { DEFAULT_MAVEN_PLUGINS } from './maven-resolution.js';\r\nimport type { MavenPluginVersions } from './maven-resolution.js';\r\n\r\nexport class MavenEcosystemStrategy implements EcosystemStrategy {\r\n readonly ecosystem: Ecosystem = 'maven';\r\n readonly displayName = 'Java / Maven';\r\n readonly icon = '☕';\r\n readonly manifestFile = 'pom.xml';\r\n readonly versioning = mavenVersionPolicy;\r\n\r\n readonly discovery = new MavenModuleDiscoveryAdapter();\r\n readonly registry: MavenRegistryAdapter;\r\n readonly reader: MavenDependencyAdapter;\r\n readonly updater = new MavenUpdaterAdapter();\r\n readonly verifier = new MavenVerificationAdapter();\r\n\r\n /** @param plugins versions of the Maven plugins Elevate runs (default: the pinned ones) */\r\n constructor(plugins: MavenPluginVersions = DEFAULT_MAVEN_PLUGINS) {\r\n this.registry = new MavenRegistryAdapter(plugins);\r\n this.reader = new MavenDependencyAdapter(plugins);\r\n }\r\n\r\n getTabLabels(\r\n counts: { total: number; prodCount: number; devCount: number },\r\n _t: any,\r\n ): TabLabels {\r\n return {\r\n all: `[1] Alle (${counts.total})`,\r\n prod: `[2] Compile (${counts.prodCount})`,\r\n dev: `[3] Test (${counts.devCount})`,\r\n };\r\n }\r\n}\r\n","/**\r\n * Elevate — Gradle module discovery.\r\n *\r\n * Finds the Gradle builds of a repository by walking the tree (no process),\r\n * asks Gradle to describe each build that no outer build includes, and turns\r\n * the descriptions into modules. A build file is a program, so the projects\r\n * are Gradle's answer, not a parse of the files (specs/22).\r\n */\r\n\r\nimport { existsSync, readFileSync, readdirSync, realpathSync } from 'node:fs';\r\nimport { basename, dirname, join, relative, resolve } from 'node:path';\r\nimport type { ModuleDiscoveryPort } from '../../domain/ports.js';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { runDescribe } from './gradle-probe.js';\r\nimport type { GradleBuildDocument, GradleProjectDocument } from './gradle-probe.js';\r\n\r\nconst SETTINGS_FILES = ['settings.gradle', 'settings.gradle.kts'];\r\nconst BUILD_FILES = ['build.gradle', 'build.gradle.kts'];\r\nconst MAX_DEPTH = 6;\r\nconst SKIPPED_DIRECTORIES = new Set(['node_modules', 'target', 'build', 'dist', 'out', 'buildSrc']);\r\n\r\nfunction hasSettings(dir: string): boolean {\r\n return SETTINGS_FILES.some((file) => existsSync(join(dir, file)));\r\n}\r\n\r\nfunction hasBuildScript(dir: string): boolean {\r\n return BUILD_FILES.some((file) => existsSync(join(dir, file)));\r\n}\r\n\r\nfunction subdirectories(dir: string): string[] {\r\n try {\r\n return readdirSync(dir, { withFileTypes: true })\r\n .filter((entry) => entry.isDirectory())\r\n .map((entry) => entry.name)\r\n .sort();\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * The directories of the Gradle builds below `rootDir`, found without running\r\n * Gradle: a directory with a settings file, or with a build script when\r\n * neither it nor an ancestor up to the root has a settings file. Absolute and\r\n * sorted (an outer build comes before the builds below it).\r\n */\r\nexport function findGradleBuildDirs(rootDir: string): string[] {\r\n const root = resolve(rootDir);\r\n const found: string[] = [];\r\n\r\n const walk = (dir: string, depth: number, settingsAbove: boolean): void => {\r\n const settings = hasSettings(dir);\r\n const script = hasBuildScript(dir);\r\n if (settings || (script && !settingsAbove)) found.push(dir);\r\n if (depth >= MAX_DEPTH) return;\r\n\r\n const inScope = settingsAbove || settings;\r\n for (const name of subdirectories(dir)) {\r\n if (name.startsWith('.') || SKIPPED_DIRECTORIES.has(name)) continue;\r\n // The source tree of a project holds fixtures and sample builds.\r\n if (name === 'src' && (settings || script)) continue;\r\n walk(join(dir, name), depth + 1, inScope);\r\n }\r\n };\r\n\r\n walk(root, 0, false);\r\n return found.sort();\r\n}\r\n\r\n// ---- repository root ---------------------------------------------------------\r\n\r\n/** Removes block and line comments from a settings file. */\r\nfunction stripComments(text: string): string {\r\n return text.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').replace(/\\/\\/[^\\n]*/g, '');\r\n}\r\n\r\n/** Whether the settings file of `settingsDir` includes `target` with `includeBuild` and a string literal. */\r\nfunction includesBuild(settingsDir: string, target: string): boolean {\r\n for (const file of SETTINGS_FILES) {\r\n let text: string;\r\n try {\r\n text = stripComments(readFileSync(join(settingsDir, file), 'utf8'));\r\n } catch {\r\n continue;\r\n }\r\n for (const match of text.matchAll(/includeBuild\\s*\\(?\\s*(['\"])(.*?)\\1/g)) {\r\n if (resolve(settingsDir, match[2]!) === target) return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/** Strict ancestors of `dir`, nearest first, up to and including the boundary. */\r\nfunction ancestorsWithin(dir: string, boundary: string | undefined): string[] {\r\n const result: string[] = [];\r\n let current = dir;\r\n while (current !== boundary) {\r\n const parent = dirname(current);\r\n if (parent === current) break;\r\n result.push(parent);\r\n current = parent;\r\n }\r\n return result;\r\n}\r\n\r\nexport class GradleModuleDiscoveryAdapter implements ModuleDiscoveryPort {\r\n /**\r\n * Proposes the root of the Gradle build around `startDir`: the nearest\r\n * settings file (else the start directory's own build script), `buildSrc`\r\n * belonging to the build around it, and builds climbing to the outermost\r\n * build that includes them with a literal `includeBuild`. Reads settings\r\n * files as text and starts no process.\r\n */\r\n findRoot(startDir: string, boundaryDir: string | undefined): string | undefined {\r\n const start = resolve(startDir);\r\n const boundary = boundaryDir ? resolve(boundaryDir) : undefined;\r\n\r\n let dir: string | undefined;\r\n if (hasSettings(start)) {\r\n dir = start;\r\n } else {\r\n dir = ancestorsWithin(start, boundary).find((ancestor) => hasSettings(ancestor));\r\n }\r\n if (!dir) {\r\n if (!hasBuildScript(start)) return undefined;\r\n dir = start;\r\n }\r\n\r\n if (basename(dir) === 'buildSrc') {\r\n const parent = ancestorsWithin(dir, boundary)[0];\r\n if (parent && hasSettings(parent)) dir = parent;\r\n }\r\n\r\n for (;;) {\r\n const current = dir;\r\n const includer = ancestorsWithin(current, boundary).find(\r\n (ancestor) => hasSettings(ancestor) && includesBuild(ancestor, current),\r\n );\r\n if (!includer) return current;\r\n dir = includer;\r\n }\r\n }\r\n\r\n async discover(rootDir: string): Promise<ProjectModule[]> {\r\n const root = resolve(rootDir);\r\n const buildDirs = findGradleBuildDirs(root);\r\n if (buildDirs.length === 0) return [];\r\n\r\n // An outer build comes first; a build it includes is described by it.\r\n const described = new Set<string>();\r\n const builds: { document: GradleBuildDocument; runDir: string }[] = [];\r\n for (const runDir of buildDirs) {\r\n if (described.has(canonical(runDir))) continue;\r\n for (const document of await runDescribe(runDir, root)) {\r\n described.add(canonical(document.build.dir));\r\n builds.push({ document, runDir });\r\n }\r\n }\r\n\r\n const modules: ProjectModule[] = [];\r\n const taken = new Set<string>();\r\n for (const { document, runDir } of builds) {\r\n if (isOutside(root, document.build.dir)) continue;\r\n const primary = canonical(document.build.dir) === canonical(root) && document.build.kind === 'root';\r\n\r\n for (const project of document.projects) {\r\n const isBuildRoot = project.path === ':';\r\n if (!isBuildRoot && !project.buildFile) continue;\r\n if (isOutside(root, project.dir)) continue;\r\n const module = toModule(document, project, runDir, root, primary);\r\n if (taken.has(module.id)) module.id = `${module.id}@${module.relPath}`;\r\n taken.add(module.id);\r\n modules.push(module);\r\n }\r\n }\r\n\r\n modules.sort((a, b) => (a.isRoot ? -1 : b.isRoot ? 1 : a.relPath.localeCompare(b.relPath)));\r\n return modules;\r\n }\r\n}\r\n\r\nfunction canonical(dir: string): string {\r\n try {\r\n return realpathSync(dir);\r\n } catch {\r\n return resolve(dir);\r\n }\r\n}\r\n\r\nfunction isOutside(root: string, dir: string): boolean {\r\n const path = relative(canonical(root), canonical(dir));\r\n return path.startsWith('..') || resolve(path) === path;\r\n}\r\n\r\n/**\r\n * The id of a project: its Gradle path in the primary build, and the name of\r\n * the build first in every other build (an included build, buildSrc, an\r\n * independent build in a subdirectory): `:build-logic`, `:buildSrc`, `:demo`.\r\n */\r\nexport function gradleModuleId(\r\n build: GradleBuildDocument['build'],\r\n project: Pick<GradleProjectDocument, 'path'>,\r\n primary: boolean,\r\n): string {\r\n return primary ? project.path : `:${build.name}${project.path === ':' ? '' : project.path}`;\r\n}\r\n\r\nfunction toModule(\r\n document: GradleBuildDocument,\r\n project: GradleProjectDocument,\r\n runDir: string,\r\n root: string,\r\n primary: boolean,\r\n): ProjectModule {\r\n const build = document.build;\r\n const isBuildRoot = project.path === ':';\r\n const relPath = relative(canonical(root), canonical(project.dir)).replace(/\\\\/g, '/');\r\n const id = gradleModuleId(build, project, primary);\r\n const version = project.version && project.version !== 'unspecified' ? project.version : undefined;\r\n const name = isBuildRoot ? build.name : project.name;\r\n\r\n return {\r\n id,\r\n name,\r\n path: project.dir,\r\n relPath: relPath || 'Root',\r\n ecosystem: 'gradle',\r\n isRoot: isBuildRoot && primary,\r\n version,\r\n buildDir: runDir,\r\n buildRoot: build.dir,\r\n buildKind: build.kind,\r\n coordinates: project.group ? `${project.group}:${project.name}` : undefined,\r\n };\r\n}\r\n","/**\r\n * Elevate — the Gradle probe: asks Gradle instead of parsing build files.\r\n *\r\n * Two runs of the build's own Gradle with a small init script (`-I`):\r\n * `describe` (builds, projects, declared dependencies, repositories) and\r\n * `lookup` (which versions of given coordinates the repositories hold). The\r\n * answers are JSON files below `.gradle/elevate-<id>/out`, never console\r\n * output. The protocol is fixed in specs/README.md (\"The probe protocol\").\r\n */\r\n\r\nimport { randomBytes } from 'node:crypto';\r\nimport { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, rmdirSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { relativeToCwd } from '../shared/process.js';\r\nimport type { RunResult } from '../shared/process.js';\r\nimport { GradleCommandError, GradleVersionError, gradleFailure, runGradle } from './gradle-command.js';\r\nimport type { GradleRunOptions } from './gradle-command.js';\r\nimport { PROBE_INIT_SCRIPT } from './gradle-init-script.js';\r\n\r\n// ---- documents of the probe protocol ---------------------------------------\r\n\r\nexport interface GradleRepositoryDocument {\r\n name: string;\r\n kind: 'maven' | 'ivy' | 'flatDir' | 'other';\r\n url: string | null;\r\n}\r\n\r\nexport interface GradleDependencyDocument {\r\n configuration: string;\r\n group: string | null;\r\n name: string;\r\n version: string | null;\r\n strictly: string | null;\r\n preferred: string | null;\r\n rejected: string[];\r\n category: 'platform' | 'enforced-platform' | null;\r\n fromCatalog: boolean;\r\n classifier: string | null;\r\n extension: string | null;\r\n}\r\n\r\nexport interface GradleConstraintDocument {\r\n configuration: string;\r\n group: string | null;\r\n name: string;\r\n version: string | null;\r\n strictly: string | null;\r\n}\r\n\r\nexport interface GradleProjectDocument {\r\n path: string;\r\n name: string;\r\n dir: string;\r\n buildFile: string | null;\r\n group: string | null;\r\n version: string | null;\r\n repositories: GradleRepositoryDocument[];\r\n buildscriptRepositories: GradleRepositoryDocument[];\r\n dependencies: GradleDependencyDocument[];\r\n constraints: GradleConstraintDocument[];\r\n projectDependencies: { configuration: string; path: string }[];\r\n buildscriptDependencies: { group: string | null; name: string; version: string | null }[];\r\n /** The names `testClasses` and `assemble` that exist in the project. */\r\n tasks: string[];\r\n /** Whether `<dir>/gradle.lockfile` exists. */\r\n lockfile: boolean;\r\n}\r\n\r\nexport interface GradleBuildDocument {\r\n protocol: 1;\r\n mode: 'describe';\r\n gradleVersion: string;\r\n build: {\r\n name: string;\r\n kind: 'root' | 'included' | 'buildSrc';\r\n dir: string;\r\n repositoriesMode: string | null;\r\n settingsRepositories: GradleRepositoryDocument[];\r\n pluginRepositories: GradleRepositoryDocument[];\r\n settingsPlugins: { id: string; version: string | null }[];\r\n };\r\n /** Every project of the build, the root project first. */\r\n projects: GradleProjectDocument[];\r\n}\r\n\r\nexport interface LookupPlanEntry {\r\n id: string;\r\n /** `build.dir` of the build the project belongs to. */\r\n buildRoot: string;\r\n project: string;\r\n kind: 'module' | 'plugin';\r\n group: string;\r\n name: string;\r\n}\r\n\r\nexport interface LookupPlan {\r\n protocol: 1;\r\n publicRepositoryUrls: string[];\r\n internalGroupPatterns: string[];\r\n lookups: LookupPlanEntry[];\r\n}\r\n\r\nexport interface LookupResultDocument {\r\n id: string;\r\n /** In the order the rule saw them, duplicates kept. */\r\n versions: string[];\r\n /** `null` when Gradle ended with the \"not found\" failure. */\r\n error: string | null;\r\n}\r\n\r\ninterface LookupDocument {\r\n protocol: 1;\r\n mode: 'lookup';\r\n results: LookupResultDocument[];\r\n}\r\n\r\n// ---- runs --------------------------------------------------------------------\r\n\r\nconst PROBE_TIMEOUT_MINUTES = 5;\r\nconst MINIMUM_GRADLE = [7, 6] as const;\r\nconst SUPPORTED_NOTE = 'checked with 7.6.6, 8.14.3 and 9.8.1';\r\n\r\n/** Compares a Gradle version string with the supported minimum. */\r\nfunction isTooOld(gradleVersion: string): boolean {\r\n const match = /^(\\d+)(?:\\.(\\d+))?/.exec(gradleVersion);\r\n if (!match) return false;\r\n const major = Number(match[1]);\r\n const minor = Number(match[2] ?? 0);\r\n return major < MINIMUM_GRADLE[0] || (major === MINIMUM_GRADLE[0] && minor < MINIMUM_GRADLE[1]);\r\n}\r\n\r\ninterface Scratch {\r\n /** The directory `.gradle/elevate-<id>` (absolute). */\r\n dir: string;\r\n script: string;\r\n plan: string;\r\n out: string;\r\n /** Whether the run created `.gradle` itself. */\r\n createdGradleDir: boolean;\r\n gradleDir: string;\r\n}\r\n\r\nfunction createScratch(buildDir: string, plan?: LookupPlan): Scratch {\r\n const gradleDir = join(buildDir, '.gradle');\r\n const createdGradleDir = !existsSync(gradleDir);\r\n const dir = join(gradleDir, `elevate-${randomBytes(4).toString('hex')}`);\r\n const out = join(dir, 'out');\r\n mkdirSync(out, { recursive: true });\r\n const script = join(dir, 'probe.init.gradle');\r\n writeFileSync(script, PROBE_INIT_SCRIPT, 'utf8');\r\n const planFile = join(dir, 'plan.json');\r\n if (plan) writeFileSync(planFile, JSON.stringify(plan), 'utf8');\r\n return { dir, script, plan: planFile, out, createdGradleDir, gradleDir };\r\n}\r\n\r\n/** Removes exactly the scratch directory (and `.gradle` when this run created it and it is empty). */\r\nfunction removeScratch(scratch: Scratch): void {\r\n rmSync(scratch.dir, { recursive: true, force: true });\r\n if (scratch.createdGradleDir) {\r\n try {\r\n rmdirSync(scratch.gradleDir);\r\n } catch {\r\n // not empty (Gradle keeps its own entries there): leave it\r\n }\r\n }\r\n}\r\n\r\nfunction readDocuments<T>(out: string, mode: 'describe' | 'lookup'): T[] {\r\n if (!existsSync(out)) return [];\r\n return readdirSync(out)\r\n .filter((file) => file.startsWith(`${mode}-`) && file.endsWith('.json'))\r\n .sort()\r\n .map((file) => JSON.parse(readFileSync(join(out, file), 'utf8')) as T);\r\n}\r\n\r\nfunction runOptions(buildDir: string, rootDir: string): GradleRunOptions {\r\n return { cwd: buildDir, rootDir, timeoutMs: PROBE_TIMEOUT_MINUTES * 60_000 };\r\n}\r\n\r\n/**\r\n * Describes the Gradle build in `buildDir` and every build it includes (the\r\n * included builds and `buildSrc`): one document per build.\r\n *\r\n * @throws GradleUnavailableError / GradleCommandError / GradleVersionError\r\n */\r\nexport async function runDescribe(buildDir: string, rootDir: string): Promise<GradleBuildDocument[]> {\r\n const scratch = createScratch(buildDir);\r\n try {\r\n const rel = (file: string): string => relativeToCwd(buildDir, file);\r\n const args = [\r\n '-q',\r\n '-m',\r\n '--console=plain',\r\n '--no-configuration-cache',\r\n '-Delevate.mode=describe',\r\n `-Delevate.outDir=${rel(scratch.out)}`,\r\n '-I',\r\n rel(scratch.script),\r\n 'help',\r\n ];\r\n const options = runOptions(buildDir, rootDir);\r\n const result: RunResult = await runGradle(args, options);\r\n if (result.timedOut || result.exitCode !== 0) {\r\n throw gradleFailure(result, options, 'describing the build', 'Gradle could not describe the build', PROBE_TIMEOUT_MINUTES);\r\n }\r\n const documents = readDocuments<GradleBuildDocument>(scratch.out, 'describe');\r\n if (documents.length === 0) {\r\n throw new GradleCommandError(\r\n 'Gradle finished without describing the build, so Elevate cannot read its dependencies.',\r\n `${result.stdout}\\n${result.stderr}`.trim(),\r\n );\r\n }\r\n for (const document of documents) {\r\n if (isTooOld(document.gradleVersion)) {\r\n throw new GradleVersionError(\r\n `Gradle ${document.gradleVersion} is not supported: Elevate needs Gradle 7.6 or newer (${SUPPORTED_NOTE}).`,\r\n );\r\n }\r\n }\r\n return documents;\r\n } finally {\r\n removeScratch(scratch);\r\n }\r\n}\r\n\r\n/**\r\n * Asks the repositories of the build in `buildDir` (and its included builds)\r\n * for the versions named in `plan`: one document per build.\r\n *\r\n * @throws GradleUnavailableError / GradleCommandError\r\n */\r\nexport async function runLookup(buildDir: string, rootDir: string, plan: LookupPlan): Promise<LookupResultDocument[]> {\r\n const scratch = createScratch(buildDir, plan);\r\n try {\r\n const rel = (file: string): string => relativeToCwd(buildDir, file);\r\n const args = [\r\n '-q',\r\n '-m',\r\n '--console=plain',\r\n '--no-configuration-cache',\r\n '-Delevate.mode=lookup',\r\n `-Delevate.plan=${rel(scratch.plan)}`,\r\n `-Delevate.outDir=${rel(scratch.out)}`,\r\n '-I',\r\n rel(scratch.script),\r\n 'help',\r\n ];\r\n const options = runOptions(buildDir, rootDir);\r\n const result = await runGradle(args, options);\r\n if (result.timedOut || result.exitCode !== 0) {\r\n throw gradleFailure(\r\n result,\r\n options,\r\n 'looking up newer versions',\r\n 'Gradle could not look up newer versions',\r\n PROBE_TIMEOUT_MINUTES,\r\n );\r\n }\r\n return readDocuments<LookupDocument>(scratch.out, 'lookup').flatMap((document) => document.results);\r\n } finally {\r\n removeScratch(scratch);\r\n }\r\n}\r\n","/**\r\n * Elevate — Gradle invocation.\r\n *\r\n * Prefers the project's Gradle Wrapper (`gradlew` / `gradlew.bat`), which pins\r\n * the Gradle version the project is built with, and falls back to `gradle` on\r\n * the PATH (checked once per process). Without either, Gradle features fail\r\n * with `GradleUnavailableError` instead of silently degrading.\r\n *\r\n * `runGradle` adds no arguments of its own: callers pass the full list.\r\n */\r\n\r\nimport { existsSync, readFileSync } from 'node:fs';\r\nimport { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';\r\nimport { relativeToCwd, runCommand } from '../shared/process.js';\r\nimport type { RunResult } from '../shared/process.js';\r\n\r\nconst NOT_AVAILABLE =\r\n 'Gradle is not available: no Gradle Wrapper (gradlew) in the repository and no `gradle` on the PATH.';\r\n\r\n/** Thrown when neither a Gradle Wrapper nor a usable `gradle` is available. */\r\nexport class GradleUnavailableError extends Error {\r\n constructor(message: string = NOT_AVAILABLE) {\r\n super(message);\r\n this.name = 'GradleUnavailableError';\r\n }\r\n}\r\n\r\n/** Thrown when a Gradle invocation fails. */\r\nexport class GradleCommandError extends Error {\r\n constructor(message: string, readonly output: string) {\r\n super(message);\r\n this.name = 'GradleCommandError';\r\n }\r\n}\r\n\r\n/** Thrown when the Gradle of the project is older than the supported minimum. */\r\nexport class GradleVersionError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'GradleVersionError';\r\n }\r\n}\r\n\r\nconst IS_WINDOWS = process.platform === 'win32';\r\nconst WRAPPER = IS_WINDOWS ? 'gradlew.bat' : 'gradlew';\r\n\r\nlet gradleOnPath: Promise<void> | undefined;\r\n\r\n/** Resets the remembered `gradle --version` check (tests only). */\r\nexport function resetGradleCheck(): void {\r\n gradleOnPath = undefined;\r\n}\r\n\r\n/**\r\n * Finds the Gradle Wrapper closest to `fromDir`, searching upwards but never\r\n * above `rootDir`.\r\n */\r\nexport function findGradleWrapper(fromDir: string, rootDir: string): string | undefined {\r\n let dir = resolve(fromDir);\r\n const root = resolve(rootDir);\r\n for (;;) {\r\n const candidate = join(dir, WRAPPER);\r\n if (existsSync(candidate)) return candidate;\r\n if (dir === root || relative(root, dir).startsWith('..')) return undefined;\r\n const parent = dirname(dir);\r\n if (parent === dir) return undefined;\r\n dir = parent;\r\n }\r\n}\r\n\r\nexport interface GradleRunOptions {\r\n /** Working directory (the directory of the Gradle build); also where the wrapper lookup starts. */\r\n cwd: string;\r\n /** Repository root; the wrapper lookup does not go above it. */\r\n rootDir: string;\r\n timeoutMs?: number;\r\n}\r\n\r\n/** Drops the line every Java start prints when JAVA_TOOL_OPTIONS is set. */\r\nfunction withoutPickedUp(text: string): string {\r\n return text\r\n .split(/\\r?\\n/)\r\n .filter((line) => !line.startsWith('Picked up '))\r\n .join('\\n');\r\n}\r\n\r\nasync function checkGradleOnPath(cwd: string): Promise<void> {\r\n let result: RunResult;\r\n try {\r\n result = await runCommand('gradle', ['--version'], { cwd, timeoutMs: 30_000 });\r\n } catch {\r\n throw new GradleUnavailableError();\r\n }\r\n if (result.timedOut) {\r\n throw new GradleUnavailableError('Gradle could not be started: gradle --version timed out.');\r\n }\r\n if (result.exitCode === 127 || (result.exitCode !== 0 && !result.stderr.trim() && !result.stdout.trim())) {\r\n throw new GradleUnavailableError();\r\n }\r\n if (result.exitCode !== 0) {\r\n const detail = withoutPickedUp(result.stderr || result.stdout)\r\n .split(/\\r?\\n/)\r\n .find((line) => line.trim());\r\n throw new GradleUnavailableError(`Gradle could not be started: ${detail ?? 'gradle --version failed.'}`);\r\n }\r\n}\r\n\r\n/** Runs Gradle. Resolves with the result even for a failed build. */\r\nexport async function runGradle(args: string[], options: GradleRunOptions): Promise<RunResult> {\r\n const wrapper = findGradleWrapper(options.cwd, options.rootDir);\r\n const run = { cwd: options.cwd, timeoutMs: options.timeoutMs };\r\n\r\n if (wrapper) {\r\n // Addressed by its relative path like every other file; a wrapper in the\r\n // working directory itself needs an explicit `.` so it is not searched on the PATH.\r\n const relativeWrapper = relativeToCwd(options.cwd, wrapper);\r\n const path =\r\n isAbsolute(relativeWrapper) || relativeWrapper.includes(sep) ? relativeWrapper : `.${sep}${relativeWrapper}`;\r\n // On POSIX the wrapper may lack the executable bit after a checkout.\r\n return IS_WINDOWS ? runCommand(path, args, run) : runCommand('sh', [path, ...args], run);\r\n }\r\n\r\n gradleOnPath ??= checkGradleOnPath(options.cwd);\r\n try {\r\n await gradleOnPath;\r\n } catch (error) {\r\n // A failed check is not remembered: the user may fix the installation.\r\n gradleOnPath = undefined;\r\n throw error;\r\n }\r\n return runCommand('gradle', args, run);\r\n}\r\n\r\n/**\r\n * The details of a failed run: the standard error without the \"Picked up …\"\r\n * line, cut before the line starting with \"* Try:\", limited to the last 30\r\n * lines. When the standard error is empty the standard output is used.\r\n */\r\nexport function gradleErrors(result: Pick<RunResult, 'stdout' | 'stderr'>): string {\r\n let text = withoutPickedUp(result.stderr);\r\n if (!text.trim()) text = withoutPickedUp(result.stdout);\r\n const lines = text.split(/\\r?\\n/);\r\n const tryAt = lines.findIndex((line) => line.startsWith('* Try:'));\r\n const kept = (tryAt >= 0 ? lines.slice(0, tryAt) : lines).slice(-30);\r\n return kept.join('\\n').trim();\r\n}\r\n\r\n/**\r\n * Recognises a wrapper that failed to download Gradle and names the\r\n * `distributionUrl` of `gradle/wrapper/gradle-wrapper.properties`.\r\n */\r\nexport function wrapperDownloadMessage(\r\n result: Pick<RunResult, 'stdout' | 'stderr'>,\r\n options: Pick<GradleRunOptions, 'cwd' | 'rootDir'>,\r\n): string | undefined {\r\n const text = result.stderr;\r\n if (!/org\\.gradle\\.wrapper\\./.test(text)) return undefined;\r\n const exception = /Exception in thread \"[^\"]*\" (.+)/.exec(text)?.[1]?.trim();\r\n if (!exception) return undefined;\r\n\r\n const wrapper = findGradleWrapper(options.cwd, options.rootDir);\r\n const propertiesFile = join(dirname(wrapper ?? join(options.cwd, WRAPPER)), 'gradle', 'wrapper', 'gradle-wrapper.properties');\r\n let url = 'the distributionUrl';\r\n try {\r\n const line = readFileSync(propertiesFile, 'utf8')\r\n .split(/\\r?\\n/)\r\n .find((l) => l.startsWith('distributionUrl='));\r\n if (line) url = line.slice('distributionUrl='.length).replace(/\\\\:/g, ':').trim();\r\n } catch {\r\n // no properties file: the message names the setting only\r\n }\r\n return (\r\n `The Gradle Wrapper could not download Gradle from ${url}: ${exception}. ` +\r\n 'Check the network connection, the proxy settings and the distributionUrl in gradle/wrapper/gradle-wrapper.properties.'\r\n );\r\n}\r\n\r\n/**\r\n * Builds the error for a run that did not succeed: timeout, wrapper download\r\n * problem, or Gradle's own words.\r\n *\r\n * @param what gerund describing the run, e.g. \"describing the build\"\r\n * @param failure sentence start for a plain failure, e.g. \"Gradle could not describe the build\"\r\n */\r\nexport function gradleFailure(\r\n result: RunResult,\r\n options: GradleRunOptions,\r\n what: string,\r\n failure: string,\r\n minutes: number,\r\n): GradleCommandError {\r\n const output = `${result.stdout}\\n${result.stderr}`.trim();\r\n if (result.timedOut) {\r\n return new GradleCommandError(`Gradle timed out after ${minutes} minutes while ${what}.`, output);\r\n }\r\n const download = wrapperDownloadMessage(result, options);\r\n if (download) return new GradleCommandError(download, output);\r\n return new GradleCommandError(`${failure}:\\n${gradleErrors(result)}`, output);\r\n}\r\n","/**\r\n * Elevate — the Gradle probe init script.\r\n *\r\n * Gradle is asked, not parsed (specs/README.md, \"The probe protocol\"). The\r\n * script is Groovy and uses no API that differs between Gradle 7.6.6, 8.14.3\r\n * and 9.8.1. It is written to `.gradle/elevate-<id>/probe.init.gradle` for the\r\n * time of a run. Every Gradle build of the run writes one answer file\r\n * `<outDir>/<mode>-<h>.json`, `h` being the first ten hex digits of the SHA-1\r\n * of the build's absolute directory. Standard output carries no answer.\r\n *\r\n * Every build of the run writes below the directory of the outermost build,\r\n * because a relative path is the client's (included builds and buildSrc have a\r\n * working directory of their own).\r\n *\r\n * The text contains neither backticks nor a dollar sign followed by a brace,\r\n * so it can live in a raw template literal.\r\n */\r\nexport const PROBE_INIT_SCRIPT: string = String.raw`import groovy.json.JsonOutput\r\nimport java.security.MessageDigest\r\n\r\n// Elevate probe init script. Interface: -Delevate.mode=describe|lookup,\r\n// -Delevate.outDir=<dir>, -Delevate.plan=<file> (lookup only).\r\n\r\n// Included builds and buildSrc run this script too, with a start parameter of their own: the\r\n// directory of the client is that of the outermost build (fact 27 holds for it only).\r\ndef elevateRoot = gradle\r\nwhile (elevateRoot.parent != null) {\r\n elevateRoot = elevateRoot.parent\r\n}\r\n\r\ndef elevateProp = { String key ->\r\n def fromArgs = elevateRoot.startParameter.systemPropertiesArgs[key]\r\n return fromArgs != null ? fromArgs : System.getProperty(key)\r\n}\r\n\r\ndef elevateMode = elevateProp('elevate.mode')\r\nif (elevateMode != 'describe' && elevateMode != 'lookup') {\r\n return\r\n}\r\n\r\ndef elevateResolveFile = { String path ->\r\n def f = new File(path)\r\n return f.isAbsolute() ? f : new File(elevateRoot.startParameter.currentDir, path)\r\n}\r\n\r\ndef elevateOutDir = elevateResolveFile(elevateProp('elevate.outDir'))\r\ndef elevateBlank = { Object v ->\r\n if (v == null) return null\r\n def s = String.valueOf(v)\r\n return s.trim().isEmpty() ? null : s\r\n}\r\n\r\ndef elevateCleanUrl = { Object u ->\r\n if (u == null) return null\r\n return String.valueOf(u).replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*://)[^/@]*@', '$1')\r\n}\r\n\r\ndef elevateNormUrl = { Object u ->\r\n def c = elevateCleanUrl(u)\r\n return c == null ? null : c.replaceAll('/+$', '')\r\n}\r\n\r\ndef elevateRepoDoc = { repo ->\r\n def name = String.valueOf(repo.name)\r\n def kind = 'other'\r\n def url = null\r\n if (repo instanceof org.gradle.api.artifacts.repositories.MavenArtifactRepository) {\r\n kind = 'maven'\r\n url = repo.url\r\n } else if (repo instanceof org.gradle.api.artifacts.repositories.IvyArtifactRepository) {\r\n kind = 'ivy'\r\n url = repo.url\r\n } else if (repo instanceof org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository) {\r\n kind = 'flatDir'\r\n }\r\n if (name.startsWith('__plugin_repository__')) {\r\n kind = 'maven'\r\n url = null\r\n }\r\n return [name: name, kind: kind, url: elevateCleanUrl(url)]\r\n}\r\n\r\ndef elevateWrite = { String mode, File dir, Map doc ->\r\n dir.mkdirs()\r\n def digest = MessageDigest.getInstance('SHA-1').digest(dir.absolutePath.getBytes('UTF-8'))\r\n def hex = new StringBuilder()\r\n digest.each { b -> hex.append(String.format('%02x', b & 0xff)) }\r\n def out = new File(elevateOutDir, mode + '-' + hex.toString().substring(0, 10) + '.json')\r\n elevateOutDir.mkdirs()\r\n out.setText(JsonOutput.toJson(doc), 'UTF-8')\r\n}\r\n\r\ndef elevateExternal = { dep ->\r\n return dep instanceof org.gradle.api.artifacts.ExternalModuleDependency\r\n}\r\n\r\ndef elevateState = [:]\r\n\r\n// ---- settings-level facts (both modes) -----------------------------------\r\n\r\ngradle.settingsEvaluated { settings ->\r\n elevateState.settingsDir = settings.settingsDir.absolutePath\r\n def drm = settings.dependencyResolutionManagement\r\n try {\r\n elevateState.repositoriesMode = String.valueOf(drm.repositoriesMode.get())\r\n } catch (Throwable ignored) {\r\n elevateState.repositoriesMode = null\r\n }\r\n elevateState.settingsRepositories = drm.repositories.collect { elevateRepoDoc(it) }\r\n elevateState.pluginRepositories = settings.pluginManagement.repositories.collect { elevateRepoDoc(it) }\r\n def settingsPlugins = []\r\n try {\r\n settings.buildscript.configurations.getByName('classpath').dependencies.each { dep ->\r\n if (elevateExternal(dep) && dep.name.endsWith('.gradle.plugin')) {\r\n settingsPlugins << [id: dep.group, version: elevateBlank(dep.version)]\r\n }\r\n }\r\n } catch (Throwable ignored) {\r\n // no buildscript classpath on these settings\r\n }\r\n elevateState.settingsPlugins = settingsPlugins\r\n elevateState.settingsRepoObjects = drm.repositories\r\n}\r\n\r\n// ---- lookup mode: protect internal groups on public repositories ---------\r\n\r\ndef elevatePlan = null\r\ndef elevatePublicUrls = []\r\ndef elevateInternalPatterns = []\r\nif (elevateMode == 'lookup') {\r\n elevatePlan = new groovy.json.JsonSlurper().parse(elevateResolveFile(elevateProp('elevate.plan')))\r\n elevatePublicUrls = (elevatePlan.publicRepositoryUrls ?: []).collect { elevateNormUrl(it) }\r\n elevateInternalPatterns = elevatePlan.internalGroupPatterns ?: []\r\n}\r\n\r\ndef elevateIsPublic = { repo ->\r\n def doc = elevateRepoDoc(repo)\r\n def url = doc.url\r\n if (url == null && String.valueOf(repo.name).startsWith('__plugin_repository__')) {\r\n def pluginName = String.valueOf(repo.name).substring('__plugin_repository__'.length())\r\n url = (elevateState.pluginRepoUrlByName ?: [:])[pluginName]\r\n }\r\n return url != null && elevatePublicUrls.contains(elevateNormUrl(url))\r\n}\r\n\r\ndef elevateProtect = { repos ->\r\n repos.each { repo ->\r\n if (!elevateIsPublic(repo)) return\r\n elevateInternalPatterns.each { pattern ->\r\n try {\r\n repo.content { descriptor -> descriptor.excludeGroupByRegex(pattern) }\r\n } catch (Throwable ignored) {\r\n // a repository kind without content filters cannot be protected\r\n }\r\n }\r\n }\r\n}\r\n\r\nif (elevateMode == 'lookup') {\r\n gradle.settingsEvaluated { settings ->\r\n def byName = [:]\r\n settings.pluginManagement.repositories.each { r ->\r\n def d = elevateRepoDoc(r)\r\n byName[d.name] = d.url\r\n }\r\n elevateState.pluginRepoUrlByName = byName\r\n elevateProtect(settings.dependencyResolutionManagement.repositories)\r\n }\r\n}\r\n\r\n// ---- describe -------------------------------------------------------------\r\n\r\ndef elevateDescribeProject = { Project p ->\r\n def dependencies = []\r\n def constraints = []\r\n def projectDependencies = []\r\n p.configurations.each { cfg ->\r\n cfg.dependencies.each { dep ->\r\n if (dep instanceof org.gradle.api.artifacts.ProjectDependency) {\r\n def path\r\n try {\r\n path = dep.path\r\n } catch (MissingPropertyException ignored) {\r\n path = dep.dependencyProject.path\r\n }\r\n projectDependencies << [configuration: cfg.name, path: path]\r\n } else if (elevateExternal(dep)) {\r\n def vc = dep.versionConstraint\r\n def category = null\r\n try {\r\n def attr = dep.attributes.getAttribute(org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE)\r\n def n = attr == null ? null : String.valueOf(attr.name)\r\n if (n == 'platform' || n == 'enforced-platform') category = n\r\n } catch (Throwable ignored) {\r\n category = null\r\n }\r\n def artifact = dep.artifacts.isEmpty() ? null : dep.artifacts.iterator().next()\r\n dependencies << [\r\n configuration: cfg.name,\r\n group : elevateBlank(dep.group),\r\n name : dep.name,\r\n version : elevateBlank(dep.version),\r\n strictly : elevateBlank(vc.strictVersion),\r\n preferred : elevateBlank(vc.preferredVersion),\r\n rejected : vc.rejectedVersions.collect { String.valueOf(it) },\r\n category : category,\r\n fromCatalog : dep instanceof org.gradle.api.artifacts.MinimalExternalModuleDependency,\r\n classifier : artifact == null ? null : elevateBlank(artifact.classifier),\r\n extension : artifact == null ? null : elevateBlank(artifact.extension),\r\n ]\r\n }\r\n }\r\n cfg.dependencyConstraints.each { c ->\r\n constraints << [\r\n configuration: cfg.name,\r\n group : elevateBlank(c.group),\r\n name : c.name,\r\n version : elevateBlank(c.version),\r\n strictly : elevateBlank(c.versionConstraint.strictVersion),\r\n ]\r\n }\r\n }\r\n def buildscriptDependencies = []\r\n try {\r\n p.buildscript.configurations.getByName('classpath').dependencies.each { dep ->\r\n if (elevateExternal(dep)) {\r\n buildscriptDependencies << [group: elevateBlank(dep.group), name: dep.name, version: elevateBlank(dep.version)]\r\n }\r\n }\r\n } catch (Throwable ignored) {\r\n // no buildscript classpath\r\n }\r\n def buildFile = p.buildFile != null && p.buildFile.exists() ? p.buildFile.absolutePath : null\r\n return [\r\n path : p.path,\r\n name : p.name,\r\n dir : p.projectDir.absolutePath,\r\n buildFile : buildFile,\r\n group : elevateBlank(p.group),\r\n version : elevateBlank(p.version),\r\n repositories : p.repositories.collect { elevateRepoDoc(it) },\r\n buildscriptRepositories: p.buildscript.repositories.collect { elevateRepoDoc(it) },\r\n dependencies : dependencies,\r\n constraints : constraints,\r\n projectDependencies : projectDependencies,\r\n buildscriptDependencies: buildscriptDependencies,\r\n tasks : ['testClasses', 'assemble'].findAll { p.tasks.names.contains(it) },\r\n lockfile : new File(p.projectDir, 'gradle.lockfile').exists(),\r\n ]\r\n}\r\n\r\nif (elevateMode == 'describe') {\r\n gradle.projectsEvaluated { g ->\r\n def root = g.rootProject\r\n def dir = elevateState.settingsDir != null ? elevateState.settingsDir : root.projectDir.absolutePath\r\n def kind = g.parent == null ? 'root' : (root.name == 'buildSrc' && root.projectDir.name == 'buildSrc' ? 'buildSrc' : 'included')\r\n def all = root.allprojects.toList().sort { a, b ->\r\n a.path == ':' ? -1 : (b.path == ':' ? 1 : a.path <=> b.path)\r\n }\r\n def doc = [\r\n protocol : 1,\r\n mode : 'describe',\r\n gradleVersion: String.valueOf(g.gradleVersion),\r\n build : [\r\n name : root.name,\r\n kind : kind,\r\n dir : dir,\r\n repositoriesMode : elevateState.repositoriesMode,\r\n settingsRepositories: elevateState.settingsRepositories ?: [],\r\n pluginRepositories : elevateState.pluginRepositories ?: [],\r\n settingsPlugins : elevateState.settingsPlugins ?: [],\r\n ],\r\n projects : all.collect { elevateDescribeProject(it) },\r\n ]\r\n elevateWrite('describe', new File(dir), doc)\r\n }\r\n}\r\n\r\n// ---- lookup ---------------------------------------------------------------\r\n\r\ndef elevateMessageLine = { Throwable t ->\r\n def m = t.message\r\n if (m == null || m.trim().isEmpty()) return t.class.simpleName\r\n return m.readLines().find { !it.trim().isEmpty() }?.trim() ?: t.class.simpleName\r\n}\r\n\r\ndef elevateHasNotFound\r\nelevateHasNotFound = { Throwable t, Set seen ->\r\n if (t == null || !seen.add(System.identityHashCode(t))) return false\r\n if (t.class.name.endsWith('ModuleVersionNotFoundException')) return true\r\n if (elevateHasNotFound(t.cause, seen)) return true\r\n try {\r\n def many = t.causes\r\n if (many != null) {\r\n for (c in many) {\r\n if (elevateHasNotFound(c, seen)) return true\r\n }\r\n }\r\n } catch (MissingPropertyException ignored) {\r\n // not a multi-cause exception\r\n }\r\n return false\r\n}\r\n\r\ndef elevateFailureText = { Throwable t ->\r\n def start = t\r\n try {\r\n def many = t.causes\r\n if (many != null && !many.isEmpty()) start = many.iterator().next()\r\n } catch (MissingPropertyException ignored) {\r\n start = t\r\n }\r\n def parts = []\r\n def cur = start\r\n int guard = 0\r\n while (cur != null && guard++ < 20) {\r\n parts << elevateMessageLine(cur)\r\n cur = cur.cause\r\n }\r\n return parts.join(' > ')\r\n}\r\n\r\ndef elevateLookupOne = { Project p, Map l ->\r\n def versions = []\r\n def error = null\r\n def isPlugin = l.kind == 'plugin'\r\n def handler = isPlugin ? p.buildscript : p\r\n def restore = null\r\n if (isPlugin && elevateInternalPatterns.any { pattern -> String.valueOf(l.group).matches(pattern) }) {\r\n def repos = p.buildscript.repositories\r\n def original = new ArrayList(repos)\r\n def publics = original.findAll { elevateIsPublic(it) }\r\n repos.removeAll(publics)\r\n restore = {\r\n repos.clear()\r\n repos.addAll(original)\r\n }\r\n }\r\n try {\r\n def dep = handler.dependencies.create(l.group + ':' + l.name + ':+')\r\n def conf = handler.configurations.detachedConfiguration(dep)\r\n conf.resolutionStrategy.cacheDynamicVersionsFor(0, 'seconds')\r\n conf.resolutionStrategy.componentSelection.all { sel ->\r\n versions << String.valueOf(sel.candidate.version)\r\n sel.reject('elevate lookup')\r\n }\r\n conf.resolve()\r\n } catch (Throwable t) {\r\n error = elevateHasNotFound(t, new HashSet()) ? null : elevateFailureText(t)\r\n } finally {\r\n if (restore != null) restore()\r\n }\r\n return [id: l.id, versions: versions, error: error]\r\n}\r\n\r\nif (elevateMode == 'lookup') {\r\n gradle.projectsEvaluated { g ->\r\n def root = g.rootProject\r\n def dir = elevateState.settingsDir != null ? elevateState.settingsDir : root.projectDir.absolutePath\r\n root.allprojects.each { p -> elevateProtect(p.repositories) }\r\n def results = []\r\n def mine = (elevatePlan.lookups ?: []).findAll { it.buildRoot == dir }\r\n root.allprojects { Project p ->\r\n mine.findAll { it.project == p.path }.each { l ->\r\n results << elevateLookupOne(p, l)\r\n }\r\n }\r\n elevateWrite('lookup', new File(dir), [protocol: 1, mode: 'lookup', results: results])\r\n }\r\n}\r\n`;\r\n","/**\r\n * Elevate — Gradle registry adapter for ad-hoc version queries\r\n * (`elevate versions`, MCP `elevate_get_versions`, the version picker).\r\n *\r\n * Like the scanner it asks Gradle instead of a fixed repository URL: a lookup\r\n * run of the build in the repository root lists the versions through the\r\n * repositories, mirrors and credentials of that build, so any Nexus or\r\n * Artifactory works without Elevate-specific configuration (specs/24,\r\n * \"Single lookups use the same machinery\").\r\n */\r\n\r\nimport { resolve } from 'node:path';\r\nimport type { RegistryEndpoint, RegistryPort } from '../../domain/ports.js';\r\nimport type { DependencyCoordinate, ReleaseChannel } from '../../domain/models.js';\r\nimport { isPreReleaseVersion } from '../../domain/versions.js';\r\nimport { findGradleBuildDirs } from './gradle-discovery.js';\r\nimport { runDescribe, runLookup } from './gradle-probe.js';\r\nimport type { GradleBuildDocument, GradleProjectDocument, GradleRepositoryDocument } from './gradle-probe.js';\r\nimport {\r\n buildLookupPlan,\r\n effectiveRepositories,\r\n isPublicRepositoryUrl,\r\n lookupFailureDetail,\r\n stripCredentials,\r\n} from './gradle-repositories.js';\r\nimport { sortGradleVersions } from './gradle-versions.js';\r\n\r\n/** A plugin id has no colon: `elevate versions org.example.plugin`. */\r\nfunction isPluginId(coordinate: DependencyCoordinate): boolean {\r\n return !coordinate.identifier.includes(':');\r\n}\r\n\r\ninterface RootBuild {\r\n /** The directory Gradle runs in. */\r\n dir: string;\r\n build: GradleBuildDocument['build'];\r\n /** The root project of the build, whose repositories decide. */\r\n project: GradleProjectDocument;\r\n}\r\n\r\n/**\r\n * The build that answers a single lookup: the one in the repository root, or\r\n * the first Gradle build of the repository when the root has none.\r\n */\r\nasync function describeRootBuild(rootDir: string): Promise<RootBuild> {\r\n const root = resolve(rootDir);\r\n const dirs = findGradleBuildDirs(root);\r\n const dir = dirs.includes(root) ? root : dirs[0];\r\n if (!dir) throw new Error(`No Gradle build found in ${root}.`);\r\n const documents = await runDescribe(dir, root);\r\n const document = documents.find((doc) => resolve(doc.build.dir) === resolve(dir)) ?? documents[0]!;\r\n return { dir, build: document.build, project: document.projects[0]! };\r\n}\r\n\r\n/** The internal scopes of the repository, read when a lookup needs them (the config module imports the adapters). */\r\nasync function internalScopesOf(rootDir: string): Promise<readonly string[]> {\r\n const { loadConfig } = await import('../../config.js');\r\n return loadConfig(rootDir).internalScopes;\r\n}\r\n\r\nfunction describeRepository(repository: GradleRepositoryDocument): string {\r\n return stripCredentials(repository.url ?? repository.name);\r\n}\r\n\r\nexport class GradleRegistryAdapter implements RegistryPort {\r\n /**\r\n * Where a lookup would go: the first repository of the build that is not a\r\n * well-known public one, otherwise the first public one. An internal package\r\n * is refused when only public repositories would be asked.\r\n */\r\n async resolveEndpoint(coordinate: DependencyCoordinate, cwd: string): Promise<RegistryEndpoint> {\r\n const { build, project } = await describeRootBuild(cwd);\r\n const repositories = effectiveRepositories(build, project, isPluginId(coordinate) ? 'plugin' : 'module');\r\n const privateRepository = repositories.find((r) => !isPublicRepositoryUrl(r.url));\r\n if (privateRepository) return { url: describeRepository(privateRepository), isPublic: false };\r\n const first = repositories[0];\r\n return first\r\n ? { url: describeRepository(first), isPublic: true }\r\n : { url: `no repository declared for ${project.path}`, isPublic: false };\r\n }\r\n\r\n async getLatestVersion(\r\n coordinate: DependencyCoordinate,\r\n channel: ReleaseChannel = 'stable',\r\n cwd = process.cwd(),\r\n ): Promise<string | null> {\r\n const versions = await this.getAllVersions(coordinate, cwd);\r\n return versions.find((v) => channel === 'all' || !isPreReleaseVersion(v)) ?? null;\r\n }\r\n\r\n /**\r\n * All versions available in the repositories of the build, newest first.\r\n * Throws when Gradle fails or a repository could not be read, so an error is\r\n * never mistaken for \"no versions\".\r\n */\r\n async getAllVersions(coordinate: DependencyCoordinate, cwd = process.cwd()): Promise<string[]> {\r\n if (!coordinate.group || !coordinate.artifact) return [];\r\n const plugin = isPluginId(coordinate);\r\n\r\n const { dir, build, project } = await describeRootBuild(cwd);\r\n const kind = plugin ? 'plugin' : 'module';\r\n const repositories = effectiveRepositories(build, project, kind);\r\n if (repositories.length === 0) throw new Error(`the build declares no repository for ${project.path}`);\r\n\r\n const { plan } = buildLookupPlan(\r\n [\r\n {\r\n buildRoot: build.dir,\r\n project: project.path,\r\n kind,\r\n group: coordinate.group,\r\n name: plugin ? `${coordinate.group}.gradle.plugin` : coordinate.artifact,\r\n repositories,\r\n },\r\n ],\r\n await internalScopesOf(cwd),\r\n );\r\n const [answer] = await runLookup(dir, resolve(cwd), plan);\r\n if (!answer) throw new Error('Gradle gave no answer for this lookup.');\r\n if (answer.error !== null) throw new Error(lookupFailureDetail(answer.error, undefined).text);\r\n return sortGradleVersions(answer.versions);\r\n }\r\n}\r\n","/**\r\n * Elevate — the repositories Gradle would use, and the lookup plan.\r\n *\r\n * Elevate never contacts a repository itself: it tells Gradle what to look up\r\n * (`LookupPlan`) and Gradle asks the repositories of the build with its own\r\n * mirrors, credentials and proxies. What Elevate decides is which repositories\r\n * apply to a project (`effectiveRepositories`), which of them are public\r\n * (`isPublicRepositoryUrl`) and which groups are internal, so that the init\r\n * script can keep them away from the public ones (specs/24, GRDVER-14 to 24).\r\n */\r\n\r\nimport type {\r\n GradleBuildDocument,\r\n GradleProjectDocument,\r\n GradleRepositoryDocument,\r\n LookupPlan,\r\n LookupPlanEntry,\r\n} from './gradle-probe.js';\r\n\r\nconst PLUGIN_REPOSITORY_PREFIX = '__plugin_repository__';\r\n\r\n/** The repository Gradle uses for plugins when the build declares none. */\r\nexport const PLUGIN_PORTAL: GradleRepositoryDocument = {\r\n name: 'Gradle Central Plugin Repository',\r\n kind: 'maven',\r\n url: 'https://plugins.gradle.org/m2',\r\n};\r\n\r\n/** Hosts that serve everybody: a company's Artifactory or Nexus is private even when it mirrors Maven Central. */\r\nconst PUBLIC_HOSTS = new Set([\r\n 'repo.maven.apache.org',\r\n 'repo1.maven.org',\r\n 'central.sonatype.com',\r\n 'plugins.gradle.org',\r\n 'dl.google.com',\r\n 'maven.google.com',\r\n 'jcenter.bintray.com',\r\n 'jitpack.io',\r\n 'oss.sonatype.org',\r\n 's01.oss.sonatype.org',\r\n 'repo.spring.io',\r\n]);\r\n\r\n/** Strips `user:password@` and trailing slashes: credentials never leave the scan. */\r\nexport function normalizeRepositoryUrl(url: string): string {\r\n return stripCredentials(url).replace(/\\/+$/, '');\r\n}\r\n\r\n/** Removes `user:password@` from a URL, or from every URL in a text. */\r\nexport function stripCredentials(text: string): string {\r\n return text.replace(/([a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/)[^/@\\s'\"]*@/g, '$1');\r\n}\r\n\r\n/** Whether the repository is a well-known public one. No URL, `file:` and any other host are private. */\r\nexport function isPublicRepositoryUrl(url: string | null): boolean {\r\n if (!url) return false;\r\n try {\r\n return PUBLIC_HOSTS.has(new URL(stripCredentials(url)).hostname.toLowerCase());\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * The repositories that decide a lookup for `project`.\r\n *\r\n * Modules follow the `repositoriesMode` of the settings (fact 23). Plugins\r\n * follow the project's `buildscript`: the wrappers Gradle reports for the\r\n * plugin management are mapped to the repositories of the settings; without\r\n * any repository the Gradle Plugin Portal applies.\r\n */\r\nexport function effectiveRepositories(\r\n build: GradleBuildDocument['build'],\r\n project: GradleProjectDocument,\r\n kind: 'module' | 'plugin',\r\n): GradleRepositoryDocument[] {\r\n if (kind === 'module') {\r\n const mode = build.repositoriesMode ?? 'PREFER_PROJECT';\r\n if (mode === 'PREFER_PROJECT') {\r\n return project.repositories.length > 0 ? project.repositories : build.settingsRepositories;\r\n }\r\n return build.settingsRepositories;\r\n }\r\n\r\n const mapped: GradleRepositoryDocument[] = [];\r\n for (const repository of project.buildscriptRepositories) {\r\n if (repository.name.startsWith(PLUGIN_REPOSITORY_PREFIX)) {\r\n const name = repository.name.slice(PLUGIN_REPOSITORY_PREFIX.length);\r\n const declared = build.pluginRepositories.find((candidate) => candidate.name === name);\r\n if (declared) mapped.push(declared);\r\n } else {\r\n mapped.push(repository);\r\n }\r\n }\r\n return mapped.length > 0 ? mapped : [PLUGIN_PORTAL];\r\n}\r\n\r\n/**\r\n * One regular expression per internal scope: the escaped scope followed by\r\n * `(\\..*)?`. A scope is cleaned like `matchesInternalScope` does it: a leading\r\n * `@` and trailing `.`, `:` and `/` go; what is left empty gives no pattern.\r\n */\r\nexport function internalGroupPatterns(internalScopes: readonly string[]): string[] {\r\n const patterns = new Set<string>();\r\n for (const scope of internalScopes) {\r\n const prefix = scope.replace(/^@/, '').replace(/[.:/]+$/, '');\r\n if (prefix.length === 0) continue;\r\n patterns.add(`${prefix.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}(\\\\..*)?`);\r\n }\r\n return [...patterns];\r\n}\r\n\r\nconst EARLIER_ERROR = /^Repository .* is disabled due to earlier error below:?$|^Skipped due to earlier error$/;\r\n\r\n/**\r\n * The detail Elevate shows for a failed lookup: the last message of Gradle's\r\n * chain (`Could not resolve … > … > Could not GET '…'. Received status code\r\n * 401`), without credentials. Once a repository has failed Gradle disables it,\r\n * and the lookups that follow fail with a note about the earlier error; their\r\n * detail is the one of the first failed lookup of the run, so the user sees the\r\n * cause and not the note.\r\n *\r\n * `isCause` is false for such a note.\r\n */\r\nexport function lookupFailureDetail(\r\n error: string,\r\n firstFailure: string | undefined,\r\n): { text: string; isCause: boolean } {\r\n const parts = stripCredentials(error).split(' > ');\r\n const last = parts[parts.length - 1] ?? error;\r\n if (EARLIER_ERROR.test(last)) return { text: firstFailure ?? last, isCause: false };\r\n return { text: last, isCause: true };\r\n}\r\n\r\n/** One coordinate a project wants to look up, with the repositories that decide it. */\r\nexport interface LookupRequest {\r\n /** `build.dir` of the build the project belongs to. */\r\n buildRoot: string;\r\n /** Gradle path of the project. */\r\n project: string;\r\n kind: 'module' | 'plugin';\r\n group: string;\r\n name: string;\r\n /** The effective repositories of the project for this kind of lookup. */\r\n repositories: readonly GradleRepositoryDocument[];\r\n}\r\n\r\nexport interface BuiltPlan {\r\n plan: LookupPlan;\r\n /** The id of the plan entry that answers a request (several requests can share one). */\r\n idOf(request: LookupRequest): string;\r\n}\r\n\r\n/** Requests of projects with the same repositories ask the same question. */\r\nfunction lookupKey(request: LookupRequest): string {\r\n const repositories = request.repositories.map((r) => `${r.name}=${r.url === null ? '' : normalizeRepositoryUrl(r.url)}`);\r\n return JSON.stringify([request.buildRoot, request.kind, request.group, request.name, repositories]);\r\n}\r\n\r\n/**\r\n * Builds the plan of a lookup run. A coordinate that several projects ask with\r\n * the same repositories is written once, under the first project (GRDVER-35);\r\n * projects with different repositories look it up separately (GRDVER-36).\r\n */\r\nexport function buildLookupPlan(requests: readonly LookupRequest[], internalScopes: readonly string[]): BuiltPlan {\r\n const lookups: LookupPlanEntry[] = [];\r\n const idByKey = new Map<string, string>();\r\n const publicUrls = new Set<string>();\r\n\r\n for (const request of requests) {\r\n for (const repository of request.repositories) {\r\n if (repository.url !== null && isPublicRepositoryUrl(repository.url)) {\r\n publicUrls.add(normalizeRepositoryUrl(repository.url));\r\n }\r\n }\r\n const key = lookupKey(request);\r\n if (idByKey.has(key)) continue;\r\n const id = `L${lookups.length + 1}`;\r\n idByKey.set(key, id);\r\n lookups.push({\r\n id,\r\n buildRoot: request.buildRoot,\r\n project: request.project,\r\n kind: request.kind,\r\n group: request.group,\r\n name: request.name,\r\n });\r\n }\r\n\r\n return {\r\n plan: {\r\n protocol: 1,\r\n publicRepositoryUrls: [...publicUrls],\r\n internalGroupPatterns: internalGroupPatterns(internalScopes),\r\n lookups,\r\n },\r\n idOf: (request) => idByKey.get(lookupKey(request)) ?? '',\r\n };\r\n}\r\n","/**\r\n * Elevate — Gradle's version order.\r\n *\r\n * Gradle compares versions part by part, not as SemVer (specs/24, GRDVER-01 to\r\n * GRDVER-04; checked against Gradle itself with 24 919 pairs of strings):\r\n *\r\n * 1. A version is split into parts at \".\", \"-\", \"_\" and \"+\" and wherever an\r\n * ASCII digit meets a non-digit. A separator closes the part before it\r\n * (also an empty one); the end of the string closes a part only when it\r\n * is not empty, so \"1.\" has the parts of \"1\".\r\n * 2. The parts are compared from the left until one version has none left.\r\n * Equal parts are skipped.\r\n * 3. A numeric part is greater than a non-numeric one. Two numeric parts\r\n * compare as numbers; a number above 9223372036854775807 is a string.\r\n * 4. Two strings: two special words (dev < rc < snapshot < final < ga <\r\n * release < sp, ignoring case) end the comparison with their order. A\r\n * special word other than \"dev\" is greater than any other string, \"dev\" is\r\n * smaller than any other string. Two other strings compare as text,\r\n * uppercase before lowercase.\r\n * 5. If one version has parts left over: when the first of them is numeric\r\n * the longer version is greater, otherwise it is smaller.\r\n *\r\n * Some different versions are equal (\"1.0-1\" and \"1.0.1\"); the order of such\r\n * versions is the order in which they were reported.\r\n */\r\n\r\nconst MAX_LONG = 9223372036854775807n;\r\nconst SPECIAL = ['dev', 'rc', 'snapshot', 'final', 'ga', 'release', 'sp'];\r\n\r\ninterface Part {\r\n text: string;\r\n /** The value of a numeric part; `undefined` for a string. */\r\n value: bigint | undefined;\r\n}\r\n\r\nfunction isDigit(code: number): boolean {\r\n return code >= 48 && code <= 57;\r\n}\r\n\r\nfunction makePart(text: string): Part {\r\n let value: bigint | undefined;\r\n if (text.length > 0 && [...text].every((ch) => isDigit(ch.charCodeAt(0)))) {\r\n const number = BigInt(text);\r\n if (text.length <= 18 || number <= MAX_LONG) value = number;\r\n }\r\n return { text, value };\r\n}\r\n\r\nfunction splitVersion(version: string): Part[] {\r\n const parts: Part[] = [];\r\n let start = 0;\r\n for (let i = 0; i < version.length; i++) {\r\n const ch = version[i]!;\r\n if (ch === '.' || ch === '-' || ch === '_' || ch === '+') {\r\n parts.push(makePart(version.slice(start, i)));\r\n start = i + 1;\r\n } else if (i > start && isDigit(ch.charCodeAt(0)) !== isDigit(version.charCodeAt(i - 1))) {\r\n parts.push(makePart(version.slice(start, i)));\r\n start = i;\r\n }\r\n }\r\n if (start < version.length) parts.push(makePart(version.slice(start)));\r\n return parts;\r\n}\r\n\r\nfunction specialRank(text: string): number | undefined {\r\n const rank = SPECIAL.indexOf(text.toLowerCase());\r\n return rank === -1 ? undefined : rank;\r\n}\r\n\r\n/** Compares two parts: a number, or `undefined` when equal and the comparison goes on. */\r\nfunction compareParts(a: Part, b: Part): number | undefined {\r\n if (a.text === b.text) return undefined;\r\n if (a.value !== undefined && b.value !== undefined) {\r\n return a.value === b.value ? undefined : a.value > b.value ? 1 : -1;\r\n }\r\n if (a.value !== undefined) return 1;\r\n if (b.value !== undefined) return -1;\r\n\r\n const rankA = specialRank(a.text);\r\n const rankB = specialRank(b.text);\r\n if (rankA !== undefined && rankB !== undefined) return Math.sign(rankA - rankB);\r\n if (rankA !== undefined) return rankA === 0 ? -1 : 1;\r\n if (rankB !== undefined) return rankB === 0 ? 1 : -1;\r\n return a.text < b.text ? -1 : a.text > b.text ? 1 : undefined;\r\n}\r\n\r\n/** Positive when `a` is newer than `b`, negative when older, 0 when Gradle sees no difference. */\r\nexport function compareGradleVersions(a: string, b: string): number {\r\n const partsA = splitVersion(a);\r\n const partsB = splitVersion(b);\r\n const common = Math.min(partsA.length, partsB.length);\r\n for (let i = 0; i < common; i++) {\r\n const result = compareParts(partsA[i]!, partsB[i]!);\r\n if (result !== undefined) return result;\r\n }\r\n if (partsA.length === partsB.length) return 0;\r\n const longerIsA = partsA.length > partsB.length;\r\n const leftover = (longerIsA ? partsA : partsB)[common]!;\r\n const longerWins = leftover.value !== undefined;\r\n return longerIsA === longerWins ? 1 : -1;\r\n}\r\n\r\n/** Whether `candidate` is strictly newer than `current`. */\r\nexport function isNewerGradleVersion(candidate: string, current: string): boolean {\r\n return compareGradleVersions(candidate, current) > 0;\r\n}\r\n\r\n/**\r\n * Sorts versions newest first without duplicates. Versions that compare equal\r\n * keep the order in which they were given.\r\n */\r\nexport function sortGradleVersions(versions: readonly string[]): string[] {\r\n return [...new Set(versions)]\r\n .map((version, index) => ({ version, index }))\r\n .sort((x, y) => compareGradleVersions(y.version, x.version) || x.index - y.index)\r\n .map((entry) => entry.version);\r\n}\r\n","/**\r\n * Elevate — Gradle dependency scanner.\r\n *\r\n * For each requested module:\r\n * 1. Gradle describes the build: the dependencies a project declares with the\r\n * version each has after every script has run (one describe run per build\r\n * directory, however many modules are requested).\r\n * 2. A dependency is not a subject when it has no version, is a project or a\r\n * file dependency, or is substituted by a project of an included build\r\n * (that one is aligned to the project's version). What carries a selector\r\n * or a constraint, or whose version text cannot be located with certainty,\r\n * is listed as not offered with the reason.\r\n * 3. Everything else is looked up through the repositories of the build with\r\n * one lookup run per build directory. Elevate never contacts a repository\r\n * itself, and an internal package is never asked of a public one.\r\n *\r\n * Specs 16 (what is offered and where the version is written) and 17 (the\r\n * versions, the repositories and the guard).\r\n */\r\n\r\nimport { existsSync, readFileSync, realpathSync } from 'node:fs';\r\nimport { relative, resolve } from 'node:path';\r\nimport semver from 'semver';\r\nimport type { DependencyReaderPort, ScanContext } from '../../domain/ports.js';\r\nimport type {\r\n DependencyOrigin,\r\n DependencyOriginKind,\r\n ProjectModule,\r\n ReleaseChannel,\r\n ScanResult,\r\n SkippedDependency,\r\n UpdateCandidate,\r\n} from '../../domain/models.js';\r\nimport { classifyOrigin } from '../../domain/origin.js';\r\nimport { cleanJavaVersion, diffVersions, extractPreReleaseTag, isPreReleaseVersion } from '../../domain/versions.js';\r\nimport { gradleModuleId } from './gradle-discovery.js';\r\nimport { assessDependency, isTestConfiguration, locateDeclarations } from './gradle-locator.js';\r\nimport type { LocatedDeclaration } from './gradle-locator.js';\r\nimport { runDescribe, runLookup } from './gradle-probe.js';\r\nimport type { GradleBuildDocument, GradleProjectDocument, LookupResultDocument } from './gradle-probe.js';\r\nimport {\r\n buildLookupPlan,\r\n effectiveRepositories,\r\n isPublicRepositoryUrl,\r\n lookupFailureDetail,\r\n stripCredentials,\r\n} from './gradle-repositories.js';\r\nimport type { BuiltPlan, LookupRequest } from './gradle-repositories.js';\r\nimport { isNewerGradleVersion, sortGradleVersions } from './gradle-versions.js';\r\n\r\nconst DIFF_ORDER: Record<string, number> = { major: 0, minor: 1, patch: 2 };\r\nconst SCOPE_ORDER: Record<UpdateCandidate['scope'], number> = { prod: 0, test: 1, dev: 1, plugin: 2 };\r\n\r\n/** One declaration Gradle reports for a coordinate. */\r\ninterface Entry {\r\n group: string | null;\r\n name: string;\r\n version: string | null;\r\n strictly: string | null;\r\n preferred: string | null;\r\n rejected: readonly string[];\r\n scope: UpdateCandidate['scope'];\r\n fromCatalog: boolean;\r\n isConstraint: boolean;\r\n isPlugin: boolean;\r\n}\r\n\r\n/** A coordinate the module declares, with everything needed to look it up. */\r\ninterface Subject {\r\n identifier: string;\r\n group: string;\r\n name: string;\r\n version: string;\r\n scope: UpdateCandidate['scope'];\r\n isPlugin: boolean;\r\n declarations: LocatedDeclaration[];\r\n}\r\n\r\ninterface LookupItem {\r\n subject: Subject;\r\n origin: DependencyOrigin;\r\n request: LookupRequest;\r\n}\r\n\r\n/** A module whose dependencies are known but not yet looked up. */\r\ninterface ModulePlan {\r\n module: ProjectModule;\r\n candidates: UpdateCandidate[];\r\n skipped: SkippedDependency[];\r\n lookups: LookupItem[];\r\n}\r\n\r\nexport class GradleDependencyAdapter implements DependencyReaderPort {\r\n async scan(module: ProjectModule, context: ScanContext): Promise<ScanResult> {\r\n const results = await this.scanMany([module], context);\r\n return results.get(module) ?? { candidates: [], skipped: [] };\r\n }\r\n\r\n /**\r\n * Modules of one Gradle build directory share one describe run and one\r\n * lookup run: Gradle starts slowly, so the runs are not repeated per module.\r\n */\r\n async scanMany(modules: readonly ProjectModule[], context: ScanContext): Promise<Map<ProjectModule, ScanResult>> {\r\n const groups = new Map<string, ProjectModule[]>();\r\n for (const module of modules) {\r\n const dir = module.buildDir ?? module.path;\r\n groups.set(dir, [...(groups.get(dir) ?? []), module]);\r\n }\r\n\r\n const results = new Map<ProjectModule, ScanResult>();\r\n for (const [dir, members] of groups) {\r\n for (const [module, result] of await scanGroup(dir, members, context)) results.set(module, result);\r\n }\r\n return results;\r\n }\r\n}\r\n\r\nasync function scanGroup(\r\n dir: string,\r\n modules: readonly ProjectModule[],\r\n context: ScanContext,\r\n): Promise<Map<ProjectModule, ScanResult>> {\r\n const documents = await runDescribe(dir, context.rootDir);\r\n const files = new FileReader();\r\n\r\n const plans: ModulePlan[] = [];\r\n for (const module of modules) {\r\n const build = documents.find((doc) => sameDir(doc.build.dir, module.buildRoot ?? dir));\r\n const project = build?.projects.find((p) => sameDir(p.dir, module.path));\r\n if (!build || !project) {\r\n plans.push({ module, candidates: [], skipped: [], lookups: [] });\r\n continue;\r\n }\r\n plans.push(planModule(module, build, project, documents, context, files));\r\n }\r\n\r\n const requests = plans.flatMap((plan) => plan.lookups.map((item) => item.request));\r\n let built: BuiltPlan | undefined;\r\n let results: LookupResultDocument[] = [];\r\n if (requests.length > 0) {\r\n built = buildLookupPlan(requests, context.internalScopes);\r\n results = await runLookup(dir, context.rootDir, built.plan);\r\n }\r\n\r\n const answers = new Answers(results);\r\n return new Map(plans.map((plan) => [plan.module, finishModule(plan, built, answers, context.channel)]));\r\n}\r\n\r\nclass FileReader {\r\n private readonly cache = new Map<string, string | undefined>();\r\n read = (file: string): string | undefined => {\r\n if (!this.cache.has(file)) this.cache.set(file, existsSync(file) ? readFileSync(file, 'utf8') : undefined);\r\n return this.cache.get(file);\r\n };\r\n}\r\n\r\nfunction canonical(dir: string): string {\r\n try {\r\n return realpathSync(dir);\r\n } catch {\r\n return resolve(dir);\r\n }\r\n}\r\n\r\nfunction sameDir(a: string, b: string): boolean {\r\n return canonical(a) === canonical(b);\r\n}\r\n\r\nfunction isOutside(rootDir: string, dir: string): boolean {\r\n const path = relative(canonical(rootDir), canonical(dir));\r\n return path.startsWith('..') || resolve(path) === path;\r\n}\r\n\r\n// ---- planning -------------------------------------------------------------------------\r\n\r\n/** The declarations Gradle reports for the project, grouped by coordinate. */\r\nfunction entriesOf(project: GradleProjectDocument): Map<string, Entry[]> {\r\n const groups = new Map<string, Entry[]>();\r\n const add = (key: string, entry: Entry): void => {\r\n groups.set(key, [...(groups.get(key) ?? []), entry]);\r\n };\r\n const keyOf = (entry: Entry): string =>\r\n entry.isPlugin ? `plugin:${entry.group}` : `${entry.group ?? ''}:${entry.name}`;\r\n\r\n for (const dep of project.dependencies) {\r\n const entry: Entry = {\r\n group: dep.group,\r\n name: dep.name,\r\n version: dep.version,\r\n strictly: dep.strictly,\r\n preferred: dep.preferred,\r\n rejected: dep.rejected,\r\n scope: isTestConfiguration(dep.configuration) ? 'test' : 'prod',\r\n fromCatalog: dep.fromCatalog,\r\n isConstraint: false,\r\n isPlugin: false,\r\n };\r\n add(keyOf(entry), entry);\r\n }\r\n for (const constraint of project.constraints) {\r\n const entry: Entry = {\r\n group: constraint.group,\r\n name: constraint.name,\r\n version: constraint.version,\r\n strictly: constraint.strictly,\r\n preferred: null,\r\n rejected: [],\r\n scope: isTestConfiguration(constraint.configuration) ? 'test' : 'prod',\r\n fromCatalog: false,\r\n isConstraint: true,\r\n isPlugin: false,\r\n };\r\n add(keyOf(entry), entry);\r\n }\r\n for (const dep of project.buildscriptDependencies) {\r\n // `plugins { id 'x' version 'v' }` is reported as the marker `x:x.gradle.plugin:v`.\r\n const isPlugin = dep.group !== null && dep.name === `${dep.group}.gradle.plugin`;\r\n const entry: Entry = {\r\n group: dep.group,\r\n name: dep.name,\r\n version: dep.version,\r\n strictly: null,\r\n preferred: null,\r\n rejected: [],\r\n scope: 'plugin',\r\n fromCatalog: false,\r\n isConstraint: false,\r\n isPlugin,\r\n };\r\n add(keyOf(entry), entry);\r\n }\r\n return groups;\r\n}\r\n\r\n/** The projects of the included builds, by `group:name`: Gradle substitutes a dependency on them. */\r\nfunction substitutions(\r\n documents: readonly GradleBuildDocument[],\r\n own: GradleBuildDocument,\r\n): Map<string, { build: GradleBuildDocument; project: GradleProjectDocument }> {\r\n const table = new Map<string, { build: GradleBuildDocument; project: GradleProjectDocument }>();\r\n for (const build of documents) {\r\n if (build.build.kind !== 'included' || sameDir(build.build.dir, own.build.dir)) continue;\r\n for (const project of build.projects) {\r\n if (project.group) table.set(`${project.group}:${project.name}`, { build, project });\r\n }\r\n }\r\n return table;\r\n}\r\n\r\nfunction planModule(\r\n module: ProjectModule,\r\n build: GradleBuildDocument,\r\n project: GradleProjectDocument,\r\n documents: readonly GradleBuildDocument[],\r\n context: ScanContext,\r\n files: FileReader,\r\n): ModulePlan {\r\n const plan: ModulePlan = { module, candidates: [], skipped: [], lookups: [] };\r\n const table = substitutions(documents, build);\r\n const skip = (identifier: string, origin: DependencyOriginKind, reason: SkippedDependency['reason'], detail?: string) =>\r\n plan.skipped.push({ identifier, origin, reason, detail });\r\n\r\n for (const entries of entriesOf(project).values()) {\r\n const first = entries[0]!;\r\n const identifier = first.isPlugin ? first.group! : first.group ? `${first.group}:${first.name}` : first.name;\r\n const versioned = entries.filter((e) => e.version !== null && e.version.trim() !== '');\r\n if (versioned.length === 0) continue; // a platform, a constraint or a plugin manages the version\r\n const originKind = classifyOrigin(identifier, 'gradle', { workspace: new Map(), internalScopes: context.internalScopes }).kind;\r\n\r\n // Nothing is offered that carries a selector or a constraint, or that has no group.\r\n const unusable = versioned\r\n .map((e) => assessDependency({ group: e.group, name: e.name, version: e.version, strictly: e.strictly, preferred: e.preferred, rejected: e.rejected }))\r\n .find((assessment) => assessment.action === 'skip');\r\n if (unusable && unusable.action === 'skip') {\r\n skip(identifier, originKind, unusable.reason, unusable.detail);\r\n continue;\r\n }\r\n\r\n // The main declaration: the first of prod, test, plugin; its version is the current one.\r\n const main = [...versioned].sort((a, b) => SCOPE_ORDER[a.scope] - SCOPE_ORDER[b.scope])[0]!;\r\n const group = main.group!;\r\n const subject: Omit<Subject, 'declarations'> = {\r\n identifier,\r\n group,\r\n name: main.name,\r\n version: main.version!,\r\n scope: main.scope,\r\n isPlugin: main.isPlugin,\r\n };\r\n\r\n // A dependency on a project of an included build is substituted by Gradle (fact 15).\r\n const target = main.isPlugin ? undefined : table.get(`${group}:${main.name}`);\r\n if (target) {\r\n const local = target.project.version;\r\n const reported = !local || local === 'unspecified' ? undefined : local;\r\n if (!reported || reported === subject.version || isOutside(context.rootDir, target.project.dir)) continue;\r\n const located = locateAll(entries, subject, build, project, context, files);\r\n if (!located.ok) {\r\n skip(identifier, 'workspace', 'declaration-mismatch', located.detail);\r\n continue;\r\n }\r\n const origin: DependencyOrigin = {\r\n kind: 'workspace',\r\n moduleId: gradleModuleId(target.build.build, target.project, false),\r\n moduleRelPath: relative(canonical(context.rootDir), canonical(target.project.dir)).replace(/\\\\/g, '/'),\r\n };\r\n const candidate = buildCandidate({ ...subject, declarations: located.declarations }, reported, origin, 'align');\r\n candidate.availableVersions = [reported];\r\n plan.candidates.push(candidate);\r\n continue;\r\n }\r\n\r\n const origin = classifyOrigin(subject.identifier, 'gradle', {\r\n workspace: new Map(),\r\n internalScopes: context.internalScopes,\r\n });\r\n\r\n const located = locateAll(entries, subject, build, project, context, files);\r\n if (!located.ok) {\r\n skip(identifier, origin.kind, 'declaration-mismatch', located.detail);\r\n continue;\r\n }\r\n\r\n const kind = main.isPlugin ? 'plugin' : 'module';\r\n const repositories = effectiveRepositories(build.build, project, kind);\r\n if (repositories.length === 0) {\r\n skip(identifier, origin.kind, 'lookup-failed', `the build declares no repository for ${project.path}`);\r\n continue;\r\n }\r\n if (origin.kind === 'private' && repositories.every((r) => isPublicRepositoryUrl(r.url))) {\r\n skip(identifier, origin.kind, 'private-on-public-registry', stripCredentials(repositories[0]!.url ?? ''));\r\n continue;\r\n }\r\n\r\n plan.lookups.push({\r\n subject: { ...subject, declarations: located.declarations },\r\n origin,\r\n request: {\r\n buildRoot: build.build.dir,\r\n project: project.path,\r\n kind,\r\n group,\r\n name: main.isPlugin ? `${group}.gradle.plugin` : main.name,\r\n repositories,\r\n },\r\n });\r\n }\r\n return plan;\r\n}\r\n\r\n/**\r\n * Finds every place the coordinate's version is written. A coordinate that is\r\n * declared with different versions (a test configuration still on the old one)\r\n * is searched for each version, so the new one is written to all of them.\r\n */\r\nfunction locateAll(\r\n entries: readonly Entry[],\r\n subject: Omit<Subject, 'declarations'>,\r\n build: GradleBuildDocument,\r\n project: GradleProjectDocument,\r\n context: ScanContext,\r\n files: FileReader,\r\n): { ok: true; declarations: LocatedDeclaration[] } | { ok: false; detail: string } {\r\n const versions = [subject.version, ...new Set(entries.map((e) => e.version).filter((v): v is string => !!v && v !== subject.version))];\r\n const declarations: LocatedDeclaration[] = [];\r\n for (const version of versions) {\r\n const same = entries.filter((e) => e.version === version);\r\n const result = locateDeclarations({\r\n rootDir: context.rootDir,\r\n build: build.build,\r\n project,\r\n projects: build.projects,\r\n group: subject.group,\r\n name: subject.name,\r\n version,\r\n isPlugin: subject.isPlugin,\r\n viaScripts: subject.isPlugin || same.some((e) => !e.fromCatalog),\r\n viaCatalog: same.some((e) => e.fromCatalog),\r\n read: files.read,\r\n });\r\n if (!result.ok) return result;\r\n declarations.push(...result.declarations);\r\n }\r\n\r\n // The same text is listed once; a constraint is never the main declaration.\r\n const seen = new Set<string>();\r\n const unique = declarations.filter((d) => {\r\n const key = `${d.file}:${d.range.start}`;\r\n if (seen.has(key)) return false;\r\n seen.add(key);\r\n return true;\r\n });\r\n unique.sort((a, b) => Number(a.kind === 'dependency-management') - Number(b.kind === 'dependency-management'));\r\n return { ok: true, declarations: unique };\r\n}\r\n\r\n// ---- finishing --------------------------------------------------------------------------\r\n\r\n/** What the lookup run answered, by the id of its plan entry. */\r\nclass Answers {\r\n private readonly byId = new Map<string, LookupResultDocument>();\r\n /** The detail of the first failed lookup of the run: the cause behind \"disabled due to earlier error\". */\r\n readonly firstFailure: string | undefined;\r\n\r\n constructor(results: readonly LookupResultDocument[]) {\r\n for (const result of results) this.byId.set(result.id, result);\r\n this.firstFailure = results\r\n .filter((r) => r.error !== null)\r\n .map((r) => lookupFailureDetail(r.error!, undefined))\r\n .find((detail) => detail.isCause)?.text;\r\n }\r\n\r\n get(id: string): LookupResultDocument | undefined {\r\n return this.byId.get(id);\r\n }\r\n}\r\n\r\nfunction finishModule(plan: ModulePlan, built: BuiltPlan | undefined, answers: Answers, channel: ReleaseChannel): ScanResult {\r\n const { candidates, skipped } = plan;\r\n for (const { subject, origin, request } of plan.lookups) {\r\n const answer = built ? answers.get(built.idOf(request)) : undefined;\r\n if (!answer) {\r\n skipped.push({ identifier: subject.identifier, origin: origin.kind, reason: 'lookup-failed', detail: 'Gradle gave no answer for this lookup.' });\r\n continue;\r\n }\r\n if (answer.error !== null) {\r\n const detail = lookupFailureDetail(answer.error, answers.firstFailure).text;\r\n skipped.push({ identifier: subject.identifier, origin: origin.kind, reason: 'lookup-failed', detail });\r\n continue;\r\n }\r\n\r\n const newer = sortGradleVersions(answer.versions).filter((v) => isNewerGradleVersion(v, subject.version));\r\n const latest = pickLatest(subject.version, newer, channel);\r\n if (!latest) continue; // nothing newer, or the coordinate is unknown: neither is an error\r\n const candidate = buildCandidate(subject, latest, origin, 'update');\r\n candidate.availableVersions = [...newer, subject.version];\r\n candidates.push(candidate);\r\n }\r\n\r\n markSharedDeclarations(candidates);\r\n candidates.sort((a, b) => (DIFF_ORDER[a.diff] ?? 3) - (DIFF_ORDER[b.diff] ?? 3));\r\n return { candidates, skipped };\r\n}\r\n\r\nfunction buildCandidate(subject: Subject, target: string, origin: DependencyOrigin, action: UpdateCandidate['action']): UpdateCandidate {\r\n const currentClean = cleanJavaVersion(subject.version) ?? '0.0.0';\r\n const targetClean = cleanJavaVersion(target) ?? currentClean;\r\n const diff = semver.eq(currentClean, targetClean) ? 'patch' : diffVersions(currentClean, targetClean);\r\n const isPreRelease = isPreReleaseVersion(target);\r\n\r\n return {\r\n coordinate: {\r\n identifier: subject.identifier,\r\n group: subject.group,\r\n artifact: subject.isPlugin ? `${subject.group}.gradle.plugin` : subject.name,\r\n ecosystem: 'gradle',\r\n },\r\n currentRange: subject.version,\r\n currentClean,\r\n latest: target,\r\n newRange: target,\r\n diff,\r\n scope: subject.scope,\r\n selected: diff !== 'major',\r\n origin,\r\n action,\r\n declaration: subject.declarations[0],\r\n declarations: subject.declarations,\r\n isPreRelease,\r\n preReleaseTag: isPreRelease ? extractPreReleaseTag(target) : undefined,\r\n };\r\n}\r\n\r\n/**\r\n * Picks the newest version the channel allows from the newer versions, newest\r\n * first. A flavour suffix such as `-jre` or `-android` (Guava) is kept when a\r\n * newer version with the same flavour exists.\r\n */\r\nexport function pickLatest(current: string, newer: readonly string[], channel: ReleaseChannel): string | undefined {\r\n const allowed = newer.filter((v) => channel === 'all' || !isPreReleaseVersion(v));\r\n const flavour = flavourOf(current);\r\n const sameFlavour = flavour ? allowed.filter((v) => flavourOf(v) === flavour) : [];\r\n return (sameFlavour.length > 0 ? sameFlavour : allowed)[0];\r\n}\r\n\r\nfunction flavourOf(version: string): string | undefined {\r\n const suffix = version.match(/-([A-Za-z]+)$/)?.[1];\r\n return suffix && !isPreReleaseVersion(version) ? suffix.toLowerCase() : undefined;\r\n}\r\n\r\n/**\r\n * Several dependencies often share one property or one catalog version (all\r\n * Jackson modules, the slf4j artifacts). Updating one updates all of them,\r\n * which the UI must show.\r\n */\r\nfunction markSharedDeclarations(candidates: UpdateCandidate[]): void {\r\n const users = new Map<string, UpdateCandidate[]>();\r\n for (const candidate of candidates) {\r\n for (const declaration of candidate.declarations ?? []) {\r\n if (declaration.kind !== 'property' && declaration.kind !== 'catalog') continue;\r\n const key = `${declaration.file}:${declaration.range?.start}`;\r\n const list = users.get(key) ?? [];\r\n if (!list.includes(candidate)) users.set(key, [...list, candidate]);\r\n }\r\n }\r\n for (const group of users.values()) {\r\n if (group.length < 2) continue;\r\n for (const candidate of group) {\r\n const others = group.filter((other) => other !== candidate).map((other) => other.coordinate.identifier);\r\n candidate.sharedWith = [...new Set([...(candidate.sharedWith ?? []), ...others])];\r\n }\r\n }\r\n}\r\n","/**\r\n * Elevate — where a Gradle dependency's version is written (specs/23).\r\n *\r\n * Gradle says what applies (the version after every script has run), not where\r\n * the version is written. The locator searches the files of the build for the\r\n * text that carries it and checks its find against Gradle's answer: a location\r\n * counts only if the text there is exactly the version Gradle reports. What\r\n * cannot be located with certainty is not guessed; it comes back as the reason\r\n * it is not offered. This is the pattern of Maven's locator, for files that are\r\n * programs instead of XML.\r\n *\r\n * Searched, in this order, for the dependencies of a module: string and map\r\n * notation in the module's own build script; when that script has no such\r\n * literal, the build scripts of the parent projects, nearest first; the\r\n * definition of a name used as the version (`gradle.properties`, `ext`,\r\n * variables); `gradle/libs.versions.toml` for a dependency from the catalog.\r\n * Not searched: `buildSrc`, included-build convention plugins, `apply from:`\r\n * scripts, init scripts and the user's `gradle.properties`.\r\n */\r\n\r\nimport { join, relative } from 'node:path';\r\nimport type { SkipReason, VersionDeclaration } from '../../domain/models.js';\r\nimport {\r\n CATALOG_FILE,\r\n CATALOG_NAME,\r\n catalogVersionKeys,\r\n catalogVersionRange,\r\n catalogVersionText,\r\n parseCatalog,\r\n} from './gradle-catalog.js';\r\nimport type { GradleBuildDocument, GradleProjectDocument } from './gradle-probe.js';\r\nimport { dslOf, findBlocks, scanSource } from './gradle-text.js';\r\nimport type { GradleDsl, ScannedSource, StringLiteral } from './gradle-text.js';\r\n\r\n// ---- what Gradle reports, and what it means -------------------------------------\r\n\r\n/** The parts of a reported dependency that decide whether it is offered. */\r\nexport interface ReportedVersion {\r\n group: string | null;\r\n name: string;\r\n version: string | null;\r\n strictly: string | null;\r\n preferred: string | null;\r\n rejected: readonly string[];\r\n}\r\n\r\nexport type Assessment =\r\n | { action: 'ignore' }\r\n | { action: 'skip'; reason: SkipReason; detail?: string }\r\n | { action: 'locate' };\r\n\r\nconst DYNAMIC_VERSION = /^\\+$|\\+$|^latest\\.|^[[(\\]]/;\r\n\r\n/**\r\n * Decides what to do with a reported external module: nothing to offer when it\r\n * has no version (a platform, a constraint or a plugin manages it), listed when\r\n * it has no group, when the version is a selector, or when it carries\r\n * `strictly`, `reject` or `prefer`.\r\n */\r\nexport function assessDependency(dependency: ReportedVersion): Assessment {\r\n const version = dependency.version;\r\n if (version === null || version.trim() === '') return { action: 'ignore' };\r\n if (!dependency.group) return { action: 'skip', reason: 'invalid-name', detail: 'no group' };\r\n if (dependency.strictly) {\r\n return { action: 'skip', reason: 'version-constraint', detail: `strictly '${dependency.strictly}'` };\r\n }\r\n if (dependency.rejected.length > 0) {\r\n return { action: 'skip', reason: 'version-constraint', detail: `reject '${dependency.rejected.join(\"', '\")}'` };\r\n }\r\n if (dependency.preferred) {\r\n return { action: 'skip', reason: 'version-constraint', detail: `prefer '${dependency.preferred}'` };\r\n }\r\n if (DYNAMIC_VERSION.test(version)) {\r\n return { action: 'skip', reason: 'version-constraint', detail: `dynamic version '${version}'` };\r\n }\r\n return { action: 'locate' };\r\n}\r\n\r\n/** A configuration is a test configuration when one of the words of its camelCase name is \"test\". */\r\nexport function isTestConfiguration(configuration: string): boolean {\r\n return configuration\r\n .split(/(?=[A-Z])/)\r\n .some((word) => word.toLowerCase() === 'test');\r\n}\r\n\r\n// ---- locating -----------------------------------------------------------------------\r\n\r\n/** A place a version is written, with the text offsets an update replaces. */\r\nexport interface LocatedDeclaration extends VersionDeclaration {\r\n range: { start: number; end: number; before: string; after: string; text: string };\r\n}\r\n\r\nexport interface LocateRequest {\r\n /** The repository root, for the paths shown to the user. */\r\n rootDir: string;\r\n /** The build the project belongs to: its directory holds `gradle.properties`, the settings file and the catalog. */\r\n build: GradleBuildDocument['build'];\r\n project: GradleProjectDocument;\r\n /** Every project of the build, to find the parent projects. */\r\n projects: readonly GradleProjectDocument[];\r\n /** The coordinate and the version Gradle reports. For a plugin `group` is the plugin id. */\r\n group: string;\r\n name: string;\r\n version: string;\r\n isPlugin: boolean;\r\n /** Gradle reports a declaration of the coordinate that is not from the catalog (or a plugin). */\r\n viaScripts: boolean;\r\n /** Gradle reports a declaration of the coordinate that comes from the catalog. */\r\n viaCatalog: boolean;\r\n /** Reads a file as text (byte order mark included); `undefined` when it does not exist. */\r\n read(file: string): string | undefined;\r\n}\r\n\r\nexport type LocateResult =\r\n | { ok: true; declarations: LocatedDeclaration[] }\r\n | { ok: false; detail: string };\r\n\r\n/** A location before the characters around it are recorded. */\r\ntype Raw = VersionDeclaration & { range: { start: number; end: number } };\r\ntype RawResult = { ok: true; declarations: Raw[] } | { ok: false; detail: string };\r\n\r\nconst fail = (detail: string): { ok: false; detail: string } => ({ ok: false, detail });\r\n\r\nfunction escapeRegExp(text: string): string {\r\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n}\r\n\r\n/** Path of `file` relative to the repository root, with forward slashes. */\r\nfunction displayPath(rootDir: string, file: string): string {\r\n return relative(rootDir, file).replace(/\\\\/g, '/');\r\n}\r\n\r\nconst SETTINGS_FILES = ['settings.gradle', 'settings.gradle.kts'];\r\n\r\ninterface Script {\r\n file: string;\r\n source: string;\r\n dsl: GradleDsl;\r\n scanned: ScannedSource;\r\n}\r\n\r\nclass Locator {\r\n private readonly scripts: Script[] = [];\r\n private readonly settings: Script[] = [];\r\n\r\n constructor(private readonly request: LocateRequest) {\r\n const { project, projects, build } = request;\r\n const own = project.buildFile ?? join(project.dir, 'build.gradle');\r\n this.addScript(this.scripts, own);\r\n // The parent projects of the same build, nearest first.\r\n const segments = project.path.split(':').filter(Boolean);\r\n for (let n = segments.length - 1; n >= 0; n--) {\r\n const path = n === 0 ? ':' : `:${segments.slice(0, n).join(':')}`;\r\n const parent = projects.find((candidate) => candidate.path === path);\r\n if (parent?.buildFile) this.addScript(this.scripts, parent.buildFile);\r\n }\r\n for (const name of SETTINGS_FILES) this.addScript(this.settings, join(build.dir, name));\r\n }\r\n\r\n private addScript(into: Script[], file: string): void {\r\n const source = this.request.read(file);\r\n if (source === undefined) return;\r\n const dsl = dslOf(file);\r\n into.push({ file, source, dsl, scanned: scanSource(source, dsl) });\r\n }\r\n\r\n private show(file: string): string {\r\n return displayPath(this.request.rootDir, file);\r\n }\r\n\r\n /** `app/build.gradle`: the build script of the module, named in the messages. */\r\n private get ownScript(): string {\r\n return this.show(this.request.project.buildFile ?? join(this.request.project.dir, 'build.gradle'));\r\n }\r\n\r\n locate(): LocateResult {\r\n const results: RawResult[] = [];\r\n if (this.request.viaScripts) results.push(this.request.isPlugin ? this.locatePlugin() : this.locateInScripts());\r\n if (this.request.viaCatalog) results.push(this.locateInCatalog());\r\n if (results.length === 0) return fail(this.notFound());\r\n\r\n // Every part must be found: a coordinate that is only partly changed would resolve to the old version.\r\n const parts: Raw[] = [];\r\n for (const result of results) {\r\n if (!result.ok) return result;\r\n parts.push(...result.declarations);\r\n }\r\n\r\n // One place is listed once, whichever way it was found.\r\n const seen = new Set<string>();\r\n const unique = parts.filter((d) => {\r\n const key = `${d.file}:${d.range.start}`;\r\n if (seen.has(key)) return false;\r\n seen.add(key);\r\n return true;\r\n });\r\n // A constraint is a declaration of the coordinate too, but never the main one.\r\n unique.sort((a, b) => Number(a.kind === 'dependency-management') - Number(b.kind === 'dependency-management'));\r\n return { ok: true, declarations: unique.map((d) => this.withContext(d)) };\r\n }\r\n\r\n /** Records the characters around the version text, so an update notices that `1.0` became `1.0.1`. */\r\n private withContext(declaration: Raw): LocatedDeclaration {\r\n const source = this.request.read(declaration.file) ?? '';\r\n const { start, end } = declaration.range;\r\n return {\r\n ...declaration,\r\n range: {\r\n start,\r\n end,\r\n before: source.slice(Math.max(0, start - 1), start),\r\n after: source.slice(end, end + 1),\r\n text: source.slice(start, end),\r\n },\r\n };\r\n }\r\n\r\n private notFound(): string {\r\n const { group, name, version, isPlugin } = this.request;\r\n const what = isPlugin ? `${group}:${version}` : `${group}:${name}:${version}`;\r\n return `no declaration of ${what} found in ${this.ownScript} or in the build scripts of its parent projects`;\r\n }\r\n\r\n // ---- dependencies in build scripts ------------------------------------------------\r\n\r\n private locateInScripts(): RawResult {\r\n for (const script of this.scripts) {\r\n const found = this.literalsIn(script);\r\n if (found.length === 0) continue;\r\n const declarations: Raw[] = [];\r\n for (const hit of found) {\r\n if (hit.type === 'literal') {\r\n declarations.push(hit.declaration);\r\n } else if (hit.type === 'name') {\r\n const resolved = this.resolveName(hit.name);\r\n if (!resolved.ok) return resolved;\r\n declarations.push(...resolved.declarations);\r\n } else {\r\n const resolved = this.resolveCatalogAccessor(hit.accessor);\r\n if (!resolved.ok) return resolved;\r\n declarations.push(...resolved.declarations);\r\n }\r\n }\r\n return { ok: true, declarations };\r\n }\r\n return fail(this.notFound());\r\n }\r\n\r\n private literalsIn(script: Script): Hit[] {\r\n const { group, name, version } = this.request;\r\n const hits: Hit[] = [];\r\n const constraints = findBlocks(script.scanned.masked, 'constraints');\r\n const kindAt = (offset: number): 'dependency' | 'dependency-management' =>\r\n constraints.some((block) => offset > block.start && offset < block.end) ? 'dependency-management' : 'dependency';\r\n const literal = (start: number, end: number): Hit => ({\r\n type: 'literal',\r\n declaration: {\r\n file: script.file,\r\n kind: kindAt(start),\r\n displayPath: this.show(script.file),\r\n range: { start, end },\r\n },\r\n });\r\n\r\n // String notation: \"group:name:version[:classifier][@extension]\".\r\n for (const lit of script.scanned.literals) {\r\n const parts = lit.value.split(':');\r\n if (parts.length < 3 || parts[0] !== group || parts[1] !== name) continue;\r\n let third = parts[2]!;\r\n if (parts.length === 3) third = third.replace(/@[^@]*$/, '');\r\n const start = lit.start + parts[0].length + 1 + parts[1].length + 1;\r\n const end = start + third.length;\r\n if (third === version) {\r\n hits.push(literal(start, end));\r\n continue;\r\n }\r\n if (!lit.quote.startsWith('\"')) continue;\r\n const reference = /^\\$(\\w+)$|^\\$\\{(\\w+)\\}$/.exec(third);\r\n if (reference) {\r\n hits.push({ type: 'name', name: (reference[1] ?? reference[2])! });\r\n continue;\r\n }\r\n const accessor = /^\\$\\{libs\\.versions\\.([\\w.-]+)\\.get\\(\\)\\}$/.exec(third);\r\n if (accessor) hits.push({ type: 'accessor', accessor: accessor[1]! });\r\n }\r\n\r\n // Map notation: group, name and version of one call, in any order.\r\n const masked = script.scanned.masked;\r\n const anchor = new RegExp(`\\\\bname\\\\s*[:=]\\\\s*(['\"])${escapeRegExp(name)}\\\\1`, 'g');\r\n for (const match of masked.matchAll(anchor)) {\r\n const region = enclosingCall(masked, match.index!);\r\n const text = masked.slice(region.start, region.end);\r\n const groupKey = new RegExp(`\\\\bgroup\\\\s*[:=]\\\\s*(['\"])${escapeRegExp(group)}\\\\1`);\r\n if (!groupKey.test(text)) continue;\r\n const versionKey = /\\bversion\\s*[:=]\\s*(?:(['\"])(.*?)\\1|([A-Za-z_]\\w*))/d.exec(text);\r\n if (!versionKey) continue;\r\n if (versionKey[3] !== undefined) {\r\n hits.push({ type: 'name', name: versionKey[3] });\r\n } else if (versionKey[2] === version) {\r\n const start = region.start + versionKey.indices![2]![0];\r\n hits.push(literal(start, start + version.length));\r\n }\r\n }\r\n\r\n return dedupeHits(hits);\r\n }\r\n\r\n // ---- names ---------------------------------------------------------------------------\r\n\r\n /** The definition of a name used as the version: `gradle.properties` first, then the scripts. */\r\n private resolveName(name: string): RawResult {\r\n const { project, build, rootDir, version } = this.request;\r\n const pattern = new RegExp(`^([ \\\\t]*${escapeRegExp(name)}[ \\\\t]*[=:][ \\\\t]*)(.*?)[ \\\\t]*$`, 'gm');\r\n\r\n const propertyFiles = [...new Set([join(project.dir, 'gradle.properties'), join(build.dir, 'gradle.properties')])];\r\n for (const file of propertyFiles) {\r\n const source = this.request.read(file);\r\n if (source === undefined) continue;\r\n const matches = [...source.matchAll(pattern)];\r\n if (matches.length === 0) continue;\r\n const shown = displayPath(rootDir, file);\r\n if (matches.length > 1) return fail(`'${name}' is defined twice in ${shown}`);\r\n const match = matches[0]!;\r\n if (match[2] !== version) {\r\n return fail(`'${name}' is ${match[2]} in ${shown} but Gradle uses ${version} (command line or user-level override?)`);\r\n }\r\n const start = match.index! + match[1]!.length;\r\n return {\r\n ok: true,\r\n declarations: [\r\n { file, kind: 'property', propertyName: name, displayPath: shown, range: { start, end: start + version.length } },\r\n ],\r\n };\r\n }\r\n\r\n for (const script of this.scripts) {\r\n const definitions = definitionsOf(script, name);\r\n if (definitions.length === 0) continue;\r\n const shown = this.show(script.file);\r\n if (definitions.length > 1) return fail(`'${name}' is defined twice in ${shown}`);\r\n const definition = definitions[0]!;\r\n if (definition.value !== version) {\r\n return fail(`'${name}' is ${definition.value} in ${shown} but Gradle uses ${version} (command line or user-level override?)`);\r\n }\r\n return {\r\n ok: true,\r\n declarations: [\r\n {\r\n file: script.file,\r\n kind: 'property',\r\n propertyName: name,\r\n displayPath: shown,\r\n range: { start: definition.start, end: definition.end },\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return fail(\r\n `no definition of '${name}' in gradle.properties or in the build scripts of '${project.path}' and its parent projects`,\r\n );\r\n }\r\n\r\n // ---- plugins ---------------------------------------------------------------------------\r\n\r\n private locatePlugin(): RawResult {\r\n const { group: id, version } = this.request;\r\n const idPattern = escapeRegExp(id);\r\n const shorthand = /^org\\.jetbrains\\.kotlin\\.(.+)$/.exec(id)?.[1];\r\n\r\n const forms = [\r\n new RegExp(`\\\\bid\\\\s*\\\\(?\\\\s*(['\"])${idPattern}\\\\1\\\\s*\\\\)?\\\\s*version\\\\s*\\\\(?\\\\s*(['\"])(.*?)\\\\2`, 'dg'),\r\n ];\r\n if (shorthand) {\r\n forms.push(\r\n new RegExp(`\\\\bkotlin\\\\s*\\\\(\\\\s*(['\"])${escapeRegExp(shorthand)}\\\\1\\\\s*\\\\)\\\\s*version\\\\s*\\\\(?\\\\s*(['\"])(.*?)\\\\2`, 'dg'),\r\n );\r\n }\r\n\r\n // The scripts first, the settings file (`pluginManagement { plugins { } }`) after them.\r\n for (const group of [this.scripts, this.settings]) {\r\n for (const script of group) {\r\n const declarations: Raw[] = [];\r\n for (const form of forms) {\r\n for (const match of script.scanned.masked.matchAll(form)) {\r\n const [start, end] = match.indices![3]!;\r\n if (script.source.slice(start, end) !== version) continue;\r\n declarations.push({\r\n file: script.file,\r\n kind: 'plugin',\r\n displayPath: this.show(script.file),\r\n range: { start, end },\r\n });\r\n }\r\n }\r\n if (declarations.length > 0) return { ok: true, declarations };\r\n }\r\n }\r\n\r\n // `alias(libs.plugins.x)`: the version is in the catalog.\r\n const fromCatalog = this.locateInCatalog();\r\n if (fromCatalog.ok) return fromCatalog;\r\n return fail(this.notFound());\r\n }\r\n\r\n // ---- the catalog -----------------------------------------------------------------------\r\n\r\n private get catalogFile(): string {\r\n return join(this.request.build.dir, CATALOG_FILE);\r\n }\r\n\r\n private locateInCatalog(): RawResult {\r\n const { group, name, version, isPlugin, rootDir } = this.request;\r\n const shown = displayPath(rootDir, this.catalogFile);\r\n const noEntry = (): RawResult =>\r\n fail(\r\n isPlugin\r\n ? `no entry for plugin ${group}:${version} in ${CATALOG_FILE} (other catalogs are not read)`\r\n : `no entry for ${group}:${name}:${version} in ${CATALOG_FILE} (other catalogs are not read)`,\r\n );\r\n\r\n const source = this.request.read(this.catalogFile);\r\n const catalog = source === undefined ? undefined : parseCatalog(source);\r\n if (source === undefined || !catalog) return noEntry();\r\n\r\n const matching = catalog.entries.filter((entry) =>\r\n isPlugin\r\n ? entry.section === 'plugins' && entry.id === group && catalogVersionText(entry.version) === version\r\n : entry.section === 'libraries' &&\r\n entry.group === group &&\r\n entry.name === name &&\r\n catalogVersionText(entry.version) === version,\r\n );\r\n if (matching.length === 0) return noEntry();\r\n if (matching.length > 1) {\r\n return fail(\r\n `${matching.length} entries of ${CATALOG_FILE} declare ${group}:${name}:${version}: ${matching.map((e) => e.key).join(', ')}`,\r\n );\r\n }\r\n\r\n const entry = matching[0]!;\r\n const range = catalogVersionRange(source, entry.versionEntry);\r\n if (!range || source.slice(range.start, range.end) !== version) {\r\n return fail(`cannot locate the version of ${entry.versionEntry} in ${CATALOG_FILE}`);\r\n }\r\n return {\r\n ok: true,\r\n declarations: [\r\n {\r\n file: this.catalogFile,\r\n kind: 'catalog',\r\n catalogName: CATALOG_NAME,\r\n entry: entry.versionEntry,\r\n displayPath: shown,\r\n range,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n /** `\"g:a:${libs.versions.lib.get()}\"`: the version entry the accessor names. */\r\n private resolveCatalogAccessor(accessor: string): RawResult {\r\n const { version, rootDir } = this.request;\r\n const source = this.request.read(this.catalogFile);\r\n const key = source === undefined ? undefined : catalogVersionKeys(source).find((k) => k.replace(/[-_]/g, '.') === accessor);\r\n const range = key === undefined || source === undefined ? undefined : catalogVersionRange(source, `versions.${key}`);\r\n if (!range || source === undefined || source.slice(range.start, range.end) !== version) {\r\n return fail(`no entry for ${accessor} with the version ${version} in ${CATALOG_FILE} (other catalogs are not read)`);\r\n }\r\n return {\r\n ok: true,\r\n declarations: [\r\n {\r\n file: this.catalogFile,\r\n kind: 'catalog',\r\n catalogName: CATALOG_NAME,\r\n entry: `versions.${key}`,\r\n displayPath: displayPath(rootDir, this.catalogFile),\r\n range,\r\n },\r\n ],\r\n };\r\n }\r\n}\r\n\r\ntype Hit =\r\n | { type: 'literal'; declaration: Raw }\r\n | { type: 'name'; name: string }\r\n | { type: 'accessor'; accessor: string };\r\n\r\nfunction dedupeHits(hits: Hit[]): Hit[] {\r\n const seen = new Set<string>();\r\n return hits.filter((hit) => {\r\n const key =\r\n hit.type === 'literal'\r\n ? `l:${hit.declaration.file}:${hit.declaration.range.start}`\r\n : hit.type === 'name'\r\n ? `n:${hit.name}`\r\n : `a:${hit.accessor}`;\r\n if (seen.has(key)) return false;\r\n seen.add(key);\r\n return true;\r\n });\r\n}\r\n\r\n/** The part of the source inside the parentheses around `index`, or its line when there are none. */\r\nfunction enclosingCall(masked: string, index: number): { start: number; end: number } {\r\n let depth = 0;\r\n for (let i = index - 1; i >= 0; i--) {\r\n const ch = masked[i];\r\n if (ch === '\\n') break;\r\n if (ch === ')') depth++;\r\n else if (ch === '(') {\r\n if (depth === 0) {\r\n let close = 1;\r\n for (let j = i + 1; j < masked.length; j++) {\r\n if (masked[j] === '(') close++;\r\n else if (masked[j] === ')' && --close === 0) return { start: i + 1, end: j };\r\n }\r\n break;\r\n }\r\n depth--;\r\n }\r\n }\r\n const start = masked.lastIndexOf('\\n', index) + 1;\r\n let end = masked.indexOf('\\n', index);\r\n if (end === -1) end = masked.length;\r\n return { start, end };\r\n}\r\n\r\ninterface Definition {\r\n value: string;\r\n start: number;\r\n end: number;\r\n}\r\n\r\n/** The plain string literals a script assigns to `name`: variables, `ext` values and `extra` entries. */\r\nfunction definitionsOf(script: Script, name: string): Definition[] {\r\n const n = escapeRegExp(name);\r\n const { masked, literals } = script.scanned;\r\n const byOpening = new Map<number, StringLiteral>();\r\n for (const lit of literals) byOpening.set(lit.start - lit.quote.length, lit);\r\n\r\n const patterns: { regex: RegExp; within?: { start: number; end: number }[] }[] =\r\n script.dsl === 'groovy'\r\n ? [\r\n { regex: new RegExp(`(?<![\\\\w.])(?:def|String|final\\\\s+String|final\\\\s+def)\\\\s+${n}\\\\s*=\\\\s*(?=['\"])`, 'g') },\r\n { regex: new RegExp(`(?<![\\\\w.])(?:project\\\\.)?ext\\\\.${n}\\\\s*=\\\\s*(?=['\"])`, 'g') },\r\n { regex: new RegExp(`(?<![\\\\w.])${n}\\\\s*=\\\\s*(?=['\"])`, 'g'), within: findBlocks(masked, 'ext') },\r\n ]\r\n : [\r\n { regex: new RegExp(`\\\\b(?:val|var)\\\\s+${n}(?:\\\\s*:\\\\s*String)?\\\\s*=\\\\s*(?=\")`, 'g') },\r\n { regex: new RegExp(`\\\\bextra\\\\s*\\\\[\\\\s*\"${n}\"\\\\s*\\\\]\\\\s*=\\\\s*(?=\")`, 'g') },\r\n { regex: new RegExp(`\\\\b(?:val|var)\\\\s+${n}\\\\s+by\\\\s+extra\\\\s*\\\\(\\\\s*(?=\")`, 'g') },\r\n ];\r\n\r\n const found = new Map<number, Definition>();\r\n for (const { regex, within } of patterns) {\r\n for (const match of masked.matchAll(regex)) {\r\n const opening = match.index! + match[0].length;\r\n if (within && !within.some((block) => opening > block.start && opening < block.end)) continue;\r\n const lit = byOpening.get(opening);\r\n if (!lit) continue;\r\n found.set(lit.start, { value: lit.value, start: lit.start, end: lit.end });\r\n }\r\n }\r\n\r\n // A definition counts when the literal is the whole value: nothing but the end of the statement follows.\r\n return [...found.values()].filter((definition) => {\r\n const lit = literals.find((candidate) => candidate.start === definition.start)!;\r\n if (lit.quote.startsWith('\"') && lit.value.includes('$')) return false;\r\n const after = masked.slice(lit.end + lit.quote.length);\r\n return /^[ \\t]*(?:\\r?\\n|;|\\}|\\)|$)/.test(after);\r\n });\r\n}\r\n\r\n/** Finds where the version of a reported dependency is written. */\r\nexport function locateDeclarations(request: LocateRequest): LocateResult {\r\n return new Locator(request).locate();\r\n}\r\n","/**\r\n * Elevate — the version catalog `gradle/libs.versions.toml`.\r\n *\r\n * Gradle reads `gradle/libs.versions.toml` of a build as the catalog \"libs\".\r\n * Elevate reads it as TOML to match a dependency to an entry by coordinates,\r\n * and finds the exact text of a version with a small scanner so that an update\r\n * changes nothing but that text: comments, spacing, order, line endings and a\r\n * byte order mark stay (specs/23, GRDCAT-01 to GRDCAT-17). Other catalogs,\r\n * declared in the settings, are not read.\r\n */\r\n\r\nimport { parse } from 'smol-toml';\r\n\r\n/** Where the catalog of a build lives, relative to the build's directory. */\r\nexport const CATALOG_FILE = 'gradle/libs.versions.toml';\r\n/** The name Gradle gives that catalog. */\r\nexport const CATALOG_NAME = 'libs';\r\n\r\n/** A version as the catalog writes it: plain, or rich with `require`, `strictly`, `prefer`, `reject`. */\r\nexport interface CatalogVersion {\r\n require?: string;\r\n strictly?: string;\r\n prefer?: string;\r\n reject?: string[];\r\n}\r\n\r\nexport interface CatalogEntry {\r\n section: 'libraries' | 'plugins';\r\n /** The alias as written in the file. */\r\n key: string;\r\n /** `group` and `name` of a library. */\r\n group?: string;\r\n name?: string;\r\n /** The id of a plugin. */\r\n id?: string;\r\n /** The version after `version.ref` is resolved; `undefined` when the entry has none. */\r\n version?: CatalogVersion;\r\n /** The entry that holds the version text: `versions.<ref>` or `<section>.<key>`. */\r\n versionEntry: string;\r\n}\r\n\r\nexport interface GradleCatalog {\r\n entries: CatalogEntry[];\r\n}\r\n\r\ntype Json = Record<string, unknown>;\r\n\r\nfunction isTable(value: unknown): value is Json {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction stringOf(value: unknown): string | undefined {\r\n return typeof value === 'string' ? value : undefined;\r\n}\r\n\r\nfunction versionOf(raw: unknown): CatalogVersion | undefined {\r\n if (typeof raw === 'string') return { require: raw };\r\n if (!isTable(raw)) return undefined;\r\n const reject = Array.isArray(raw.reject) ? raw.reject.filter((v): v is string => typeof v === 'string') : undefined;\r\n return {\r\n require: stringOf(raw.require),\r\n strictly: stringOf(raw.strictly),\r\n prefer: stringOf(raw.prefer),\r\n reject: reject ?? (typeof raw.reject === 'string' ? [raw.reject] : undefined),\r\n };\r\n}\r\n\r\n/** The version text a plain entry carries: `require`, else `strictly`, else `prefer`. */\r\nexport function catalogVersionText(version: CatalogVersion | undefined): string | undefined {\r\n return version?.require ?? version?.strictly ?? version?.prefer;\r\n}\r\n\r\n/** Whether the version has a constraint that an update must not change. */\r\nexport function catalogConstraint(version: CatalogVersion | undefined): string | undefined {\r\n if (!version) return undefined;\r\n if (version.strictly !== undefined) return `strictly '${version.strictly}'`;\r\n if (version.reject && version.reject.length > 0) return `reject '${version.reject.join(\"', '\")}'`;\r\n if (version.prefer !== undefined && version.require === undefined) return `prefer '${version.prefer}'`;\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Reads the entries of a catalog. `undefined` when the text is not valid TOML.\r\n */\r\nexport function parseCatalog(source: string): GradleCatalog | undefined {\r\n let doc: Json;\r\n try {\r\n doc = parse(source.replace(/^/, '')) as Json;\r\n } catch {\r\n return undefined;\r\n }\r\n\r\n const versions = isTable(doc.versions) ? doc.versions : {};\r\n const entries: CatalogEntry[] = [];\r\n\r\n const resolve = (raw: unknown, section: 'libraries' | 'plugins', key: string): Pick<CatalogEntry, 'version' | 'versionEntry'> => {\r\n const own = { versionEntry: `${section}.${key}` };\r\n if (isTable(raw) && isTable(raw.version) && typeof raw.version.ref === 'string') {\r\n const ref = raw.version.ref;\r\n return { version: versionOf(versions[ref]), versionEntry: `versions.${ref}` };\r\n }\r\n return { ...own, version: versionOf(isTable(raw) ? raw.version : undefined) };\r\n };\r\n\r\n if (isTable(doc.libraries)) {\r\n for (const [key, raw] of Object.entries(doc.libraries)) {\r\n if (typeof raw === 'string') {\r\n const [group, name, ...rest] = raw.split(':');\r\n if (!group || !name) continue;\r\n entries.push({\r\n section: 'libraries', key, group, name,\r\n version: rest.length > 0 ? { require: rest.join(':') } : undefined,\r\n versionEntry: `libraries.${key}`,\r\n });\r\n } else if (isTable(raw)) {\r\n let group = stringOf(raw.group);\r\n let name = stringOf(raw.name);\r\n const module = stringOf(raw.module);\r\n if (module) [group, name] = module.split(':');\r\n if (!group || !name) continue;\r\n entries.push({ section: 'libraries', key, group, name, ...resolve(raw, 'libraries', key) });\r\n }\r\n }\r\n }\r\n\r\n if (isTable(doc.plugins)) {\r\n for (const [key, raw] of Object.entries(doc.plugins)) {\r\n if (typeof raw === 'string') {\r\n const at = raw.lastIndexOf(':');\r\n entries.push({\r\n section: 'plugins', key, id: at === -1 ? raw : raw.slice(0, at),\r\n version: at === -1 ? undefined : { require: raw.slice(at + 1) },\r\n versionEntry: `plugins.${key}`,\r\n });\r\n } else if (isTable(raw) && typeof raw.id === 'string') {\r\n entries.push({ section: 'plugins', key, id: raw.id, ...resolve(raw, 'plugins', key) });\r\n }\r\n }\r\n }\r\n\r\n return { entries };\r\n}\r\n\r\n/** The `[versions]` keys, for the accessor `libs.versions.<key>.get()`. */\r\nexport function catalogVersionKeys(source: string): string[] {\r\n try {\r\n const doc = parse(source.replace(/^/, '')) as Json;\r\n return isTable(doc.versions) ? Object.keys(doc.versions) : [];\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\n// ---- finding the text of a version ----------------------------------------------\r\n\r\ninterface Range {\r\n start: number;\r\n end: number;\r\n}\r\n\r\n/** The text between the quotes of the TOML string that opens at `open`. */\r\nfunction stringAt(text: string, open: number): Range | undefined {\r\n const quote = text[open];\r\n if (quote !== '\"' && quote !== \"'\") return undefined;\r\n for (let i = open + 1; i < text.length; i++) {\r\n if (quote === '\"' && text[i] === '\\\\') {\r\n i++;\r\n continue;\r\n }\r\n if (text[i] === quote) return { start: open + 1, end: i };\r\n }\r\n return undefined;\r\n}\r\n\r\n/** Cuts a `#` comment off a line, respecting strings. Returns the length of the code part. */\r\nfunction codeLength(line: string): number {\r\n let quote: string | undefined;\r\n for (let i = 0; i < line.length; i++) {\r\n const ch = line[i]!;\r\n if (quote) {\r\n if (quote === '\"' && ch === '\\\\') i++;\r\n else if (ch === quote) quote = undefined;\r\n } else if (ch === '\"' || ch === \"'\") {\r\n quote = ch;\r\n } else if (ch === '#') {\r\n return i;\r\n }\r\n }\r\n return line.length;\r\n}\r\n\r\n/**\r\n * The exact text of the version of a catalog entry, as offsets into `source`:\r\n * the string of `versions.<key>`, or of `libraries.<key>` and `plugins.<key>`\r\n * (the part after the last colon of `\"g:a:1.0\"`, the `version` string, or the\r\n * `require` string of a rich version).\r\n */\r\nexport function catalogVersionRange(source: string, entry: string): Range | undefined {\r\n const dot = entry.indexOf('.');\r\n const section = entry.slice(0, dot);\r\n const key = entry.slice(dot + 1);\r\n\r\n let currentSection: string | undefined;\r\n let offset = 0;\r\n for (const rawLine of source.split('\\n')) {\r\n const lineStart = offset;\r\n offset += rawLine.length + 1;\r\n const line = rawLine.slice(0, codeLength(rawLine));\r\n\r\n const header = /^\\s*\\[\\s*([A-Za-z0-9_.-]+)\\s*\\]\\s*$/.exec(line.replace(/^/, ''));\r\n if (header) {\r\n currentSection = header[1];\r\n continue;\r\n }\r\n if (currentSection !== section) continue;\r\n\r\n const assignment = /^?\\s*(?:\"([^\"]*)\"|'([^']*)'|([A-Za-z0-9_-]+))\\s*=\\s*/.exec(line);\r\n if (!assignment || (assignment[1] ?? assignment[2] ?? assignment[3]) !== key) continue;\r\n\r\n const valueStart = assignment[0].length;\r\n const value = line.slice(valueStart);\r\n const inLine = (range: Range): Range => ({ start: lineStart + valueStart + range.start, end: lineStart + valueStart + range.end });\r\n\r\n if (value.startsWith('\"') || value.startsWith(\"'\")) {\r\n const text = stringAt(value, 0);\r\n if (!text) return undefined;\r\n if (section === 'versions') return inLine(text);\r\n const inner = value.slice(text.start, text.end);\r\n const colon = inner.lastIndexOf(':');\r\n return colon === -1 ? undefined : inLine({ start: text.start + colon + 1, end: text.end });\r\n }\r\n\r\n if (value.startsWith('{')) {\r\n const versionString = /\\bversion\\s*=\\s*([\"'])/.exec(value);\r\n if (versionString && section !== 'versions') {\r\n return inLine(stringAt(value, versionString.index + versionString[0].length - 1)!);\r\n }\r\n const require = /\\brequire\\s*=\\s*([\"'])/.exec(value);\r\n if (require) return inLine(stringAt(value, require.index + require[0].length - 1)!);\r\n const nested = /\\bversion\\s*=\\s*\\{[^}]*?\\brequire\\s*=\\s*([\"'])/.exec(value);\r\n if (nested) return inLine(stringAt(value, nested.index + nested[0].length - 1)!);\r\n }\r\n return undefined;\r\n }\r\n return undefined;\r\n}\r\n","/**\r\n * Elevate — reading and editing the text of Gradle build scripts.\r\n *\r\n * A build script is a program, so Elevate does not parse it; it looks for the\r\n * text that carries a version and changes exactly that text (specs/23). Both\r\n * DSLs are read by the same literal rules: outside comments, every string\r\n * literal is a candidate (single, double and triple quotes). The text around a\r\n * literal is never changed, so layout, quotes, comments, tabs, line endings and\r\n * a byte order mark survive an update.\r\n */\r\n\r\nimport { StaleEditError } from '../shared/xml.js';\r\n\r\nexport type GradleDsl = 'groovy' | 'kotlin';\r\n\r\n/** A string literal. `start` and `end` delimit the text between the quotes (end exclusive). */\r\nexport interface StringLiteral {\r\n value: string;\r\n start: number;\r\n end: number;\r\n /** The quote that opens the literal: `'`, `\"`, `'''` or `\"\"\"`. */\r\n quote: string;\r\n}\r\n\r\nexport interface ScannedSource {\r\n /** The source with every comment replaced by spaces (line breaks stay), so offsets are the same. */\r\n masked: string;\r\n literals: StringLiteral[];\r\n}\r\n\r\n/** Whether `dsl` is the Kotlin one for a file name. */\r\nexport function dslOf(file: string): GradleDsl {\r\n return file.endsWith('.kts') ? 'kotlin' : 'groovy';\r\n}\r\n\r\n/**\r\n * Walks the source once and returns the string literals outside comments and\r\n * the source with its comments blanked out. A `//` or `/*` inside a string is\r\n * not a comment; a quote inside a comment does not open a string.\r\n */\r\nexport function scanSource(source: string, _dsl: GradleDsl): ScannedSource {\r\n const literals: StringLiteral[] = [];\r\n const chars = source.split('');\r\n const blank = (from: number, to: number): void => {\r\n for (let k = from; k < to; k++) if (chars[k] !== '\\n' && chars[k] !== '\\r') chars[k] = ' ';\r\n };\r\n\r\n let i = 0;\r\n while (i < source.length) {\r\n const ch = source[i]!;\r\n const next = source[i + 1];\r\n\r\n if (ch === '/' && next === '/') {\r\n let end = source.indexOf('\\n', i);\r\n if (end === -1) end = source.length;\r\n blank(i, end);\r\n i = end;\r\n } else if (ch === '/' && next === '*') {\r\n const close = source.indexOf('*/', i + 2);\r\n const end = close === -1 ? source.length : close + 2;\r\n blank(i, end);\r\n i = end;\r\n } else if (ch === \"'\" || ch === '\"') {\r\n const triple = source.startsWith(ch.repeat(3), i);\r\n const quote = triple ? ch.repeat(3) : ch;\r\n const start = i + quote.length;\r\n const end = findStringEnd(source, start, ch, triple);\r\n literals.push({ value: source.slice(start, end), start, end, quote });\r\n i = Math.min(end + quote.length, source.length);\r\n } else {\r\n i++;\r\n }\r\n }\r\n\r\n return { masked: chars.join(''), literals };\r\n}\r\n\r\n/** The offset of the quote that closes the string whose text starts at `start`. */\r\nfunction findStringEnd(source: string, start: number, quote: string, triple: boolean): number {\r\n let depth = 0; // inside ${ ... } of a double-quoted string\r\n let i = start;\r\n while (i < source.length) {\r\n const ch = source[i]!;\r\n if (ch === '\\\\' && !triple) {\r\n i += 2;\r\n continue;\r\n }\r\n if (quote === '\"' && ch === '$' && source[i + 1] === '{') {\r\n depth++;\r\n i += 2;\r\n continue;\r\n }\r\n if (depth > 0) {\r\n if (ch === '{') depth++;\r\n else if (ch === '}') depth--;\r\n i++;\r\n continue;\r\n }\r\n if (triple) {\r\n if (source.startsWith(quote.repeat(3), i)) return i;\r\n } else if (ch === quote) {\r\n return i;\r\n } else if (ch === '\\n') {\r\n return i; // an unterminated string ends at the line break\r\n }\r\n i++;\r\n }\r\n return source.length;\r\n}\r\n\r\n/** The string literals of a script outside comments. */\r\nexport function findStringLiterals(source: string, dsl: GradleDsl): StringLiteral[] {\r\n return scanSource(source, dsl).literals;\r\n}\r\n\r\n/** Offset ranges of the `{ … }` blocks that follow `keyword` (e.g. `constraints`), in a masked source. */\r\nexport function findBlocks(masked: string, keyword: string): { start: number; end: number }[] {\r\n const blocks: { start: number; end: number }[] = [];\r\n const opener = new RegExp(`\\\\b${keyword}\\\\s*\\\\{`, 'g');\r\n for (const match of masked.matchAll(opener)) {\r\n const open = match.index! + match[0].length - 1;\r\n let depth = 0;\r\n for (let i = open; i < masked.length; i++) {\r\n if (masked[i] === '{') depth++;\r\n else if (masked[i] === '}' && --depth === 0) {\r\n blocks.push({ start: open, end: i });\r\n break;\r\n }\r\n }\r\n }\r\n return blocks;\r\n}\r\n\r\n/** One replacement of text a scan found. */\r\nexport interface GradleTextEdit {\r\n start: number;\r\n end: number;\r\n /** The text that must be there; anything else means the file changed since it was scanned. */\r\n expected: string;\r\n replacement: string;\r\n /** The character directly before and after the text at scan time (`''` at the edges of the file). */\r\n before?: string;\r\n after?: string;\r\n}\r\n\r\n/**\r\n * Applies replacements to the original source. Every edit verifies that the\r\n * text it replaces is still the one that was scanned, so an edit computed from\r\n * an outdated scan fails loudly instead of overwriting a change made in the\r\n * meantime. Edits on the same range are allowed when they agree.\r\n *\r\n * @throws StaleEditError\r\n */\r\nexport function applyGradleEdits(source: string, edits: readonly GradleTextEdit[]): string {\r\n const unique = new Map<string, GradleTextEdit>();\r\n for (const edit of edits) {\r\n const key = `${edit.start}:${edit.end}`;\r\n const known = unique.get(key);\r\n if (known && known.replacement !== edit.replacement) {\r\n throw new StaleEditError(`Conflicting edits of the same text at offset ${edit.start}.`);\r\n }\r\n unique.set(key, edit);\r\n }\r\n\r\n const sorted = [...unique.values()].sort((a, b) => a.start - b.start);\r\n for (let i = 0; i < sorted.length; i++) {\r\n const edit = sorted[i]!;\r\n const found = source.slice(edit.start, edit.end);\r\n const before = source.slice(Math.max(0, edit.start - 1), edit.start);\r\n const after = source.slice(edit.end, edit.end + 1);\r\n if (\r\n found !== edit.expected ||\r\n (edit.before !== undefined && before !== edit.before) ||\r\n (edit.after !== undefined && after !== edit.after)\r\n ) {\r\n // Show the whole value that is there now, not just the part that still matches.\r\n let end = edit.end;\r\n if (edit.after !== undefined && after !== edit.after) {\r\n while (end < source.length && end - edit.end < 40 && !/[\\s'\"),;}]/.test(source[end]!)) end++;\r\n }\r\n const shown = `${edit.before !== undefined && before !== edit.before ? before : ''}${source.slice(edit.start, end)}`;\r\n throw new StaleEditError(`'${shown}' found where '${edit.expected}' was expected. The file changed since it was scanned.`);\r\n }\r\n if (i > 0 && edit.start < sorted[i - 1]!.end) {\r\n throw new StaleEditError('Overlapping edits on the same text.');\r\n }\r\n }\r\n\r\n let result = source;\r\n for (const edit of [...sorted].reverse()) {\r\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\r\n }\r\n return result;\r\n}\r\n","/**\r\n * Elevate — Gradle updater.\r\n *\r\n * Writes each new version to the text that declares it (specs/23) and brings\r\n * the dependency locks of the build up to date when it uses them (specs/25).\r\n * Edits replace only the version text, so layout, quotes, comments, line\r\n * endings and a byte order mark survive, and each edit checks that the file\r\n * still holds what the scan saw. Every edit is computed before the first file\r\n * is written.\r\n *\r\n * Gradle has no installed state to repair: the snapshot of the files taken by\r\n * the update workflow is the whole rollback, and the verification that follows\r\n * (a Gradle run that resolves and compiles) is what judges the result.\r\n */\r\n\r\nimport { readFileSync, writeFileSync } from 'node:fs';\r\nimport { relative, resolve } from 'node:path';\r\nimport type { ProjectModule, UpdateCandidate, VersionDeclaration } from '../../domain/models.js';\r\nimport { InstallError } from '../../domain/ports.js';\r\nimport type { ApplyOutcome, DependencyUpdaterPort } from '../../domain/ports.js';\r\nimport { StaleEditError } from '../shared/xml.js';\r\nimport { findLockFiles, refreshLocks } from './gradle-locks.js';\r\nimport { applyGradleEdits } from './gradle-text.js';\r\nimport type { GradleTextEdit } from './gradle-text.js';\r\n\r\n/** The places a candidate's version is written, the first being its main declaration. */\r\nfunction declarationsOf(update: UpdateCandidate): VersionDeclaration[] {\r\n return update.declarations ?? (update.declaration ? [update.declaration] : []);\r\n}\r\n\r\nfunction display(rootDir: string, file: string): string {\r\n return relative(rootDir, file).replace(/\\\\/g, '/');\r\n}\r\n\r\nfunction describeShared(declaration: VersionDeclaration): string {\r\n if (declaration.kind === 'property') return `the property $${declaration.propertyName} in ${declaration.displayPath}`;\r\n if (declaration.kind === 'catalog') return `the version ${declaration.entry} in ${declaration.displayPath}`;\r\n return `a version in ${declaration.displayPath}`;\r\n}\r\n\r\nexport class GradleUpdaterAdapter implements DependencyUpdaterPort {\r\n /**\r\n * The files named by the declarations, in the order of the candidates, then\r\n * every lock file below the directory of the build. `verification-metadata.xml`\r\n * is never among them: it is not regenerated (a regenerated file records the\r\n * checksum of whatever was downloaded and defeats its purpose).\r\n */\r\n affectedFiles(module: ProjectModule, _rootDir: string, updates: UpdateCandidate[]): string[] {\r\n const files = new Set<string>();\r\n for (const update of updates) {\r\n for (const declaration of declarationsOf(update)) files.add(resolve(declaration.file));\r\n }\r\n for (const lock of findLockFiles(module.buildDir ?? module.path)) files.add(lock);\r\n return [...files];\r\n }\r\n\r\n async applyUpdates(\r\n module: ProjectModule,\r\n rootDir: string,\r\n updates: UpdateCandidate[],\r\n onProgress: (stepMessage: string) => void,\r\n ): Promise<ApplyOutcome> {\r\n const buildDir = module.buildDir ?? module.path;\r\n const inRootBuild = module.buildKind === undefined || module.buildKind === 'root';\r\n\r\n // Locks of an included build or buildSrc are not refreshed; a half-refreshed lock state\r\n // is worse than none, so such an update is refused before anything changes.\r\n if (!inRootBuild) {\r\n const locks = findLockFiles(module.buildRoot ?? module.path);\r\n if (locks.length > 0) {\r\n throw new InstallError(\r\n `The build of module ${module.id} (${module.relPath}) uses dependency locking (${display(rootDir, locks[0]!)}), ` +\r\n 'which Elevate refreshes only for the root build. Nothing was changed.',\r\n );\r\n }\r\n }\r\n\r\n // Compute every edit before writing anything, so a stale or conflicting edit\r\n // in the second file does not leave the first one half-updated.\r\n const byFile = new Map<string, { displayPath: string; edits: Map<string, GradleTextEdit & { identifier: string; declaration: VersionDeclaration }> }>();\r\n for (const update of updates) {\r\n const identifier = update.coordinate.identifier;\r\n const declarations = declarationsOf(update);\r\n if (declarations.length === 0) {\r\n throw new InstallError(`No version declaration known for ${identifier}; rescan the module.`);\r\n }\r\n for (const declaration of declarations) {\r\n if (!declaration.range) {\r\n throw new InstallError(`${declaration.displayPath}: cannot find the version of ${identifier} any more; rescan the module.`);\r\n }\r\n const file = resolve(declaration.file);\r\n const entry = byFile.get(file) ?? { displayPath: declaration.displayPath, edits: new Map() };\r\n byFile.set(file, entry);\r\n\r\n const key = `${declaration.range.start}:${declaration.range.end}`;\r\n const existing = entry.edits.get(key);\r\n if (existing) {\r\n if (existing.replacement !== update.newRange) {\r\n throw new InstallError(\r\n `${identifier} and ${existing.identifier} share ${describeShared(declaration)} ` +\r\n `but target different versions (${update.newRange} vs ${existing.replacement}).`,\r\n );\r\n }\r\n continue;\r\n }\r\n entry.edits.set(key, {\r\n start: declaration.range.start,\r\n end: declaration.range.end,\r\n expected: declaration.range.text ?? update.currentRange,\r\n replacement: update.newRange,\r\n before: declaration.range.before,\r\n after: declaration.range.after,\r\n identifier,\r\n declaration,\r\n });\r\n }\r\n }\r\n\r\n const writes: { file: string; content: string }[] = [];\r\n for (const [file, { displayPath, edits }] of byFile) {\r\n onProgress(`Preparing ${edits.size} change(s) in ${displayPath}…`);\r\n try {\r\n writes.push({ file, content: applyGradleEdits(readFileSync(file, 'utf8'), [...edits.values()]) });\r\n } catch (err) {\r\n if (err instanceof StaleEditError) throw new InstallError(`${displayPath}: ${err.message}`);\r\n throw err;\r\n }\r\n }\r\n\r\n onProgress('Writing build files…');\r\n for (const write of writes) writeFileSync(write.file, write.content, 'utf8');\r\n\r\n // A library or platform was updated and the build locks its dependencies: refresh the locks.\r\n let refreshed = 0;\r\n const libraries = updates.filter((update) => update.scope !== 'plugin');\r\n if (inRootBuild && libraries.length > 0 && findLockFiles(buildDir).length > 0) {\r\n onProgress('Refreshing dependency locks…');\r\n refreshed = await refreshLocks(module, rootDir, libraries.map((update) => update.coordinate.identifier));\r\n }\r\n\r\n return {\r\n updatedCount: updates.length,\r\n auditMessage:\r\n `Updated ${updates.length} version declaration(s) in ${writes.length} file(s).` +\r\n (refreshed > 0 ? ` Refreshed ${refreshed} dependency lock file(s).` : ''),\r\n auditSeverity: 'clean',\r\n integrityViolations: [],\r\n };\r\n }\r\n\r\n async resync(): Promise<void> {\r\n // Gradle keeps no installed state next to the build files; restoring them suffices.\r\n }\r\n}\r\n","/**\r\n * Elevate — Gradle dependency locks.\r\n *\r\n * With dependency locking (`dependencyLocking { lockAllConfigurations() }`) a\r\n * `gradle.lockfile` sits in each project directory, and raising a declared\r\n * version makes every task that resolves it fail until the lock is refreshed\r\n * (\"Dependency version enforced by Dependency Locking\"). Elevate refreshes the\r\n * locks with Gradle's own command (specs/25, facts 22, 34 to 36):\r\n *\r\n * <gradle> -q --console=plain --no-configuration-cache\r\n * :app:dependencies :core:dependencies … --update-locks g:a,g:b\r\n *\r\n * The task `dependencies` must be named per project (at the root it reports\r\n * the root project only), and all lock files of the build are refreshed\r\n * together, because a stale lock does not always fail: a lower declared\r\n * version is silently resolved down to the locked one.\r\n */\r\n\r\nimport { existsSync, readdirSync } from 'node:fs';\r\nimport { join, resolve } from 'node:path';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { InstallError } from '../../domain/ports.js';\r\nimport { UnsafeArgumentError } from '../shared/process.js';\r\nimport { GradleCommandError, GradleUnavailableError, GradleVersionError, gradleErrors, runGradle } from './gradle-command.js';\r\nimport { runDescribe } from './gradle-probe.js';\r\n\r\nconst LOCK_FILE = 'gradle.lockfile';\r\nconst SKIPPED_DIRECTORIES = new Set(['node_modules', 'build', 'target', 'dist', 'out']);\r\nconst REFRESH_TIMEOUT_MINUTES = 10;\r\n\r\n/**\r\n * Every `gradle.lockfile` below the directory of a build, absolute and sorted.\r\n * Build output and dependency directories, and directories whose name starts\r\n * with \".\", are not entered.\r\n */\r\nexport function findLockFiles(buildDir: string): string[] {\r\n const found: string[] = [];\r\n const walk = (dir: string): void => {\r\n let entries;\r\n try {\r\n entries = readdirSync(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n for (const entry of entries) {\r\n if (entry.isFile() && entry.name === LOCK_FILE) found.push(join(dir, entry.name));\r\n else if (entry.isDirectory() && !entry.name.startsWith('.') && !SKIPPED_DIRECTORIES.has(entry.name)) {\r\n walk(join(dir, entry.name));\r\n }\r\n }\r\n };\r\n walk(resolve(buildDir));\r\n return found.sort();\r\n}\r\n\r\n/**\r\n * Brings the lock files of the module's build up to date for the updated\r\n * coordinates (`group:name`). Describes the build, names `:dependencies` for\r\n * each project that has a lock file in the order of their Gradle paths, and\r\n * returns the number of lock files that exist afterwards.\r\n *\r\n * @throws InstallError when Gradle cannot be run, fails, or does not finish\r\n */\r\nexport async function refreshLocks(module: ProjectModule, rootDir: string, coordinates: readonly string[]): Promise<number> {\r\n const buildDir = module.buildDir ?? module.path;\r\n try {\r\n const documents = await runDescribe(buildDir, rootDir);\r\n const build = documents.find((doc) => resolve(doc.build.dir) === resolve(buildDir)) ?? documents[0];\r\n const locked = (build?.projects ?? []).filter((project) => project.lockfile).sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));\r\n if (locked.length === 0) return 0;\r\n\r\n const tasks = locked.map((project) => `${project.path === ':' ? '' : project.path}:dependencies`);\r\n const args = [\r\n '-q',\r\n '--console=plain',\r\n '--no-configuration-cache',\r\n ...tasks,\r\n '--update-locks',\r\n [...new Set(coordinates)].sort().join(','),\r\n ];\r\n const result = await runGradle(args, { cwd: buildDir, rootDir, timeoutMs: REFRESH_TIMEOUT_MINUTES * 60_000 });\r\n if (result.timedOut) {\r\n throw new InstallError(`Refreshing the Gradle dependency locks timed out after ${REFRESH_TIMEOUT_MINUTES} minutes.`);\r\n }\r\n if (result.exitCode !== 0) {\r\n throw new InstallError(`Refreshing the Gradle dependency locks failed\\n${gradleErrors(result)}`);\r\n }\r\n return locked.filter((project) => existsSync(join(project.dir, LOCK_FILE))).length;\r\n } catch (err) {\r\n if (err instanceof InstallError) throw err;\r\n if (\r\n err instanceof UnsafeArgumentError ||\r\n err instanceof GradleUnavailableError ||\r\n err instanceof GradleCommandError ||\r\n err instanceof GradleVersionError\r\n ) {\r\n throw new InstallError(err.message);\r\n }\r\n throw err;\r\n }\r\n}\r\n","/**\r\n * Elevate — Gradle verification.\r\n *\r\n * Lets the build judge the update: a Gradle run that resolves and compiles what\r\n * the change can affect. The projects checked are the projects of the module's\r\n * build that the changed files can affect (specs/25):\r\n *\r\n * - a file in the directory of a project P that is not the root project (build\r\n * script, properties, lock file): P and every project that depends on P\r\n * through `project(...)`, directly or indirectly;\r\n * - a file of the root project (root build script, gradle.properties, the\r\n * settings file, `gradle/libs.versions.toml`, the root lock file): every\r\n * project of the build;\r\n * - no changed file known: the project of the module and its dependents.\r\n *\r\n * Each affected project is checked with `testClasses` (main and test sources\r\n * compile), else `assemble`, else nothing. Without any task the run is `help`,\r\n * which configures the build and compiles `buildSrc`. A failed build is a\r\n * warning that quotes Gradle; dependency verification\r\n * (`gradle/verification-metadata.xml`) is never regenerated.\r\n */\r\n\r\nimport { resolve, sep } from 'node:path';\r\nimport type { VerificationOptions, VerificationPort, VerificationResult } from '../../domain/ports.js';\r\nimport type { ProjectModule } from '../../domain/models.js';\r\nimport { UnsafeArgumentError, runShellScript } from '../shared/process.js';\r\nimport type { RunResult } from '../shared/process.js';\r\nimport { GradleCommandError, GradleUnavailableError, GradleVersionError, gradleErrors, runGradle } from './gradle-command.js';\r\nimport { runDescribe } from './gradle-probe.js';\r\nimport type { GradleBuildDocument, GradleProjectDocument } from './gradle-probe.js';\r\n\r\nconst VERIFY_TIMEOUT_MINUTES = 30;\r\nconst FALLBACK_LABEL = 'Gradle build';\r\nconst TASKS = ['testClasses', 'assemble'] as const;\r\n\r\nconst HELP_ONLY = 'Only the configuration of the build and buildSrc were checked: no project with a compile task is affected.';\r\n\r\nexport class GradleVerificationAdapter implements VerificationPort {\r\n async verify(module: ProjectModule, rootDir: string, options: VerificationOptions = {}): Promise<VerificationResult> {\r\n const buildDir = module.buildDir ?? module.path;\r\n\r\n if (options.customScript) {\r\n const label = options.customLabel || options.customScript;\r\n const result = await runShellScript(options.customScript, { cwd: buildDir, timeoutMs: VERIFY_TIMEOUT_MINUTES * 60_000 });\r\n return result.exitCode === 0\r\n ? { status: 'clean', details: 'Verification script succeeded.', label }\r\n : { status: 'warn', details: result.timedOut ? 'Verification script timed out.' : failureDetails(result), label };\r\n }\r\n\r\n try {\r\n const documents = await runDescribe(buildDir, rootDir);\r\n const plan = planGradleBuild(module, documents, options.changedFiles ?? []);\r\n const result = await runGradle(['-q', '--console=plain', ...plan.tasks], {\r\n cwd: buildDir,\r\n rootDir,\r\n timeoutMs: VERIFY_TIMEOUT_MINUTES * 60_000,\r\n });\r\n if (result.exitCode === 0 && !result.timedOut) {\r\n const onlyHelp = plan.tasks.length === 1 && plan.tasks[0] === 'help';\r\n return { status: 'clean', details: onlyHelp ? HELP_ONLY : 'All affected projects build successfully.', label: plan.label };\r\n }\r\n return { status: 'warn', details: result.timedOut ? 'Gradle build timed out.' : failureDetails(result), label: plan.label };\r\n } catch (err) {\r\n // Gradle that cannot be started, or a build that cannot be described, is a warning, not a crash.\r\n if (\r\n err instanceof GradleUnavailableError ||\r\n err instanceof GradleCommandError ||\r\n err instanceof GradleVersionError ||\r\n err instanceof UnsafeArgumentError\r\n ) {\r\n return { status: 'warn', details: err.message, label: FALLBACK_LABEL };\r\n }\r\n throw err;\r\n }\r\n }\r\n}\r\n\r\n/** Gradle's own words for a failure, or the exit code when it printed nothing. */\r\nfunction failureDetails(result: RunResult): string {\r\n return gradleErrors(result) || `Exited with code ${result.exitCode}.`;\r\n}\r\n\r\nfunction sameOrInside(dir: string, file: string): boolean {\r\n const base = resolve(dir);\r\n const target = resolve(file);\r\n return target === base || target.startsWith(base + sep);\r\n}\r\n\r\n/**\r\n * Chooses the tasks that check what a change can affect. A pure function of the\r\n * described build: `documents` is what the describe run of the module's build\r\n * returned, `changedFiles` are absolute paths (none when unknown).\r\n */\r\nexport function planGradleBuild(\r\n module: ProjectModule,\r\n documents: readonly GradleBuildDocument[],\r\n changedFiles: readonly string[],\r\n): { tasks: string[]; label: string } {\r\n const help = { tasks: ['help'], label: `${FALLBACK_LABEL} (help)` };\r\n const document = documents.find((doc) => resolve(doc.build.dir) === resolve(module.buildRoot ?? module.buildDir ?? module.path));\r\n // buildSrc has no selector: every run compiles it.\r\n if (!document || document.build.kind === 'buildSrc') return help;\r\n\r\n const projects = document.projects;\r\n const own = projects.find((project) => resolve(project.dir) === resolve(module.path));\r\n const dependents = (start: readonly string[]): Set<string> => {\r\n const affected = new Set(start);\r\n for (let grew = true; grew; ) {\r\n grew = false;\r\n for (const project of projects) {\r\n if (!affected.has(project.path) && project.projectDependencies.some((dependency) => affected.has(dependency.path))) {\r\n affected.add(project.path);\r\n grew = true;\r\n }\r\n }\r\n }\r\n return affected;\r\n };\r\n\r\n // The project whose directory is the deepest one that holds the file.\r\n const ownerOf = (file: string): GradleProjectDocument | undefined =>\r\n projects\r\n .filter((project) => sameOrInside(project.dir, file))\r\n .sort((a, b) => resolve(b.dir).length - resolve(a.dir).length)[0];\r\n\r\n let affected = new Set<string>();\r\n for (const file of changedFiles) {\r\n const owner = ownerOf(file);\r\n if (!owner) continue;\r\n if (owner.path === ':') {\r\n affected = new Set(projects.map((project) => project.path));\r\n break;\r\n }\r\n for (const path of dependents([owner.path])) affected.add(path);\r\n }\r\n if (affected.size === 0 && own) affected = dependents([own.path]);\r\n\r\n const chosen = projects\r\n .filter((project) => affected.has(project.path))\r\n .map((project) => ({ project, task: TASKS.find((task) => project.tasks.includes(task)) }))\r\n .filter((entry): entry is { project: GradleProjectDocument; task: (typeof TASKS)[number] } => entry.task !== undefined);\r\n\r\n // In the root build, running a task in every project that has it is exactly what is wanted\r\n // when the whole build is affected and those are the projects that need it.\r\n const inRootBuild = document.build.kind === 'root';\r\n const wholeBuild = affected.size === projects.length;\r\n const unqualified = TASKS.filter((task) => {\r\n const needed = chosen.filter((entry) => entry.task === task).length;\r\n return inRootBuild && wholeBuild && needed > 0 && needed === projects.filter((project) => project.tasks.includes(task)).length;\r\n });\r\n\r\n const prefix = inRootBuild ? '' : `:${document.build.name}`;\r\n const qualified = chosen\r\n .filter((entry) => !unqualified.includes(entry.task))\r\n .map((entry) => `${prefix}${entry.project.path === ':' ? '' : entry.project.path}:${entry.task}`)\r\n .sort();\r\n\r\n const tasks = [...unqualified, ...qualified];\r\n if (tasks.length === 0) return help;\r\n return { tasks, label: `${FALLBACK_LABEL} (${tasks.join(' ')})` };\r\n}\r\n","/**\r\n * Elevate — Gradle ecosystem strategy: wires the Gradle adapters together.\r\n */\r\n\r\nimport type { EcosystemStrategy, TabLabels } from '../../domain/ecosystem-strategy.js';\r\nimport type { Ecosystem } from '../../domain/models.js';\r\nimport { mavenVersionPolicy } from '../../domain/version-policy.js';\r\nimport { GradleModuleDiscoveryAdapter } from './gradle-discovery.js';\r\nimport { GradleRegistryAdapter } from './gradle-registry.js';\r\nimport { GradleDependencyAdapter } from './gradle-scanner.js';\r\nimport { GradleUpdaterAdapter } from './gradle-updater.js';\r\nimport { GradleVerificationAdapter } from './gradle-verifier.js';\r\n\r\nexport class GradleEcosystemStrategy implements EcosystemStrategy {\r\n readonly ecosystem: Ecosystem = 'gradle';\r\n readonly displayName = 'Java / Gradle';\r\n readonly icon = '🐘';\r\n readonly manifestFile = 'build.gradle';\r\n /** Gradle versions follow the JVM rules Maven uses: a version is written as it is, `1.0-rc1` is a pre-release. */\r\n readonly versioning = mavenVersionPolicy;\r\n\r\n readonly discovery = new GradleModuleDiscoveryAdapter();\r\n readonly registry = new GradleRegistryAdapter();\r\n readonly reader = new GradleDependencyAdapter();\r\n readonly updater = new GradleUpdaterAdapter();\r\n readonly verifier = new GradleVerificationAdapter();\r\n\r\n getTabLabels(\r\n counts: { total: number; prodCount: number; devCount: number },\r\n t: any,\r\n ): TabLabels {\r\n return {\r\n all: t.tabs.all(counts.total),\r\n prod: t.tabs.main(counts.prodCount),\r\n dev: t.tabs.testAndPlugins(counts.devCount),\r\n };\r\n }\r\n}\r\n","/**\r\n * 🪶 Elevate — Ecosystem Factory (Factory Pattern)\r\n *\r\n * Creates and caches the ecosystem strategies for Node/npm, Java/Maven, Rust/Cargo and Java/Gradle.\r\n */\r\n\r\nimport type { Ecosystem } from './models.js';\r\nimport type { EcosystemStrategy } from './ecosystem-strategy.js';\r\nimport { NpmEcosystemStrategy } from '../adapters/npm/npm-strategy.js';\r\nimport { CargoEcosystemStrategy } from '../adapters/cargo/cargo-strategy.js';\r\nimport { MavenEcosystemStrategy } from '../adapters/maven/maven-strategy.js';\r\nimport { GradleEcosystemStrategy } from '../adapters/gradle/gradle-strategy.js';\r\nimport type { MavenPluginVersions } from '../adapters/maven/maven-resolution.js';\r\n\r\n/** Settings the strategies are created with. */\r\nexport interface EcosystemSettings {\r\n /** Versions of the Maven plugins Elevate runs; defaults apply when omitted. */\r\n mavenPlugins?: MavenPluginVersions;\r\n}\r\n\r\nexport class EcosystemFactory {\r\n private static instances = new Map<Ecosystem, EcosystemStrategy>();\r\n private static settings: EcosystemSettings = {};\r\n\r\n /**\r\n * Stores the settings and drops the cached strategies, so strategies created\r\n * afterwards use them. Without a call the defaults apply.\r\n */\r\n static configure(settings: EcosystemSettings): void {\r\n this.settings = settings;\r\n this.instances.clear();\r\n }\r\n\r\n /** Returns the strategy for an ecosystem (lazily created singleton). */\r\n static getStrategy(ecosystem: Ecosystem): EcosystemStrategy {\r\n let strategy = this.instances.get(ecosystem);\r\n if (!strategy) {\r\n if (ecosystem === 'maven') {\r\n strategy = new MavenEcosystemStrategy(this.settings.mavenPlugins);\r\n } else if (ecosystem === 'cargo') {\r\n strategy = new CargoEcosystemStrategy();\r\n } else if (ecosystem === 'gradle') {\r\n strategy = new GradleEcosystemStrategy();\r\n } else {\r\n strategy = new NpmEcosystemStrategy();\r\n }\r\n this.instances.set(ecosystem, strategy);\r\n }\r\n return strategy;\r\n }\r\n\r\n /**\r\n * All supported ecosystems. The order is the order the repository root is\r\n * asked in and the order the dashboard cycles through.\r\n */\r\n static getAvailableEcosystems(): Ecosystem[] {\r\n return ['npm', 'maven', 'cargo', 'gradle'];\r\n }\r\n\r\n /** The ecosystem after `current`, for the dashboard's ecosystem switch. */\r\n static next(current: Ecosystem): Ecosystem {\r\n const all = this.getAvailableEcosystems();\r\n return all[(all.indexOf(current) + 1) % all.length]!;\r\n }\r\n}\r\n"],"mappings":";AAQA,SAAS,cAAAA,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,WAAAC,WAAS,QAAAC,QAAM,WAAAC,iBAAe;;;ACFvC,OAAOC,aAAY;;;ACHnB,OAAO,YAAY;AAQnB,IAAM,cACJ;AAGK,SAAS,oBAAoB,SAA0B;AAC5D,SAAO,YAAY,KAAK,OAAO;AACjC;AAGO,SAAS,qBAAqB,SAAqC;AACxE,QAAM,QAAQ,QAAQ,MAAM,WAAW;AACvC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAQ,MAAM,CAAC,EAAG,YAAY;AACpC,MAAI,UAAU,IAAK,QAAO;AAC1B,MAAI,UAAU,IAAK,QAAO;AAC1B,MAAI,UAAU,KAAK;AACjB,UAAM,SAAS,QAAQ,OAAO,MAAM,SAAS,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,MAAM,IAAI,CAAC;AACpF,WAAO,IAAI,UAAU,EAAE;AAAA,EACzB;AACA,SAAO,MAAM,YAAY;AAC3B;AAOO,SAAS,iBAAiB,SAAgC;AAC/D,QAAM,QAAQ,QAAQ,MAAM,wBAAwB;AACpD,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,OAAO,OAAO,MAAM,CAAC,CAAC,GAAG,WAAW;AAC7C;AAGO,SAAS,aAAa,MAAc,IAAyC;AAClF,QAAM,OAAO,OAAO,KAAK,MAAM,EAAE;AACjC,MAAI,SAAS,WAAW,SAAS,WAAY,QAAO;AACpD,MAAI,SAAS,WAAW,SAAS,WAAY,QAAO;AACpD,SAAO;AACT;AAGO,SAAS,YAAY,OAA+B;AACzD,MAAI,MAAM,WAAW,GAAG,EAAG,QAAO;AAClC,MAAI,MAAM,WAAW,GAAG,EAAG,QAAO;AAClC,SAAO;AACT;;;ADnCO,SAAS,WAAW,SAAiB,QAAgB,WAAsD;AAChH,QAAM,KAAK,UAAU,MAAM;AAC3B,MAAI,CAAC,MAAM,CAACC,QAAO,MAAM,OAAO,EAAG,QAAO;AAC1C,SAAOA,QAAO,GAAG,SAAS,EAAE,IAAI,UAAU,aAAa,SAAS,EAAE;AACpE;AAEO,IAAM,mBAAkC;AAAA,EAC7C,WAAW,CAAC,MAAMA,QAAO,MAAM,CAAC;AAAA,EAChC,SAAS,CAAC,SAAS,WAAW,GAAG,YAAY,OAAO,CAAC,GAAG,MAAM;AAAA,EAC9D,MAAM,CAAC,SAAS,WAAW,WAAW,SAAS,QAAQ,CAAC,MAAMA,QAAO,MAAM,CAAC,CAAC;AAAA,EAC7E,qBAAqB;AACvB;AAEO,IAAM,qBAAoC;AAAA,EAC/C,WAAW;AAAA,EACX,SAAS,CAAC,UAAU,WAAW;AAAA,EAC/B,MAAM,CAAC,SAAS,WAAW,WAAW,SAAS,QAAQ,gBAAgB;AAAA,EACvE,qBAAqB;AACvB;;;AEhCA,SAAS,cAAAC,aAAY,oBAAoB;AACzC,SAAS,WAAAC,UAAS,QAAAC,OAAM,WAAAC,gBAAe;;;ACFvC,SAAS,kBAAkB;AAC3B,SAAS,SAAS,MAAM,eAAe;AAOhC,SAAS,qBAAqB,UAAsC;AACzE,MAAI,MAAM,QAAQ,QAAQ;AAC1B,aAAS;AACP,QAAI,WAAW,KAAK,KAAK,MAAM,CAAC,EAAG,QAAO;AAC1C,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;;;ACZA,SAAS,MAAM,aAAa;AAC5B,SAAS,YAAY,gBAAgB;AAgB9B,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YAAY,UAAkB;AAC5B;AAAA,MACE,eAAe,KAAK,UAAU,QAAQ,CAAC;AAAA,IAGzC;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,aAAa,QAAQ,aAAa;AAGxC,IAAM,iBAAiB;AAMhB,SAAS,WAAW,SAAiB,MAAgB,SAAyC;AACnG,SAAO,IAAI,QAAQ,CAACC,WAAS,WAAW;AACtC,UAAM,eAAe,EAAE,KAAK,QAAQ,KAAK,aAAa,MAAM,KAAK,QAAQ,IAAI;AAC7E,QAAIC;AAEJ,QAAI,YAAY;AACd,iBAAW,OAAO,CAAC,SAAS,GAAG,IAAI,GAAG;AACpC,YAAI,eAAe,KAAK,GAAG,GAAG;AAC5B,iBAAO,IAAI,oBAAoB,GAAG,CAAC;AACnC;AAAA,QACF;AAAA,MACF;AAIA,YAAM,cAAc,CAAC,SAAS,GAAG,IAAI,EAAE,IAAI,YAAY,EAAE,KAAK,GAAG;AACjE,MAAAA,SAAQ,MAAM,aAAa,EAAE,GAAG,cAAc,OAAO,KAAK,CAAC;AAAA,IAC7D,OAAO;AACL,MAAAA,SAAQ,MAAM,SAAS,MAAM,YAAY;AAAA,IAC3C;AAEA,QAAI,SAAS;AACb,QAAI,SAAS;AACb,QAAI,WAAW;AACf,IAAAA,OAAM,OAAO,YAAY,MAAM,EAAE,GAAG,QAAQ,CAAC,UAAmB,UAAU,KAAM;AAChF,IAAAA,OAAM,OAAO,YAAY,MAAM,EAAE,GAAG,QAAQ,CAAC,UAAmB,UAAU,KAAM;AAEhF,UAAM,QAAQ,QAAQ,YAClB,WAAW,MAAM;AACf,iBAAW;AACX,eAASA,OAAM,KAAK,MAAMA,OAAM,KAAK,CAAC;AAAA,IACxC,GAAG,QAAQ,SAAS,IACpB;AAEJ,IAAAA,OAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,UAAI,MAAO,cAAa,KAAK;AAC7B,aAAO,GAAG;AAAA,IACZ,CAAC;AAED,IAAAA,OAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,UAAI,MAAO,cAAa,KAAK;AAC7B,MAAAD,UAAQ,EAAE,UAAU,QAAQ,GAAG,QAAQ,QAAQ,SAAS,CAAC;AAAA,IAC3D,CAAC;AAAA,EACH,CAAC;AACH;AAOO,SAAS,eAAe,QAAgB,SAAyC;AACtF,SAAO,IAAI,QAAQ,CAACA,cAAY;AAC9B;AAAA,MACE;AAAA,MACA,EAAE,KAAK,QAAQ,KAAK,SAAS,QAAQ,WAAW,WAAW,KAAK,OAAO,MAAM,aAAa,KAAK;AAAA,MAC/F,CAAC,OAAO,QAAQ,WAAW;AACzB,cAAM,WAAW,QAAQ,OAAO,MAAM;AACtC,cAAM,WAAW,QAAS,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO,IAAK;AAC7E,QAAAA,UAAQ,EAAE,UAAU,QAAQ,QAAQ,SAAS,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAOA,SAAS,SAAS,KAAyB,UAA4B;AACrE,MAAI,CAAC,cAAc,QAAQ,QAAW;AACpC,aAAS;AACT;AAAA,EACF;AACA,QAAM,SAAS,MAAM,YAAY,CAAC,QAAQ,OAAO,GAAG,GAAG,MAAM,IAAI,GAAG,EAAE,aAAa,MAAM,OAAO,SAAS,CAAC;AAC1G,SAAO,GAAG,SAAS,QAAQ;AAC7B;AAGO,SAAS,KAAK,QAAgB,QAAQ,IAAY;AACvD,SAAO,OAAO,KAAK,EAAE,MAAM,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,IAAI;AAC7D;AAEA,SAAS,aAAa,KAAqB;AAEzC,SAAO,kBAAkB,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG;AACpD;AAUO,SAAS,cAAc,KAAa,MAAsB;AAC/D,QAAM,OAAO,SAAS,KAAK,IAAI;AAC/B,SAAO,WAAW,IAAI,IAAI,OAAO,QAAQ;AAC3C;;;AF9HA,IAAM,eAAmE;AAAA,EACvE,CAAC,OAAO,CAAC,qBAAqB,qBAAqB,CAAC;AAAA,EACpD,CAAC,QAAQ,CAAC,kBAAkB,qBAAqB,CAAC;AAAA,EAClD,CAAC,QAAQ,CAAC,aAAa,aAAa,CAAC;AAAA,EACrC,CAAC,OAAO,CAAC,YAAY,WAAW,CAAC;AACnC;AAGO,IAAM,iCAAN,cAA6C,MAAM;AAAA,EACxD,YAAY,UAAkC;AAC5C;AAAA,MACE,iCAAiC,SAAS,IAAI,KAAK,SAAS,QAAQ,4GAE/D,SAAS,IAAI;AAAA,IACpB;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAWO,SAAS,qBAAqB,KAAqC;AACxE,QAAM,WAAW,qBAAqB,GAAG;AACzC,MAAI,UAAUE,SAAQ,GAAG;AACzB,aAAS;AACP,UAAM,QAAQ,SAAS,OAAO;AAC9B,QAAI,MAAO,QAAO;AAClB,UAAM,SAASC,SAAQ,OAAO;AAC9B,QAAI,aAAa,UAAa,YAAY,YAAY,WAAW,QAAS;AAC1E,cAAU;AAAA,EACZ;AACA,SAAO,EAAE,MAAM,OAAO,UAAU,oCAAoC;AACtE;AAGA,SAAS,SAAS,KAAiD;AACjE,QAAM,WAAW,wBAAwB,GAAG;AAC5C,QAAM,OAAO,UAAU,MAAM,uBAAuB,IAAI,CAAC;AACzD,MAAI,YAAY,KAAM,QAAO,EAAE,MAAM,UAAU,sBAAsB,QAAQ,oBAAoB;AAEjG,aAAW,CAAC,SAAS,KAAK,KAAK,cAAc;AAC3C,UAAM,QAAQ,MAAM,KAAK,CAAC,SAASC,YAAWC,MAAK,KAAK,IAAI,CAAC,CAAC;AAC9D,QAAI,MAAO,QAAO,EAAE,MAAM,SAAS,UAAU,MAAM;AAAA,EACrD;AACA,SAAO;AACT;AAMO,SAAS,8BAA8B,SAAiC;AAC7E,QAAM,WAAW,qBAAqB,OAAO;AAC7C,MAAI,SAAS,SAAS,SAAS,SAAS,SAAS,OAAQ,QAAO,SAAS;AACzE,QAAM,IAAI,+BAA+B,QAAQ;AACnD;AAGO,IAAM,8BAAN,cAA0C,MAAM;AAAA,EACrD,YAAY,QAAgB,UAAkC;AAC5D;AAAA,MACE,6CAA6C,MAAM,0CAC7C,SAAS,QAAQ;AAAA,IACzB;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,qBAAqB;AAC3B,IAAM,gBAAgB,oBAAI,IAAY;AAMtC,eAAsB,mBAAmB,SAAiB,UAAiD;AACzG,QAAM,MAAMH,SAAQ,OAAO;AAC3B,MAAI,cAAc,IAAI,GAAG,EAAG;AAE5B,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,MAAM,WAAW,QAAQ,CAAC,WAAW,GAAG,EAAE,KAAK,SAAS,WAAW,mBAAmB,CAAC;AACtG,QAAI,OAAO,SAAU,UAAS;AAAA,aACrB,OAAO,aAAa,GAAG;AAC9B,YAAM,OAAO,UAAU,OAAO,MAAM,KAAK,UAAU,OAAO,MAAM;AAChE,eAAS,mCAAmC,OAAO,QAAQ,KAAK,IAAI;AAAA,IACtE;AAAA,EACF,QAAQ;AACN,aAAS;AAAA,EACX;AACA,MAAI,WAAW,OAAW,OAAM,IAAI,4BAA4B,QAAQ,QAAQ;AAChF,gBAAc,IAAI,GAAG;AACvB;AAMA,eAAsB,+BAA+B,SAA0C;AAC7F,QAAM,UAAU,8BAA8B,OAAO;AACrD,MAAI,YAAY,OAAQ,OAAM,mBAAmB,SAAS,qBAAqB,OAAO,CAAC;AACvF,SAAO;AACT;AAEA,SAAS,UAAU,MAAsB;AACvC,SAAO,KAAK,MAAM,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,KAAK,KAAK;AACrE;AAEA,SAAS,wBAAwB,SAAqC;AACpE,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,aAAaG,MAAK,SAAS,cAAc,GAAG,MAAM,CAAC,GAAG;AAC/E,WAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,EAC7C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AGtIA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,WAAAC,UAAS,QAAAC,OAAM,YAAAC,WAAU,WAAAC,gBAAe;AACjD,OAAO,mBAAmB;;;ACJ1B,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,QAAAC,aAAY;AACrB,SAAS,OAAO,UAAU,OAAO,qBAAqB;AAG/C,IAAM,sBAAsB;AAanC,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,QAAQ,OAAqC;AACpD,QAAM,MAAM,oBAAI,IAAoB;AACpC,MAAI,SAAS,KAAK,GAAG;AACnB,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,UAAI,OAAO,UAAU,SAAU,KAAI,IAAI,MAAM,KAAK;AAAA,IACpD;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,kBAAkB,SAA4C;AAC5E,QAAM,OAAOA,MAAK,SAAS,mBAAmB;AAC9C,MAAI;AACJ,MAAI;AACF,WAAO,MAAMD,cAAa,MAAM,MAAM,CAAC;AAAA,EACzC,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,SAAS,QAAQ,CAAC,SAAS,IAAI,EAAG,QAAO;AAC7C,QAAM,MAAO,QAAQ,CAAC;AAEtB,QAAM,WAAW,MAAM,QAAQ,IAAI,QAAQ,IAAI,IAAI,SAAS,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAAI,CAAC;AAEjH,QAAM,WAAW,oBAAI,IAAiC;AACtD,QAAM,QAAQ,SAAS,IAAI,QAAQ,IAAI,IAAI,WAAW,CAAC;AACvD,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,KAAK,EAAG,UAAS,IAAI,MAAM,QAAQ,OAAO,CAAC;AACxF,QAAM,cAAc,SAAS,IAAI,OAAO;AACxC,QAAM,kBAAkB,SAAS,MAAM,OAAO;AAC9C,MAAI,YAAa,UAAS,IAAI,WAAW,QAAQ,IAAI,OAAO,CAAC;AAE7D,SAAO,EAAE,MAAM,UAAU,UAAU,yBAAyB,eAAe,gBAAgB;AAC7F;AAMO,SAAS,gBAAgB,QAAgB,SAAiB,MAAc,UAA0B;AACvG,QAAM,MAAM,cAAc,MAAM;AAChC,QAAM,UAAU,YAAY,YAAY,CAAC,IAAI,IAAI,WAAW,IAAI,GAAG,IAAI,MAAM,CAAC,YAAY,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,YAAY,OAAO,GAAG,IAAI,CAAC;AAEtJ,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,MAAM,MAAM,EAAG;AACpB,UAAM,OAAO,OAAO,IAAI,MAAM,IAAI;AAClC,QAAI,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,MAAO;AACpC,UAAM,SAAS;AACf,UAAM,CAAC,OAAO,GAAG,IAAI,OAAO;AAC5B,UAAM,QAAQ,OAAO,SAAS,iBAAiB,MAAM,OAAO,SAAS,iBAAiB,MAAM;AAC5F,WAAO,OAAO,MAAM,GAAG,KAAK,IAAI,QAAQ,WAAW,QAAQ,OAAO,MAAM,GAAG;AAAA,EAC7E;AACA,QAAM,IAAI,MAAM,iBAAiB,IAAI,iBAAiB,OAAO,QAAQ,mBAAmB,GAAG;AAC7F;;;ADhEA,SAAS,SAAS,UAAuB;AACvC,MAAI;AACF,WAAO,KAAK,MAAME,cAAa,UAAU,MAAM,CAAC;AAAA,EAClD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,4BAAN,MAA+D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpE,SAAS,UAAkB,aAAqD;AAC9E,QAAI,MAAMC,SAAQ,QAAQ;AAC1B,UAAM,WAAW,cAAcA,SAAQ,WAAW,IAAI;AACtD,eAAS;AACP,UAAI,SAASC,MAAK,KAAK,cAAc,CAAC,GAAG,cAAc,kBAAkB,GAAG,EAAG,QAAO;AACtF,YAAM,SAASC,SAAQ,GAAG;AAC1B,UAAI,QAAQ,YAAY,WAAW,IAAK,QAAO;AAC/C,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,SAA2C;AACxD,UAAM,UAAU,SAASD,MAAK,SAAS,cAAc,CAAC;AAEtD,UAAM,UAA2B;AAAA,MAC/B;AAAA,QACE,IAAI,SAAS,QAAQ;AAAA,QACrB,MAAM,SAAS,QAAQ;AAAA,QACvB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,SAAS,OAAO,SAAS,YAAY,WAAW,QAAQ,UAAU;AAAA,MACpE;AAAA,IACF;AAGA,UAAM,WACJ,qBAAqB,OAAO,EAAE,SAAS,SAAS,kBAAkB,OAAO,GAAG,WAAW,SAAS;AAClG,QAAI,CAAC,YAAa,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW,EAAI,QAAO;AAE5E,QAAI;AACJ,QAAI;AACF,mBAAa,MAAM,cAAc,EAAE,KAAK,SAAS,KAAK,EAAE,GAAG,SAAS,YAAY,SAAS,EAAE,CAAC;AAAA,IAC9F,QAAQ;AAGN,aAAO;AAAA,IACT;AAEA,eAAW,CAAC,MAAM,IAAI,KAAK,YAAY;AACrC,YAAM,MAAM,SAASA,MAAK,MAAM,cAAc,CAAC;AAC/C,cAAQ,KAAK;AAAA,QACX,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA,SAASE,UAAS,SAAS,IAAI,EAAE,QAAQ,OAAO,GAAG;AAAA,QACnD,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,SAAS,OAAO,KAAK,YAAY,WAAW,IAAI,UAAU;AAAA,MAC5D,CAAC;AAAA,IACH;AAEA,YAAQ,KAAK,CAAC,GAAG,MAAO,EAAE,SAAS,KAAK,EAAE,SAAS,IAAI,EAAE,QAAQ,cAAc,EAAE,OAAO,CAAE;AAC1F,WAAO;AAAA,EACT;AACF;;;AElFA,OAAOC,aAAY;;;ACsBZ,SAAS,oBAAoB,SAAmD;AACrF,QAAM,QAAQ,oBAAI,IAA2B;AAC7C,aAAW,UAAU,SAAS;AAC5B,UAAM,MAAM,OAAO,eAAe,OAAO;AACzC,QAAI,OAAO,QAAQ,QAAS,OAAM,IAAI,KAAK,MAAM;AAAA,EACnD;AACA,SAAO;AACT;AAEO,SAAS,eACd,YACA,WACA,SACkB;AAClB,QAAM,SAAS,QAAQ,UAAU,IAAI,UAAU;AAC/C,MAAI,QAAQ;AACV,WAAO,EAAE,MAAM,aAAa,UAAU,OAAO,IAAI,eAAe,OAAO,QAAQ;AAAA,EACjF;AAEA,MAAI,qBAAqB,YAAY,WAAW,QAAQ,cAAc,GAAG;AACvE,WAAO,EAAE,MAAM,WAAW,WAAW,iBAAiB;AAAA,EACxD;AAEA,MAAI,cAAc,SAAS,QAAQ,kBAAkB;AACnD,UAAM,QAAQ,WAAW,UAAU;AACnC,UAAM,WAAW,QAAQ,QAAQ,iBAAiB,IAAI,KAAK,IAAI;AAC/D,QAAI,SAAU,QAAO,EAAE,MAAM,WAAW,WAAW,mBAAmB,SAAS;AAAA,EACjF;AAEA,SAAO,EAAE,MAAM,SAAS;AAC1B;AAaO,SAAS,qBACd,YACA,WACA,gBACS;AAET,MAAI,cAAc,WAAW,cAAc,UAAU;AACnD,UAAM,UAAU,WAAW,MAAM,GAAG,EAAE,CAAC,KAAK;AAC5C,WAAO,eAAe,KAAK,CAAC,UAAU;AACpC,YAAM,SAAS,MAAM,QAAQ,MAAM,EAAE,EAAE,QAAQ,WAAW,EAAE;AAC5D,aAAO,OAAO,SAAS,MAAM,YAAY,UAAU,QAAQ,WAAW,GAAG,MAAM,GAAG;AAAA,IACpF,CAAC;AAAA,EACH;AAEA,SAAO,eAAe,KAAK,CAAC,UAAU;AACpC,QAAI,MAAM,WAAW,GAAG,GAAG;AACzB,YAAM,QAAQ,MAAM,QAAQ,QAAQ,EAAE;AACtC,aAAO,WAAW,WAAW,GAAG,KAAK,GAAG;AAAA,IAC1C;AACA,QAAI,MAAM,SAAS,GAAG,EAAG,QAAO,WAAW,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AACxE,WAAO,eAAe;AAAA,EACxB,CAAC;AACH;AAGO,SAAS,WAAW,MAAkC;AAC3D,MAAI,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO;AAClC,QAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,SAAO,QAAQ,IAAI,KAAK,MAAM,GAAG,KAAK,IAAI;AAC5C;;;AChFO,SAAS,UAAU,KAAqB;AAC7C,SAAO,qBAAqB,GAAG,EAAE,SAAS,SAAS,SAAS;AAC9D;AAEO,IAAM,WAAW;AAAA;AAAA,EAEtB,SAAS,CAAC,MACR,MAAM,SAAS,EAAE,SAAS,QAAQ,MAAM,CAAC,WAAW,sBAAsB,EAAE,IAAI,EAAE,SAAS,OAAO,MAAM,CAAC,SAAS,EAAE;AAAA;AAAA,EAEtH,SAAS,CAAC,MACR,MAAM,SAAS,EAAE,SAAS,QAAQ,MAAM,CAAC,WAAW,mBAAmB,EAAE,IAAI,EAAE,SAAS,OAAO,MAAM,CAAC,SAAS,EAAE;AAAA;AAAA,EAEnH,QAAQ,CAAC,MACP,MAAM,SACF,EAAE,SAAS,QAAQ,MAAM,CAAC,WAAW,qBAAqB,iBAAiB,EAAE,IAC7E,EAAE,SAAS,OAAO,MAAM,CAAC,IAAI,EAAE;AAAA,EACrC,MAAM,CAAC,GAAW,MAAc,WAAgC,EAAE,SAAS,GAAG,MAAM,CAAC,QAAQ,MAAM,OAAO,QAAQ,EAAE;AAAA,EACpH,QAAQ,CAAC,OAA4B,EAAE,SAAS,GAAG,MAAM,CAAC,UAAU,QAAQ,QAAQ,EAAE;AACxF;;;ACnBA,IAAM,mBAAmB;AAGzB,IAAM,mBAAmB,oBAAI,IAAI,CAAC,sBAAsB,sBAAsB,wBAAwB,YAAY,CAAC;AAE5G,IAAM,kBAAN,MAAsB;AAAA,EACV,QAAQ,oBAAI,IAAwC;AAAA;AAAA,EAGrE,KAAK,KAAyC;AAC5C,QAAI,UAAU,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,SAAS;AACZ,gBAAU,WAAW,GAAG;AACxB,WAAK,MAAM,IAAI,KAAK,OAAO;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,YAAY,aAAqB,KAA8B;AACnE,UAAM,SAAS,MAAM,KAAK,KAAK,GAAG;AAClC,UAAM,QAAQ,WAAW,WAAW;AACpC,WAAQ,SAAS,OAAO,iBAAiB,IAAI,KAAK,KAAM,OAAO;AAAA,EACjE;AACF;AAGO,SAAS,oBAAoB,KAAsB;AACxD,MAAI;AACF,WAAO,iBAAiB,IAAI,IAAI,IAAI,GAAG,EAAE,SAAS,YAAY,CAAC;AAAA,EACjE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,eAAe,MAAkD;AAC/E,QAAM,mBAAmB,oBAAI,IAAoB;AACjD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,UAAM,QAAQ,IAAI,MAAM,qBAAqB;AAC7C,QAAI,SAAS,OAAO,UAAU,YAAY,MAAO,kBAAiB,IAAI,MAAM,CAAC,GAAI,KAAK;AAAA,EACxF;AACA,QAAM,WAAW,OAAO,KAAK,aAAa,YAAY,KAAK,WAAW,KAAK,WAAW;AACtF,SAAO,EAAE,UAAU,iBAAiB;AACtC;AAEA,eAAe,WAAW,KAAyC;AACjE,MAAI;AACF,UAAM,EAAE,SAAS,KAAK,IAAI,SAAS,OAAO,UAAU,GAAG,CAAC;AACxD,UAAM,SAAS,MAAM,WAAW,SAAS,MAAM,EAAE,KAAK,WAAW,KAAO,CAAC;AACzE,QAAI,OAAO,aAAa,EAAG,QAAO,eAAe,CAAC,CAAC;AACnD,WAAO,eAAe,KAAK,MAAM,OAAO,MAAM,CAA4B;AAAA,EAC5E,QAAQ;AAGN,WAAO,eAAe,CAAC,CAAC;AAAA,EAC1B;AACF;;;AH/DA,IAAM,oBAAoB;AAG1B,IAAM,eAAe;AAGd,SAAS,mBAAmB,MAAuB;AACxD,SAAO,KAAK,UAAU,OAAO,aAAa,KAAK,IAAI;AACrD;AAEO,IAAM,qBAAN,MAAiD;AAAA,EACtD,YAAqB,SAAS,IAAI,gBAAgB,GAAG;AAAhC;AAAA,EAAiC;AAAA,EAAjC;AAAA,EAErB,MAAM,gBAAgB,YAAkC,KAAwC;AAC9F,UAAM,MAAM,MAAM,KAAK,OAAO,YAAY,WAAW,YAAY,GAAG;AACpE,WAAO,EAAE,KAAK,UAAU,oBAAoB,GAAG,EAAE;AAAA,EACnD;AAAA,EAEA,MAAM,iBACJ,YACA,UAA0B,UAC1B,MAAM,QAAQ,IAAI,GACM;AACxB,QAAI,CAAC,mBAAmB,WAAW,UAAU,EAAG,QAAO;AAEvD,QAAI,YAAY,UAAU;AAExB,YAAM,SAAS,MAAM,KAAK,KAAK,WAAW,YAAY,oBAAoB,GAAG;AAC7E,UAAI,OAAO,WAAW,YAAYC,QAAO,MAAM,MAAM,KAAKA,QAAO,WAAW,MAAM,MAAM,MAAM;AAC5F,eAAO;AAAA,MACT;AAGA,YAAM,YAAY,MAAM,KAAK,eAAe,YAAY,GAAG,GAAG;AAAA,QAC5D,CAAC,MAAMA,QAAO,MAAM,CAAC,KAAKA,QAAO,WAAW,CAAC,MAAM;AAAA,MACrD;AACA,aAAO,SAAS,SAAS,IAAIA,QAAO,MAAM,QAAQ,EAAE,CAAC,IAAK;AAAA,IAC5D;AAGA,UAAM,UAAU,MAAM,KAAK,KAAK,WAAW,YAAY,WAAW,GAAG;AACrE,WAAO,OAAO,YAAY,YAAY,UAAU,UAAU;AAAA,EAC5D;AAAA,EAEA,MAAM,eAAe,YAAkC,MAAM,QAAQ,IAAI,GAAsB;AAC7F,QAAI,CAAC,mBAAmB,WAAW,UAAU,EAAG,QAAO,CAAC;AACxD,UAAM,WAAW,MAAM,KAAK,KAAK,WAAW,YAAY,YAAY,GAAG;AACvE,UAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI,WAAW,WAAW,CAAC,QAAQ,IAAI,CAAC;AAC3E,WAAO,KAAK,IAAI,MAAM,EAAE,QAAQ;AAAA,EAClC;AAAA;AAAA,EAGA,MAAgB,KAAK,MAAc,OAAe,KAA+B;AAC/E,QAAI;AACF,YAAM,EAAE,SAAS,KAAK,IAAI,SAAS,KAAK,UAAU,GAAG,GAAG,MAAM,KAAK;AACnE,YAAM,SAAS,MAAM,WAAW,SAAS,MAAM;AAAA,QAC7C;AAAA,QACA,WAAW;AAAA,MACb,CAAC;AACD,UAAI,OAAO,aAAa,KAAK,CAAC,OAAO,OAAO,KAAK,EAAG,QAAO;AAC3D,aAAO,KAAK,MAAM,OAAO,MAAM;AAAA,IACjC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AI9DA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,QAAAC,aAAY;AACrB,OAAOC,aAAY;;;ACVnB,eAAsB,UACpB,OACA,aACA,IACc;AACd,QAAM,UAAU,IAAI,MAAS,MAAM,MAAM;AACzC,MAAI,OAAO;AAEX,iBAAe,SAAwB;AACrC,WAAO,OAAO,MAAM,QAAQ;AAC1B,YAAM,QAAQ;AACd,cAAQ,KAAK,IAAI,MAAM,GAAG,MAAM,KAAK,CAAE;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,aAAa,MAAM,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC;AAC1F,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;;;ACdO,SAAS,mBAAmB,OAA2B;AAC5D,MAAI,MAAM,WAAW,YAAY,EAAG,QAAO,EAAE,UAAU,aAAa,MAAM,MAAM,MAAM,aAAa,MAAM,EAAE;AAC3G,MAAI,MAAM,WAAW,UAAU,EAAG,QAAO,EAAE,UAAU,WAAW,MAAM,MAAM,MAAM,WAAW,MAAM,EAAE;AACrG,SAAO,EAAE,UAAU,QAAW,MAAM,MAAM;AAC5C;;;AFwBA,IAAM,cAAc;AACpB,IAAM,aAAqC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,EAAE;AAUnE,IAAM,uBAAN,MAA2D;AAAA,EAChE,YACmB,UACA,QACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAGnB,MAAM,KAAK,QAAuB,SAA2C;AAC3E,UAAM,UAAU,MAAM,+BAA+B,QAAQ,OAAO;AACpE,UAAM,OAAO,YAAY;AAEzB,QAAI;AACJ,QAAI;AACF,YAAM,KAAK,MAAMC,cAAaC,MAAK,OAAO,MAAM,cAAc,GAAG,MAAM,CAAC;AAAA,IAC1E,QAAQ;AACN,aAAO,EAAE,YAAY,CAAC,GAAG,SAAS,CAAC,EAAE;AAAA,IACvC;AAEA,UAAM,YAAY,MAAM,KAAK,OAAO,KAAK,QAAQ,OAAO;AACxD,UAAM,gBAAgB;AAAA,MACpB,WAAW,QAAQ;AAAA,MACnB,gBAAgB,QAAQ;AAAA;AAAA;AAAA,MAGxB,kBAAkB,IAAI;AAAA,QACpB,CAAC,GAAG,UAAU,gBAAgB,EAAE,OAAO,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,oBAAoB,GAAG,CAAC;AAAA,MAC/E;AAAA,IACF;AAEA,UAAM,gBAAgB,OAAO,kBAAkB,QAAQ,OAAO,IAAI;AAElE,UAAM,WAAW,MAAM,UAAU,qBAAqB,GAAG,GAAG,aAAa,OAAO,QAA0B;AACxG,YAAM,SAAS,eAAe,IAAI,MAAM,OAAO,aAAa;AAC5D,UAAI,OAAO,SAAS,aAAa;AAC/B,cAAM,SAAS,QAAQ,UAAU,IAAI,IAAI,IAAI;AAC7C,YAAI,QAAQ,kBAAkB,IAAI,KAAK,KAAK,mBAAmB,IAAI,KAAK,EAAE,aAAa,QAAW;AAEhG,iBAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,aAAa,QAAQ,cAAc,QAAQ,IAAI,MAAM,EAAE;AAAA,QAC3G;AACA,cAAM,YAAY,SAAS,mBAAmB,KAAK,QAAQ,QAAQ,IAAI,IAAI;AAC3E,eAAO,YAAY,EAAE,UAAU,IAAI;AAAA,MACrC;AACA,UAAI,QAAQ,mBAAmB,IAAI,KAAK,EAAE,aAAa,WAAW;AAChE,eAAO,KAAK,eAAe,KAAK,QAAQ,SAAS,OAAO,MAAM,aAAa;AAAA,MAC7E;AACA,aAAO,KAAK,gBAAgB,KAAK,QAAQ,OAAO;AAAA,IAClD,CAAC;AAED,UAAM,aAAgC,CAAC;AACvC,UAAM,UAA+B,CAAC;AACtC,eAAW,WAAW,UAAU;AAC9B,UAAI,CAAC,QAAS;AACd,UAAI,eAAe,QAAS,YAAW,KAAK,QAAQ,SAAS;AAAA,UACxD,SAAQ,KAAK,QAAQ,OAAO;AAAA,IACnC;AAEA,eAAW,KAAK,CAAC,GAAG,OAAO,WAAW,EAAE,IAAI,KAAK,MAAM,WAAW,EAAE,IAAI,KAAK,EAAE;AAC/E,WAAO,EAAE,YAAY,QAAQ;AAAA,EAC/B;AAAA;AAAA,EAGA,MAAc,eACZ,KACA,QACA,SACA,YACA,eACkB;AAClB,UAAM,cAAc,mBAAmB,IAAI,KAAK,EAAE,QAAQ;AAC1D,UAAM,aAAa,CAAC,YAA6B;AAAA,MAC/C,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,sBAAsB,OAAO;AAAA,IAC7F;AACA,QAAI,CAAC,cAAe,QAAO,WAAW,kDAAkD;AACxF,QAAI,gBAAgB,aAAa,cAAc,yBAAyB;AACtE,aAAO,WAAW,mEAAmE;AAAA,IACvF;AACA,UAAM,UAAU,cAAc,SAAS,IAAI,WAAW;AACtD,QAAI,CAAC,QAAS,QAAO,WAAW,eAAe,WAAW,GAAG;AAC7D,UAAM,QAAQ,QAAQ,IAAI,IAAI,IAAI;AAClC,QAAI,UAAU,OAAW,QAAO,WAAW,iBAAiB,IAAI,IAAI,iBAAiB,WAAW,GAAG;AAEnG,UAAM,cAAkC;AAAA,MACtC,MAAM,cAAc;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,aAAa;AAAA,IACf;AACA,UAAM,aAAa,oBAAoB,SAAS,YAAY,IAAI,MAAM,WAAW;AACjF,WAAO,KAAK,gBAAgB,EAAE,GAAG,KAAK,MAAM,GAAG,QAAQ,SAAS;AAAA,MAC9D;AAAA,MACA,GAAI,WAAW,SAAS,IAAI,EAAE,WAAW,IAAI,CAAC;AAAA,IAChD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAc,gBACZ,KACA,QACA,SACA,QAAkC,CAAC,GACjB;AAElB,QAAI,CAAC,kBAAkB,IAAI,KAAK,EAAG,QAAO;AAE1C,QAAI,CAAC,mBAAmB,IAAI,IAAI,GAAG;AACjC,aAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,eAAe,EAAE;AAAA,IAC1F;AAEA,UAAM,aAAmC,EAAE,YAAY,IAAI,MAAM,UAAU,IAAI,MAAM,WAAW,MAAM;AAEtG,QAAI,iBAAiB;AACrB,QAAI,OAAO,SAAS,WAAW;AAG7B,YAAM,WAAW,MAAM,KAAK,SAAS,gBAAgB,YAAY,QAAQ,OAAO;AAChF,UAAI,SAAS,UAAU;AACrB,eAAO;AAAA,UACL,SAAS;AAAA,YACP,YAAY,IAAI;AAAA,YAChB,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,QAAQ,SAAS;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AACA,uBAAiB,EAAE,GAAG,QAAQ,UAAU,SAAS,IAAI;AAAA,IACvD;AAEA,UAAM,SAAS,MAAM,KAAK,SAAS,iBAAiB,YAAY,QAAQ,SAAS,QAAQ,OAAO;AAChG,QAAI,CAAC,QAAQ;AACX,aAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,gBAAgB,EAAE;AAAA,IAC3F;AAEA,UAAM,eAAeC,QAAO,WAAW,IAAI,KAAK,GAAG;AACnD,QAAI,CAAC,gBAAgB,CAACA,QAAO,MAAM,MAAM,KAAK,CAACA,QAAO,GAAG,QAAQ,YAAY,EAAG,QAAO;AAEvF,UAAM,MAAMA,QAAO,WAAW,MAAM,IAAI,qBAAqB,MAAM,KAAK,QAAQ;AAChF,UAAM,OAAO,aAAa,cAAc,MAAM;AAC9C,WAAO;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA,cAAc,IAAI;AAAA,QAClB;AAAA,QACA;AAAA,QACA,UAAU,GAAG,YAAY,IAAI,KAAK,CAAC,GAAG,MAAM;AAAA,QAC5C;AAAA,QACA,OAAO,IAAI;AAAA,QACX,UAAU,SAAS;AAAA,QACnB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,cAAc,QAAQ;AAAA,QACtB,eAAe;AAAA,QACf,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAQO,IAAM,sBAAsB,CAAC,gBAAgB,wBAAwB,iBAAiB;AAQ7F,SAAS,qBAAqB,KAAgC;AAC5D,QAAM,OAAO,oBAAI,IAAgC;AACjD,aAAW,WAAW,qBAAqB;AACzC,UAAM,QAAQ,YAAY,oBAAoB,QAAQ;AACtD,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,OAAO,KAAK,CAAC,CAAC,GAAG;AAC9D,UAAI,OAAO,UAAU,SAAU,MAAK,IAAI,MAAM,EAAE,MAAM,OAAO,MAAM,CAAC;AAAA,IACtE;AAAA,EACF;AACA,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B;AAGO,SAAS,kBAAkB,OAAwB;AACxD,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,MAAM,YAAY,OAAO,QAAQ,YAAY,MAAM,IAAK,QAAO;AAC/E,SAAOA,QAAO,WAAW,OAAO,MAAM;AACxC;AAQO,SAAS,mBACd,KACA,QACA,QACA,OAAO,OACiB;AAExB,QAAM,QAAQ,OAAO,mBAAmB,IAAI,KAAK,IAAI,EAAE,UAAU,QAAW,MAAM,IAAI,MAAM;AAC5F,QAAM,QAAQ,MAAM,aAAa,cAAc,MAAM,OAAO,IAAI;AAChE,QAAM,WAAW,MAAM,aAAa,cAAc,eAAe;AAEjE,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,SAAS,CAACA,QAAO,MAAM,KAAK,KAAK,CAAC,kBAAkB,KAAK,EAAG,QAAO;AACxE,MAAIA,QAAO,UAAU,OAAO,OAAO,EAAE,mBAAmB,KAAK,CAAC,EAAG,QAAO;AAExE,QAAM,eAAeA,QAAO,WAAW,KAAK,GAAG,WAAW;AAC1D,QAAM,OAAO,aAAa,cAAc,KAAK;AAC7C,QAAM,MAAMA,QAAO,WAAW,KAAK,IAAI,qBAAqB,KAAK,KAAK,QAAQ;AAE9E,SAAO;AAAA,IACL,YAAY,EAAE,YAAY,IAAI,MAAM,UAAU,IAAI,MAAM,WAAW,MAAM;AAAA,IACzE,cAAc,IAAI;AAAA,IAClB;AAAA,IACA,QAAQ;AAAA,IACR,UAAU,GAAG,QAAQ,GAAG,YAAY,KAAK,CAAC,GAAG,KAAK;AAAA,IAClD;AAAA,IACA,OAAO,IAAI;AAAA,IACX,UAAU,SAAS;AAAA,IACnB;AAAA,IACA,QAAQ;AAAA,IACR,mBAAmB,CAAC,KAAK;AAAA,IACzB,cAAc,QAAQ;AAAA,IACtB,eAAe;AAAA,EACjB;AACF;AAGA,SAAS,oBAAoB,SAAsB,UAAkB,MAAc,aAA+B;AAChH,QAAM,QAAkB,CAAC;AACzB,aAAW,UAAU,QAAQ,UAAU,OAAO,GAAG;AAC/C,QAAI,OAAO,SAAS,SAAU;AAC9B,QAAI;AACJ,QAAI;AACF,YAAM,KAAK,MAAMF,cAAaC,MAAK,OAAO,MAAM,cAAc,GAAG,MAAM,CAAC;AAAA,IAC1E,QAAQ;AACN;AAAA,IACF;AACA,UAAM,MAAM,qBAAqB,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACjE,QAAI,CAAC,OAAO,mBAAmB,IAAI,KAAK,EAAE,aAAa,UAAW;AAClE,SAAK,mBAAmB,IAAI,KAAK,EAAE,QAAQ,eAAe,YAAa;AACvE,UAAM,KAAK,OAAO,EAAE;AAAA,EACtB;AACA,SAAO;AACT;;;AGpSA,SAAS,gBAAAE,eAAc,qBAAqB;AAC5C,SAAS,QAAAC,OAAM,YAAAC,iBAAgB;;;ACmFxB,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,SAA0B,QAAiB;AACrD,UAAM,OAAO;AADuB;AAEpC,SAAK,OAAO;AAAA,EACd;AAAA,EAHsC;AAIxC;;;ACvFA,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,QAAAC,aAAY;AAad,SAAS,aAAa,SAAuC;AAClE,QAAM,OAAOA,MAAK,SAAS,mBAAmB;AAC9C,MAAI,CAACF,YAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,WAAO,KAAK,MAAMC,cAAa,MAAM,MAAM,CAAC;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYO,SAAS,kCACd,UACA,eACA,OACU;AACV,QAAM,WAAW,SAAS,YAAY,CAAC;AACvC,QAAM,SAAS,gBAAgB,GAAG,aAAa,MAAM;AACrD,QAAM,aAAuB,CAAC;AAE9B,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,SAAS,GAAG,MAAM,gBAAgB,IAAI,EAAE,KAAK,SAAS,gBAAgB,IAAI,EAAE;AAC1F,QAAI,CAAC,OAAO;AACV,iBAAW,KAAK,GAAG,IAAI,oCAAoC;AAAA,IAC7D,WAAW,CAAC,MAAM,MAAM;AACtB,YAAM,SAAS,MAAM,YAAY;AACjC,iBAAW,KAAK,GAAG,IAAI,oBAAoB,MAAM,2CAA2C;AAAA,IAC9F;AAAA,EACF;AACA,SAAO;AACT;;;AC3DO,IAAM,mBAAmB;AAEhC,IAAM,SAAS,CAAC,QAAQ,OAAO,YAAY,QAAQ,UAAU;AAOtD,SAAS,YAAY,QAA8B;AACxD,SAAO,EAAE,SAAS,oCAAoC,MAAM,KAAK,UAAU,OAAO;AACpF;AAGO,SAAS,eAAe,QAA8B;AAC3D,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,MAAM;AAAA,EAC1B,QAAQ;AACN,WAAO,YAAY,+BAA+B;AAAA,EACpD;AACA,QAAM,SAAS,MAAM,UAAU;AAC/B,MAAI,UAAU,OAAO,WAAW,UAAU;AACxC,UAAM,QAAkB,CAAC;AACzB,QAAI,QAAQ;AACZ,eAAW,SAAS,QAAQ;AAC1B,YAAM,IAAI,OAAO,OAAO,KAAK,CAAC,KAAK;AACnC,eAAS;AACT,UAAI,IAAI,EAAG,OAAM,KAAK,GAAG,CAAC,IAAI,KAAK,EAAE;AAAA,IACvC;AACA,QAAI,UAAU,EAAG,QAAO,EAAE,SAAS,mCAAmC,UAAU,QAAQ;AACxF,WAAO;AAAA,MACL,SAAS,GAAG,KAAK,IAAI,UAAU,IAAI,kBAAkB,iBAAiB,KAAK,MAAM,KAAK,IAAI,CAAC;AAAA,MAC3F,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,eAAe,MAAM,OAAO;AAClC,MAAI,OAAO,iBAAiB,YAAY,aAAc,QAAO,YAAY,YAAY;AACrF,SAAO,YAAY,+BAA+B;AACpD;;;AClCA,SAAS,cAAAE,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,QAAAC,aAAY;AACrB,SAAS,SAAAC,cAAa;AAetB,IAAM,WAAW,CAAC,gBAAgB,mBAAmB,sBAAsB;AAEpE,SAAS,iBAAiB,SAA+B;AAC9D,QAAM,OAAOD,MAAK,SAAS,gBAAgB;AAC3C,MAAI,CAACF,YAAW,IAAI,EAAG,QAAO,EAAE,MAAM,UAAU;AAChD,MAAI;AACJ,MAAI;AACF,WAAOG,OAAMF,cAAa,MAAM,MAAM,CAAC;AAAA,EACzC,QAAQ;AACN,WAAO,EAAE,MAAM,aAAa;AAAA,EAC9B;AACA,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,MAAM,QAAQ,IAAI,EAAG,QAAO,EAAE,MAAM,aAAa;AAElG,QAAM,kBAAkB,OAAO,KAAK,mBAAmB,EAAE;AACzD,MAAI,CAAC,WAAW,KAAK,eAAe,EAAG,QAAO,EAAE,MAAM,eAAe,gBAAgB;AACrF,QAAM,YAAY,KAAK,aAAa,CAAC;AACrC,MAAI,OAAO,cAAc,YAAY,MAAM,QAAQ,SAAS,EAAG,QAAO,EAAE,MAAM,aAAa;AAC3F,SAAO,EAAE,MAAM,MAAM,UAAsC;AAC7D;AAOO,SAAS,6BACd,UACA,eACA,OACU;AACV,UAAQ,SAAS,MAAM;AAAA,IACrB,KAAK;AACH,aAAO,CAAC,+DAA+D;AAAA,IACzE,KAAK;AACH,aAAO,CAAC,sEAAsE;AAAA,IAChF,KAAK;AACH,aAAO;AAAA,QACL,uCAAuC,SAAS,eAAe;AAAA,MACjE;AAAA,EACJ;AAEA,QAAM,WAAW,SAAS,UAAU,kBAAkB,KAAK,MAAM,aAAa,KAAK,CAAC;AACpF,QAAM,aAAuB,CAAC;AAC9B,aAAW,QAAQ,OAAO;AACxB,QAAI;AACJ,eAAW,WAAW,UAAU;AAC9B,cAAQ,SAAS,OAAO,IAAI,IAAI;AAChC,UAAI,MAAO;AAAA,IACb;AACA,QAAI,CAAC,MAAO,YAAW,KAAK,GAAG,IAAI,iCAAiC;AAAA,aAC3D,CAAC,OAAO,MAAM,OAAO,EAAE,WAAW,OAAO,GAAG;AACnD,iBAAW,KAAK,GAAG,IAAI,iBAAiB,MAAM,OAAO,2CAA2C;AAAA,IAClG;AAAA,EACF;AACA,SAAO;AACT;;;AJnDA,IAAM,qBAAqB,KAAK;AAGhC,SAAS,eAAe,SAAiB,QAA2B;AAClE,SAAO,YAAY,SAAS,KAAK,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM,EAAE,IAAI,KAAK,OAAO,UAAU,OAAO,MAAM;AAC9G;AAEO,IAAM,oBAAN,MAAyD;AAAA,EAC9D,cAAc,QAAuB,SAA2B;AAC9D,QAAI,qBAAqB,OAAO,EAAE,SAAS,QAAQ;AACjD,aAAO;AAAA,QACLG,MAAK,OAAO,MAAM,cAAc;AAAA,QAChCA,MAAK,SAAS,cAAc;AAAA,QAC5BA,MAAK,SAAS,gBAAgB;AAAA,QAC9BA,MAAK,SAAS,qBAAqB;AAAA,MACrC;AAAA,IACF;AACA,WAAO;AAAA,MACLA,MAAK,OAAO,MAAM,cAAc;AAAA,MAChCA,MAAK,SAAS,cAAc;AAAA,MAC5BA,MAAK,SAAS,mBAAmB;AAAA,MACjCA,MAAK,SAAS,qBAAqB;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAM,aACJ,QACA,SACA,SACA,YACuB;AACvB,QAAI;AACJ,QAAI;AACF,gBAAU,MAAM,+BAA+B,OAAO;AAAA,IACxD,SAAS,KAAK;AACZ,UAAI,eAAe,kCAAkC,eAAe,6BAA6B;AAC/F,cAAM,IAAI,aAAa,IAAI,OAAO;AAAA,MACpC;AACA,YAAM;AAAA,IACR;AAGA,UAAM,iBAAiB,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,SAAS;AAC9E,UAAM,kBAAkB,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,SAAS;AAE/E,UAAM,UAAUA,MAAK,OAAO,MAAM,cAAc;AAChD,QAAI;AACJ,QAAI,gBAAgB,SAAS,KAAK,eAAe,WAAW,GAAG;AAC7D,UAAI;AACF,cAAM,SAASC,cAAa,SAAS,MAAM;AAC3C,mBAAW,EAAE,QAAQ,KAAK,KAAK,MAAM,MAAM,EAAE;AAAA,MAC/C,QAAQ;AACN,cAAM,IAAI,aAAa,+BAA+B,OAAO,IAAI,GAAG;AAAA,MACtE;AAAA,IACF;AAEA,QAAI,UAAU;AACZ,iBAAW,4CAAuC;AAClD,iBAAW,QAAQ,iBAAiB;AAClC,cAAM,OAAO,KAAK,WAAW;AAE7B,mBAAW,WAAW,qBAAqB;AACzC,cAAI,OAAO,SAAS,IAAI,OAAO,IAAI,IAAI,MAAM,SAAU,UAAS,IAAI,OAAO,EAAE,IAAI,IAAI,KAAK;AAAA,QAC5F;AAAA,MACF;AACA,oBAAc,SAAS,cAAc,SAAS,QAAQ,SAAS,GAAG,GAAG,MAAM;AAAA,IAC7E;AAEA,QAAI,eAAe,SAAS,GAAG;AAC7B,iBAAW,mDAA8C;AACzD,yBAAmB,cAAc;AAAA,IACnC;AAEA,UAAM,UAAU,SAAS,QAAQ,OAAO;AACxC,eAAW,WAAW,OAAO,gBAAW;AACxC,UAAM,SAAS,MAAM,WAAW,QAAQ,SAAS,QAAQ,MAAM,EAAE,KAAK,SAAS,WAAW,mBAAmB,CAAC;AAC9G,QAAI,OAAO,aAAa,GAAG;AACzB,YAAM,SAAS,OAAO,WAAW,GAAG,OAAO,uBAAuB,GAAG,OAAO;AAC5E,YAAM,IAAI,aAAa,QAAQ,eAAe,SAAS,MAAM,CAAC;AAAA,IAChE;AAEA,UAAM,WAAW,YAAY,SAAS,mBAAmB;AACzD,eAAW,+BAA+B,QAAQ,QAAG;AACrD,UAAM,sBAAsB,mBAAmB,SAAS,QAAQ,SAAS,OAAO;AAEhF,QAAI,YAAY,QAAQ;AACtB,YAAMC,SAAQ,oBAAoB,SAAS,IAAI,SAAY,MAAM,aAAa,OAAO;AACrF,aAAO;AAAA,QACL,cAAc,QAAQ;AAAA,QACtB,cAAcA,QAAO,WAAW;AAAA,QAChC,eAAeA,QAAO,YAAY;AAAA,QAClC,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM;AACnD,UAAM,QAAQ,kBAAkB,QAAQ;AACxC,UAAM,eAAe,SAAS,MAAM,iDAAiD;AAErF,WAAO;AAAA,MACL,cAAc,QAAQ;AAAA,MACtB,cAAc,MAAM;AAAA,MACpB,eAAe,MAAM;AAAA,MACrB,gBAAgB,eAAe,aAAa,CAAC,IAAI;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,SAAwB,SAAiB,YAA0D;AAE9G,UAAM,OAAO,qBAAqB,OAAO,EAAE;AAC3C,QAAI,SAAS,SAAS,SAAS,OAAQ;AAEvC,UAAM,UAAU,SAAS,QAAQ,IAAI;AACrC,eAAW,2BAA2B,IAAI,iBAAY;AACtD,UAAM,SAAS,MAAM,WAAW,QAAQ,SAAS,QAAQ,MAAM,EAAE,KAAK,SAAS,WAAW,mBAAmB,CAAC;AAC9G,QAAI,OAAO,aAAa,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,GAAG,IAAI;AAAA,QACP,SAAS,SAAS,eAAe,MAAM,MAAM,IAAI,KAAK,OAAO,MAAM;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,mBAAmB,SAAkC;AAC5D,QAAM,UAAU,oBAAI,IAAoB;AACxC,aAAW,QAAQ,SAAS;AAC1B,UAAM,cAAc,KAAK;AACzB,QAAI;AACF,UAAI,SAAS,QAAQ,IAAI,YAAY,IAAI,KAAKD,cAAa,YAAY,MAAM,MAAM;AACnF,eAAS,gBAAgB,QAAQ,YAAY,eAAe,WAAW,KAAK,WAAW,UAAU,KAAK,QAAQ;AAC9G,cAAQ,IAAI,YAAY,MAAM,MAAM;AAAA,IACtC,SAAS,KAAK;AACZ,YAAM,IAAI,aAAa,eAAe,QAAQ,IAAI,UAAU,iBAAiB,YAAY,WAAW,GAAG;AAAA,IACzG;AAAA,EACF;AACA,aAAW,CAAC,MAAM,MAAM,KAAK,QAAS,eAAc,MAAM,QAAQ,MAAM;AAC1E;AAGA,eAAe,aAAa,SAAwC;AAClE,MAAI;AACF,UAAM,SAAS,MAAM,WAAW,QAAQ,CAAC,SAAS,QAAQ,GAAG,EAAE,KAAK,SAAS,WAAW,iBAAiB,CAAC;AAC1G,QAAI,OAAO,SAAU,QAAO,YAAY,8BAA8B,mBAAmB,GAAI,UAAU;AACvG,WAAO,eAAe,OAAO,MAAM;AAAA,EACrC,QAAQ;AACN,WAAO,YAAY,+BAA+B;AAAA,EACpD;AACF;AAQA,IAAM,qBAAqB;AAOpB,SAAS,kBAAkB,QAAiE;AACjG,aAAW,QAAQ,OAAO,MAAM,OAAO,GAAG;AACxC,UAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,kBAAkB;AAClD,QAAI,SAAS,OAAO,MAAM,CAAC,CAAC,IAAI,EAAG,QAAO,EAAE,SAAS,KAAK,KAAK,GAAG,UAAU,OAAO;AAAA,EACrF;AACA,SAAO,EAAE,SAAS,mCAAmC,UAAU,QAAQ;AACzE;AAGA,SAAS,mBACP,SACA,QACA,SACA,SACU;AACV,QAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,UAAU;AACvG,MAAI,QAAQ,WAAW,EAAG,QAAO,CAAC;AAElC,QAAM,gBAAgBE,UAAS,SAAS,OAAO,IAAI,EAAE,QAAQ,OAAO,GAAG;AACvE,MAAI,YAAY,OAAQ,QAAO,6BAA6B,iBAAiB,OAAO,GAAG,eAAe,OAAO;AAE7G,QAAM,WAAW,aAAa,OAAO;AACrC,MAAI,CAAC,SAAU,QAAO,CAAC,kEAAkE;AACzF,SAAO,kCAAkC,UAAU,eAAe,OAAO;AAC3E;AAGA,SAAS,cAAc,UAAkB,OAAwB;AAC/D,QAAM,SAAS,SAAS,MAAM,eAAe,IAAI,CAAC,KAAK;AACvD,QAAM,UAAU,SAAS,SAAS,MAAM,IAAI,SAAS;AACrD,QAAM,OAAO,KAAK,UAAU,OAAO,MAAM,MAAM,EAAE,QAAQ,OAAO,OAAO;AACvE,SAAO,SAAS,SAAS,IAAI,IAAI,OAAO,UAAU;AACpD;;;AKlNA,IAAM,oBAAoB,KAAK;AAExB,IAAM,yBAAN,MAAyD;AAAA,EAC9D,MAAM,OACJ,SACA,SACA,UAA+B,CAAC,GACH;AAC7B,QAAI,UAA0B;AAC9B,QAAI,CAAC,QAAQ,cAAc;AAEzB,UAAI;AACF,kBAAU,MAAM,+BAA+B,OAAO;AAAA,MACxD,SAAS,KAAK;AACZ,YAAI,eAAe,kCAAkC,eAAe,6BAA6B;AAC/F,iBAAO,EAAE,QAAQ,QAAQ,SAAS,IAAI,SAAS,OAAO,QAAQ,eAAe,0BAA0B;AAAA,QACzG;AACA,cAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM,eACJ,YAAY,SACR,0DACA;AACN,UAAM,QAAQ,QAAQ,eAAe,QAAQ,gBAAgB;AAE7D,UAAM,SAAS,SAAS,OAAO,OAAO;AACtC,UAAM,SAAS,QAAQ,eACnB,MAAM,eAAe,QAAQ,cAAc,EAAE,KAAK,SAAS,WAAW,kBAAkB,CAAC,IACzF,MAAM,WAAW,OAAO,SAAS,OAAO,MAAM,EAAE,KAAK,SAAS,WAAW,kBAAkB,CAAC;AAEhG,QAAI,OAAO,aAAa,GAAG;AACzB,YAAM,UACJ,YAAY,UAAU,CAAC,QAAQ,eAC3B,8DACA;AACN,aAAO,EAAE,QAAQ,SAAS,SAAS,MAAM;AAAA,IAC3C;AACA,UAAM,SACJ,YAAY,UAAU,CAAC,QAAQ,eAC3B,KAAK,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM,EAAE,IACzC,KAAK,OAAO,UAAU,OAAO,MAAM;AACzC,WAAO,EAAE,QAAQ,QAAQ,SAAS,OAAO,WAAW,4BAA4B,QAAQ,MAAM;AAAA,EAChG;AACF;;;AChDO,IAAM,uBAAN,MAAwD;AAAA,EACpD,YAAuB;AAAA,EACvB,cAAc;AAAA,EAEvB,kBAAkB,SAAyB;AACzC,WAAO,qBAAqB,OAAO,EAAE;AAAA,EACvC;AAAA,EAEA,eAAe,SAAyB;AACtC,WAAO,qBAAqB,OAAO,EAAE,SAAS,SAAS,gBAAgB;AAAA,EACzE;AAAA,EACS,OAAO;AAAA,EACP,eAAe;AAAA,EACf,aAAa;AAAA,EAEb,YAAY,IAAI,0BAA0B;AAAA,EAC1C,WAAW,IAAI,mBAAmB;AAAA,EAClC,SAAS,IAAI,qBAAqB,KAAK,UAAU,KAAK,SAAS,MAAM;AAAA,EACrE,UAAU,IAAI,kBAAkB;AAAA,EAChC,WAAW,IAAI,uBAAuB;AAAA,EAE/C,aACE,QACA,GACW;AACX,WAAO;AAAA,MACL,KAAK,EAAE,KAAK,IAAI,OAAO,KAAK;AAAA,MAC5B,MAAM,EAAE,KAAK,aAAa,OAAO,SAAS;AAAA,MAC1C,KAAK,EAAE,KAAK,gBAAgB,OAAO,QAAQ;AAAA,IAC7C;AAAA,EACF;AACF;;;ACzCA,OAAOC,cAAY;;;ACInB,SAAS,cAAAC,aAAY,aAAa,gBAAAC,qBAAoB;AACtD,SAAS,WAAAC,UAAS,QAAAC,OAAM,YAAAC,WAAU,WAAAC,gBAAe;;;ACE1C,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAC/C,cAAc;AACZ,UAAM,mFAAmF;AACzF,SAAK,OAAO;AAAA,EACd;AACF;AAEA,eAAsB,SAAS,MAAgB,SAAkE;AAC/G,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAW,SAAS,MAAM,OAAO;AAAA,EAClD,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,OAAM,IAAI,sBAAsB;AACtF,UAAM;AAAA,EACR;AACA,MAAI,wBAAwB,MAAM,KAAK,CAAE,MAAM,YAAY,QAAQ,GAAG,EAAI,OAAM,IAAI,sBAAsB;AAC1G,SAAO;AACT;AAQA,SAAS,wBAAwB,QAA4B;AAC3D,SACE,QAAQ,aAAa,WAAW,OAAO,aAAa,KAAK,CAAC,OAAO,OAAO,KAAK,KAAK,CAAC,UAAU,KAAK,OAAO,MAAM;AAEnH;AAEA,eAAe,YAAY,KAA+B;AACxD,MAAI;AACF,YAAQ,MAAM,WAAW,SAAS,CAAC,WAAW,GAAG,EAAE,KAAK,WAAW,IAAO,CAAC,GAAG,aAAa;AAAA,EAC7F,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,YAAY,QAAwB;AAClD,QAAM,QAAQ,OAAO,MAAM,OAAO;AAClC,QAAM,SAAS,MAAM,OAAO,CAAC,MAAM,qBAAqB,KAAK,CAAC,CAAC;AAC/D,QAAM,WAAW,OAAO,SAAS,IAAI,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG,MAAM,GAAG,EAAE;AACnG,MAAI,kCAAkC,KAAK,MAAM,GAAG;AAClD,YAAQ,KAAK,0FAA0F;AAAA,EACzG;AACA,SAAO,QAAQ,KAAK,IAAI;AAC1B;;;ACtBO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,SAA0B,KAAa;AACjD,UAAM,OAAO;AADuB;AAEpC,SAAK,OAAO;AAAA,EACd;AAAA,EAHsC;AAIxC;AAEA,eAAsB,aAAa,KAAqC;AACtE,QAAM,SAAS,MAAM,SAAS,CAAC,YAAY,aAAa,oBAAoB,GAAG,GAAG,EAAE,KAAK,KAAK,WAAW,IAAO,CAAC;AACjH,MAAI,OAAO,aAAa,GAAG;AACzB,UAAM,IAAI,mBAAmB,4BAA4B,GAAG,KAAK,YAAY,OAAO,UAAU,OAAO,MAAM,CAAC,IAAI,GAAG;AAAA,EACrH;AACA,MAAI;AACF,WAAO,KAAK,MAAM,OAAO,MAAM;AAAA,EACjC,QAAQ;AACN,UAAM,IAAI,mBAAmB,qCAAqC,GAAG,KAAK,GAAG;AAAA,EAC/E;AACF;;;AFtCA,IAAM,UAAU,oBAAI,IAAI,CAAC,UAAU,gBAAgB,UAAU,QAAQ,SAAS,OAAO,KAAK,CAAC;AAE3F,IAAM,OAAO,CAAC,SAAiBC,SAAQ,IAAI,EAAE,QAAQ,OAAO,GAAG;AAE/D,SAAS,cAAc,MAAwB;AAC7C,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,CAAC,KAAa,UAAkB;AAC3C,QAAIC;AACJ,QAAI;AACF,MAAAA,WAAU,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IACpD,QAAQ;AACN;AAAA,IACF;AACA,QAAIA,SAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,SAAS,YAAY,EAAG,OAAM,KAAKC,MAAK,KAAK,YAAY,CAAC;AAClG,eAAW,SAASD,UAAS;AAC3B,UAAI,MAAM,YAAY,KAAK,CAAC,MAAM,KAAK,WAAW,GAAG,KAAK,CAAC,QAAQ,IAAI,MAAM,IAAI,EAAG,MAAKC,MAAK,KAAK,MAAM,IAAI,GAAG,QAAQ,CAAC;AAAA,IAC3H;AAAA,EACF;AACA,OAAK,MAAM,CAAC;AAEZ,SAAO,MAAM,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;AACrG;AAEA,IAAM,oBAAoB,CAAC,QAAgB;AACzC,MAAI;AACF,WAAO,wBAAwB,KAAKC,cAAaD,MAAK,KAAK,YAAY,GAAG,MAAM,CAAC;AAAA,EACnF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,8BAAN,MAAiE;AAAA,EAC9D,WAAqB,CAAC;AAAA,EAE9B,cAAwB;AACtB,WAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA,EAGA,SAAS,UAAkB,aAAqD;AAC9E,UAAM,WAAW,cAAcF,SAAQ,WAAW,IAAI;AACtD,UAAM,QAAkB,CAAC;AACzB,aAAS,MAAMA,SAAQ,QAAQ,OAAO;AACpC,YAAM,KAAK,GAAG;AACd,YAAM,SAASI,SAAQ,GAAG;AAC1B,UAAI,QAAQ,YAAY,WAAW,IAAK;AACxC,YAAM;AAAA,IACR;AACA,WAAO,MAAM,KAAK,iBAAiB,KAAK,MAAM,KAAK,CAAC,MAAMC,YAAWH,MAAK,GAAG,YAAY,CAAC,CAAC;AAAA,EAC7F;AAAA,EAEA,MAAM,SAAS,SAA2C;AACxD,UAAM,UAAU,oBAAI,IAAY;AAChC,UAAM,UAA2B,CAAC;AAClC,UAAM,SAA+B,CAAC;AACtC,SAAK,WAAW,CAAC;AAEjB,eAAW,YAAY,cAAc,OAAO,GAAG;AAC7C,UAAI,QAAQ,IAAI,KAAK,QAAQ,CAAC,EAAG;AACjC,UAAI;AACF,cAAM,WAAW,MAAM,aAAaE,SAAQ,QAAQ,CAAC;AACrD,mBAAW,OAAO,SAAS,UAAU;AACnC,kBAAQ,IAAI,KAAK,IAAI,aAAa,CAAC;AACnC,gBAAM,OAAOA,SAAQ,IAAI,aAAa;AACtC,gBAAM,UAAUE,UAAS,SAAS,IAAI,EAAE,QAAQ,OAAO,GAAG;AAC1D,kBAAQ,KAAK;AAAA,YACX,IAAI,IAAI;AAAA,YACR,MAAM,IAAI;AAAA,YACV;AAAA,YACA,SAAS,YAAY,KAAK,SAAS;AAAA,YACnC,WAAW;AAAA,YACX,QAAQ,YAAY;AAAA,YACpB,SAAS,IAAI;AAAA,YACb,eAAeN,SAAQ,SAAS,cAAc;AAAA,UAChD,CAAC;AAAA,QACH;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,eAAe,sBAAuB,OAAM;AAChD,YAAI,eAAe,oBAAoB;AACrC,iBAAO,KAAK,GAAG;AACf,eAAK,SAAS,KAAK,IAAI,OAAO;AAAA,QAChC,MACK,OAAM;AAAA,MACb;AAAA,IACF;AAGA,QAAI,QAAQ,WAAW,KAAK,OAAO,SAAS,EAAG,OAAM,OAAO,CAAC;AAC7D,YAAQ,KAAK,CAAC,GAAG,MAAO,EAAE,SAAS,KAAK,EAAE,SAAS,IAAI,EAAE,QAAQ,cAAc,EAAE,OAAO,CAAE;AAG1F,UAAM,QAAQ,oBAAI,IAAY;AAC9B,eAAW,UAAU,SAAS;AAC5B,UAAI,MAAM,IAAI,OAAO,EAAE,EAAG,QAAO,KAAK,GAAG,OAAO,IAAI,KAAK,OAAO,OAAO;AACvE,YAAM,IAAI,OAAO,EAAE;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AACF;;;AGrGA,SAAS,cAAAO,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,eAAe;AACxB,SAAS,WAAAC,UAAS,cAAAC,aAAY,QAAAC,QAAM,WAAAC,gBAAe;AACnD,SAAS,oBAAoB,iBAAiB;AAE9C,IAAM,YAAY;AAClB,IAAM,eAAe,oBAAI,IAAI,CAAC,mBAAmB,oBAAoB,aAAa,YAAY,CAAC;AAExF,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,YAAY,QAAgB;AAC1B,UAAM,oEAAoE,MAAM,wBAAwB;AACxG,SAAK,OAAO;AAAA,EACd;AACF;AAIA,SAAS,cAAc,OAAwB;AAC7C,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,MAAM,QAAQ,wBAAwB,EAAE,CAAC;AAC7D,WAAO,aAAa,IAAI,IAAI,SAAS,YAAY,CAAC,MAAM,IAAI,aAAa,gBAAgB,IAAI,SAAS,SAAS,iBAAiB;AAAA,EAClI,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,MAAM,MAAa,KAAmB;AAC7C,QAAM,MAAa,EAAE,GAAG,KAAK;AAC7B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,UAAM,WAAW,IAAI,GAAG;AACxB,QAAI,GAAG,IACL,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,KAAK,YAAY,OAAO,aAAa,YAAY,CAAC,MAAM,QAAQ,QAAQ,IAC9H,MAAM,UAAU,KAAK,IACrB;AAAA,EACR;AACA,SAAO;AACT;AAEA,SAAS,SAAS,MAAc,QAAQ,GAAU;AAChD,MAAI;AACJ,MAAI;AACF,YAAQ,mBAAmB,UAAUJ,cAAa,MAAM,MAAM,CAAC,CAAC;AAAA,EAClE,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,QAAM,WAAoB,MAAM;AAChC,SAAO,MAAM;AACb,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,QAAQ,EAAG,QAAO;AAClD,MAAI,WAAkB,CAAC;AACvB,aAAW,SAAS,UAAU;AAC5B,UAAM,OAAO,OAAO,UAAU,WAAW,QAAQ,OAAO;AACxD,QAAI,OAAO,SAAS,SAAU,YAAW,MAAM,UAAU,SAASE,YAAW,IAAI,IAAI,OAAOE,SAAQH,SAAQ,IAAI,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC;AAAA,EACtI;AACA,SAAO,MAAM,UAAU,KAAK;AAC9B;AAEO,IAAM,oBAAN,MAAwB;AAAA,EACZ;AAAA,EACA,QAAQ,oBAAI,IAAmB;AAAA,EAEhD,YAAY,UAAuC,CAAC,GAAG;AACrD,SAAK,MAAM,QAAQ,OAAO,QAAQ;AAAA,EACpC;AAAA;AAAA,EAGQ,OAAO,KAAoB;AACjC,UAAM,QAAQG,SAAQ,GAAG;AACzB,QAAI,SAAS,KAAK,MAAM,IAAI,KAAK;AACjC,QAAI,OAAQ,QAAO;AACnB,UAAM,QAAkB,CAAC;AACzB,aAAS,MAAM,WAAW;AACxB,iBAAW,QAAQ,CAAC,eAAe,QAAQ,GAAG;AAC5C,cAAM,OAAOD,OAAK,KAAK,UAAU,IAAI;AACrC,YAAIJ,YAAW,IAAI,GAAG;AACpB,gBAAM,KAAK,IAAI;AACf;AAAA,QACF;AAAA,MACF;AACA,YAAM,SAASE,SAAQ,GAAG;AAC1B,UAAI,WAAW,IAAK;AACpB,YAAM;AAAA,IACR;AACA,UAAM,OAAO,KAAK,IAAI,cAAcE,OAAK,QAAQ,GAAG,QAAQ;AAC5D,eAAW,QAAQ,CAAC,eAAe,QAAQ,GAAG;AAC5C,YAAM,OAAOA,OAAK,MAAM,IAAI;AAC5B,UAAIJ,YAAW,IAAI,KAAK,CAAC,MAAM,SAAS,IAAI,GAAG;AAC7C,cAAM,KAAK,IAAI;AACf;AAAA,MACF;AAAA,IACF;AAEA,aAAS,MAAM,YAAY,CAAC,KAAK,SAAS,MAAM,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,CAAU;AACjF,SAAK,MAAM,IAAI,OAAO,MAAM;AAC5B,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,YAAY,QAAe,QAAgB,OAAmC;AACpF,UAAM,QAAQ,OAAO,SAAS,MAAM,IAAI,KAAK;AAC7C,WAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ,UAA8B,KAA4D;AACtG,UAAM,SAAS,KAAK,OAAO,GAAG;AAC9B,QAAI,OAAO,aAAa,SAAY,cAAc,KAAK,YAAY,QAAQ,QAAQ;AACnF,QAAI,QAAQ,YAAY;AACxB,UAAM,OAAO,oBAAI,IAAY;AAE7B,WAAO,SAAS,QAAW;AACzB,UAAI,KAAK,IAAI,IAAI,EAAG,OAAM,IAAI,uBAAuB,yBAAyB,IAAI,GAAG;AACrF,WAAK,IAAI,IAAI;AACb,YAAM,OAAO,KAAK,YAAY,QAAQ,MAAM,cAAc;AAC1D,UAAI,SAAS,OAAW;AACxB,iBAAW,QAAQ,CAAC,aAAa,kBAAkB,KAAK,GAAG;AACzD,YAAI,KAAK,YAAY,QAAQ,MAAM,IAAI,MAAM,OAAW,OAAM,IAAI,uBAAuB,IAAI,IAAI,UAAU,IAAI,SAAS;AAAA,MAC1H;AACA,YAAM,SAAS,KAAK,YAAY,QAAQ,MAAM,UAAU;AACxD,UAAI,WAAW,QAAW;AACxB,gBAAQ;AACR,eAAO;AAEP,YAAI,KAAK,YAAY,QAAQ,MAAM,cAAc,MAAM,OAAW;AAClE;AAAA,MACF;AACA,UAAI,KAAK,YAAY,QAAQ,MAAM,cAAc,MAAM,QAAW;AAChE,cAAM,IAAI,uBAAuB,IAAI,IAAI,mBAAmB;AAAA,MAC9D;AACA,aAAO;AAAA,IACT;AACA,WAAO,EAAE,OAAO,UAAU,cAAc,KAAK,EAAE;AAAA,EACjD;AAAA;AAAA,EAGQ,YAAY,QAAe,KAAiC;AAClE,WAAO,OAAO,KAAK,OAAO,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,KAAK,YAAY,QAAQ,GAAG,UAAU,MAAM,GAAG;AAAA,EACrG;AACF;;;AClJA,SAAS,qBAAqB;AAYvB,IAAM,UAAkB,OAA0C,UAAsB,YAAY;;;ACHpG,IAAM,4BAAN,cAAwC,MAAM;AAAA,EACnD,YAAqB,OAAe;AAClC,UAAM,gBAAgB,KAAK,yEAAyE;AADjF;AAEnB,SAAK,OAAO;AAAA,EACd;AAAA,EAHqB;AAIvB;AAEO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAqB,OAAwB,OAAe;AAC1D,UAAM,IAAI,KAAK,4BAA4B,KAAK,GAAG;AADhC;AAAwB;AAE3C,SAAK,OAAO;AAAA,EACd;AAAA,EAHqB;AAAA,EAAwB;AAI/C;AAEO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAC/C,YAAqB,OAAe;AAClC,UAAM,sBAAsB,KAAK,iDAAiD;AAD/D;AAEnB,SAAK,OAAO;AAAA,EACd;AAAA,EAHqB;AAIvB;AAEA,IAAM,mBAAmB;AACzB,IAAM,gBAAgB;AAGf,SAAS,UAAU,MAAsB;AAC9C,QAAM,IAAI,KAAK,YAAY;AAC3B,MAAI,EAAE,UAAU,EAAG,QAAO,GAAG,EAAE,MAAM,IAAI,CAAC;AAC1C,MAAI,EAAE,WAAW,EAAG,QAAO,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC;AACzC,SAAO,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC;AAC/C;AAEO,SAAS,WAAW,MAA8B;AACvD,QAAM,WAA2B,CAAC;AAClC,aAAW,OAAO,KAAK,MAAM,OAAO,GAAG;AACrC,QAAI,CAAC,IAAI,KAAK,EAAG;AACjB,QAAI;AACF,YAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,UAAI,OAAO,MAAM,SAAS,SAAU;AACpC,eAAS,KAAK,EAAE,SAAS,MAAM,MAAM,QAAQ,MAAM,WAAW,MAAM,aAAa,MAAM,aAAa,CAAC;AAAA,IACvG,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,WAAW,OAAuB;AACzC,MAAI,UAAU,cAAe,QAAO;AACpC,MAAI,MAAM,WAAW,SAAS,GAAG;AAC/B,UAAM,MAAM,MAAM,MAAM,UAAU,MAAM;AACxC,WAAO,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,GAAG;AAAA,EACzC;AACA,QAAM,IAAI,sBAAsB,KAAK;AACvC;AAEA,IAAM,YAAY,MAAM,WAAW,OAAO;AAE1C,SAAS,cAAc,KAAsB;AAC3C,QAAM,QAAS,KAA0C,OAAO;AAChE,SAAO,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAClE;AAEO,IAAM,mBAAN,MAAuB;AAAA,EAG5B,YACmB,UAAwB,OACxB,MAAyB,QAAQ,KAClD;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAJF,OAAO,oBAAI,IAAqC;AAAA;AAAA,EAQjE,SAAS,OAAe,OAAwC;AAC9D,UAAM,MAAM,GAAG,KAAK;AAAA,EAAK,MAAM,YAAY,CAAC;AAC5C,QAAI,UAAU,KAAK,KAAK,IAAI,GAAG;AAC/B,QAAI,CAAC,SAAS;AACZ,gBAAU,KAAK,KAAK,OAAO,KAAK;AAChC,WAAK,KAAK,IAAI,KAAK,OAAO;AAAA,IAC5B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,KAAK,OAAe,OAAwC;AACxE,UAAM,MAAM,GAAG,WAAW,KAAK,CAAC,GAAG,UAAU,KAAK,CAAC;AACnD,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,KAAK,QAAQ,KAAK,EAAE,SAAS,EAAE,cAAc,UAAU,EAAE,EAAE,CAAC;AAAA,IAC/E,SAAS,KAAK;AACZ,YAAM,IAAI,MAAM,gBAAgB,GAAG,KAAK,cAAc,GAAG,CAAC,GAAG,KAAK,UAAU,CAAC,EAAE;AAAA,IACjF;AACA,QAAI,SAAS,WAAW,OAAO,SAAS,WAAW,IAAK,OAAM,IAAI,0BAA0B,KAAK;AACjG,QAAI,SAAS,WAAW,IAAK,OAAM,IAAI,mBAAmB,OAAO,KAAK;AACtE,QAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,qBAAqB,SAAS,MAAM,QAAQ,GAAG,GAAG;AACpF,WAAO,WAAW,MAAM,SAAS,KAAK,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAoB;AAC1B,UAAM,UAAU,KAAK,IAAI,eAAe,KAAK,IAAI,eAAe,KAAK,IAAI,cAAc,KAAK,IAAI;AAChG,QAAI,CAAC,WAAW,KAAK,IAAI,uBAAuB,IAAK,QAAO;AAC5D,WAAO;AAAA,EACT;AACF;;;ACtHA,OAAOM,aAAY;;;ACDnB,OAAOC,aAAY;AAUnB,IAAM,OAAO,CAAC,MAAcA,QAAO,OAAO,CAAC,GAAG;AAGvC,SAAS,iBACd,UACA,SACU;AACV,QAAM,UAAU,QAAQ,cAAc,KAAK,QAAQ,WAAW,IAAI;AAClE,SAAO,SACJ,OAAO,CAAC,MAAM,CAAC,EAAE,UAAUA,QAAO,MAAM,EAAE,OAAO,CAAC,EAClD,OAAO,CAAC,MAAM,QAAQ,YAAY,SAASA,QAAO,WAAW,EAAE,OAAO,MAAM,IAAI,EAChF,OAAO,CAAC,MAAM;AACb,UAAM,QAAQ,EAAE,cAAc,KAAK,EAAE,WAAW,IAAI;AACpD,WAAO,EAAE,WAAW,SAASA,QAAO,GAAG,OAAO,OAAO;AAAA,EACvD,CAAC,EACA,IAAI,CAAC,MAAM,EAAE,OAAO,EACpB,KAAKA,QAAO,QAAQ;AACzB;AAEO,SAAS,cACd,UACA,SACW;AACX,QAAM,aAAa,SAChB,OAAO,CAAC,MAAM,CAAC,EAAE,UAAUA,QAAO,MAAM,EAAE,OAAO,CAAC,EAClD,OAAO,CAAC,MAAM,QAAQ,YAAY,SAASA,QAAO,WAAW,EAAE,OAAO,MAAM,IAAI,EAChF,KAAK,CAAC,GAAG,MAAMA,QAAO,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC;AAEvD,QAAM,UAAU,QAAQ,cAAc,KAAK,QAAQ,WAAW,IAAI;AAClE,MAAI;AACJ,aAAW,aAAa,YAAY;AAClC,UAAM,QAAQ,UAAU,cAAc,KAAK,UAAU,WAAW,IAAI;AACpE,QAAI,WAAW,SAASA,QAAO,GAAG,OAAO,OAAO,GAAG;AACjD,kBAAY,EAAE,SAAS,UAAU,SAAS,UAAU,UAAU,YAAa;AAC3E;AAAA,IACF;AACA,WAAO,EAAE,SAAS,UAAU,SAAS,GAAI,UAAU,EAAE,eAAe,QAAQ,IAAI,CAAC,EAAG;AAAA,EACtF;AACA,SAAO,EAAE,SAAS,QAAW,GAAI,UAAU,EAAE,eAAe,QAAQ,IAAI,CAAC,EAAG;AAC9E;;;ADrCO,IAAM,uBAAN,MAAmD;AAAA,EACxD,YAA6B,MAAyB;AAAzB;AAAA,EAA0B;AAAA,EAA1B;AAAA,EAE7B,MAAM,gBAAgB,YAAkC,KAAwC;AAC9F,UAAM,EAAE,OAAO,SAAS,IAAI,MAAM,KAAK,KAAK,SAAS,WAAW,UAAU,GAAG;AAC7E,WAAO,EAAE,KAAK,OAAO,SAAS;AAAA,EAChC;AAAA,EAEA,MAAM,iBACJ,YACA,UAA0B,UAC1B,MAAM,QAAQ,IAAI,GACM;AACxB,WAAO,cAAc,MAAM,KAAK,KAAK,YAAY,GAAG,GAAG,EAAE,QAAQ,CAAC,EAAE,WAAW;AAAA,EACjF;AAAA;AAAA,EAGA,MAAM,eAAe,YAAkC,MAAM,QAAQ,IAAI,GAAsB;AAC7F,YAAQ,MAAM,KAAK,KAAK,YAAY,GAAG,GACpC,OAAO,CAAC,MAAM,CAAC,EAAE,UAAUC,QAAO,MAAM,EAAE,OAAO,CAAC,EAClD,IAAI,CAAC,MAAM,EAAE,OAAO,EACpB,KAAKA,QAAO,QAAQ;AAAA,EACzB;AAAA,EAEA,MAAc,KAAK,YAAkC,KAAsC;AACzF,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,KAAK,SAAS,WAAW,UAAU,GAAG;AACnE,WAAO,KAAK,KAAK,MAAM,SAAS,OAAO,WAAW,QAAQ;AAAA,EAC5D;AACF;;;AEnCA,OAAOC,aAAY;AAInB,IAAM,SAAS;AAGR,SAAS,cAAc,aAAoC;AAChE,QAAM,QAAQ,YAAY,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACxD,MAAI,MAAM,KAAK,CAAC,MAAM,MAAM,EAAE,EAAG,QAAO;AACxC,QAAM,YAAY,MAAM,IAAI,CAAC,SAAS;AACpC,UAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,WAAO,OAAO,IAAI,IAAI,KAAK;AAAA,EAC7B,CAAC;AACD,SAAOA,QAAO,WAAW,UAAU,KAAK,GAAG,CAAC,IAAI,UAAU,KAAK,GAAG,IAAI;AACxE;AAGO,SAAS,qBAAqB,aAAqB,SAA0B;AAClF,QAAM,QAAQ,cAAc,WAAW;AACvC,SAAO,UAAU,QAAQA,QAAO,UAAU,SAAS,OAAO,EAAE,mBAAmB,MAAM,CAAC;AACxF;AAGO,SAAS,wBAAwB,aAA8B;AACpE,SAAO,OAAO,KAAK,YAAY,KAAK,CAAC;AACvC;AAGO,SAAS,iBAAiB,aAAoC;AACnE,QAAM,QAAQ,cAAc,WAAW;AACvC,SAAO,QAASA,QAAO,WAAW,KAAK,GAAG,WAAW,OAAQ;AAC/D;AAQO,SAAS,mBAAmB,SAAiB,QAAwB;AAC1E,QAAM,QAAQ,QAAQ,KAAK,EAAE,MAAM,MAAM;AACzC,MAAI,CAAC,MAAO,QAAO;AACnB,MAAIA,QAAO,WAAW,MAAM,EAAG,QAAO,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,MAAM;AAChE,QAAM,YAAY,MAAM,CAAC,EAAG,MAAM,GAAG,EAAE;AACvC,QAAM,CAAC,OAAO,OAAO,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE,CAAC,EAAG,MAAM,GAAG;AAChE,QAAM,UAAU,CAAC,OAAO,OAAO,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,GAAG;AAClE,SAAO,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,OAAO;AACpC;AAGO,SAAS,UAAU,MAAc,IAAyB;AAC/D,QAAM,IAAIA,QAAO,MAAM,IAAI;AAC3B,QAAM,IAAIA,QAAO,MAAM,EAAE;AACzB,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,MAAI,EAAE,QAAQ,KAAK,EAAE,QAAQ,EAAE,OAAO;AACpC,QAAI,EAAE,UAAU,EAAE,MAAO,QAAO;AAChC,WAAO,EAAE,UAAU,EAAE,QAAQ,UAAU;AAAA,EACzC;AACA,MAAI,EAAE,QAAQ,GAAG;AACf,QAAI,EAAE,UAAU,EAAE,MAAO,QAAO;AAChC,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;AC1DA,SAAS,gBAAAC,sBAAoB;AAC7B,SAAS,QAAAC,QAAM,YAAAC,iBAAgB;AAC/B,OAAOC,aAAY;;;ACRnB,SAAS,aAAAC,kBAAiB;AA0B1B,IAAMC,YAA8C;AAAA,EAClD,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,oBAAoB;AACtB;AAOO,SAAS,mBAAmB,QAAyC;AAC1E,QAAM,OAAOD,WAAU,MAAM,EAAE,KAAK,CAAC;AACrC,QAAM,SAAiB,CAAC;AAExB,QAAM,UAAU,CAAC,QAAuB,IAAI,KAAK,IAAI,CAAC,MAAY,EAAE,SAAS,aAAa,EAAE,OAAO,EAAE,KAAM;AAC3G,QAAM,YAAY,CAAC,QAAkB,SAAoB;AACvD,UAAM,OAAO,CAAC,GAAG,QAAQ,GAAG,QAAQ,KAAK,GAAG,CAAC;AAC7C,WAAO,KAAK,EAAE,MAAM,MAAM,KAAK,MAAM,CAAC;AACtC,QAAI,KAAK,MAAM,SAAS,kBAAmB,YAAW,SAAS,KAAK,MAAM,KAAM,WAAU,MAAM,KAAK;AAAA,EACvG;AAEA,aAAW,WAAW,KAAK,MAAM;AAC/B,QAAI,QAAQ,SAAS,eAAgB,WAAU,CAAC,GAAG,OAAO;AAAA,aACjD,QAAQ,SAAS,aAAa;AACrC,YAAM,SAAS,QAAQ,QAAQ,GAAG;AAClC,iBAAW,QAAQ,QAAQ,KAAM,WAAU,QAAQ,IAAI;AACvD,aAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAAA,IAC7C;AAAA,EACF;AAEA,QAAM,QAAQ,oBAAI,IAAmC;AACrD,aAAW,EAAE,MAAM,KAAK,KAAK,QAAQ;AACnC,UAAM,UAAU,cAAc,IAAI;AAClC,QAAI,CAAC,WAAW,QAAQ,KAAK,WAAW,EAAG;AAC3C,UAAM,CAAC,KAAK,KAAK,IAAI,QAAQ;AAC7B,UAAM,KAAK,GAAG,QAAQ,WAAW,IAAI,QAAQ,UAAU,EAAE,IAAI,QAAQ,OAAO,IAAI,GAAG;AACnF,QAAI,OAAO,MAAM,IAAI,EAAE;AACvB,QAAI,CAAC,MAAM;AACT,aAAO,EAAE,KAAW,SAAS,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,aAAa,QAAQ,aAAa,WAAW,MAAM;AACzH,YAAM,IAAI,IAAI,IAAI;AAAA,IACpB;AACA,QAAI,QAAQ,KAAK,WAAW,KAAK,KAAK,SAAS,eAAe,KAAK,SAAS,UAAU;AACpF,WAAK,UAAU,UAAU,IAAI;AAAA,IAC/B,WAAW,UAAU,aAAa,QAAQ,KAAK,WAAW,KAAK,KAAK,SAAS,eAAe,KAAK,SAAS,UAAU;AAClH,WAAK,UAAU,UAAU,IAAI;AAAA,IAC/B,WAAW,UAAU,eAAe,QAAQ,KAAK,WAAW,KAAK,KAAK,UAAU,MAAM;AACpF,WAAK,YAAY;AAAA,IACnB,WAAW,UAAU,aAAa,QAAQ,KAAK,WAAW,KAAK,KAAK,SAAS,aAAa;AACxF,WAAK,UAAU,OAAO,KAAK,KAAK;AAAA,IAClC;AAAA,EACF;AACA,SAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAC3B;AAEA,SAAS,UAAU,MAA2B;AAC5C,SAAO,EAAE,OAAO,KAAK,OAAO,OAAO,KAAK,MAAM,CAAC,IAAI,GAAG,KAAK,KAAK,MAAM,CAAC,IAAI,EAAE;AAC/E;AAGA,SAAS,cAAc,MAAgB;AACrC,MAAI,IAAI;AACR,MAAI;AACJ,MAAI,cAAc;AAClB,MAAI,KAAK,CAAC,MAAM,eAAe,KAAK,CAAC,MAAM,gBAAgB;AACzD,WAAO,EAAE,SAAS,gBAAyB,aAAa,MAAM,QAAQ,MAAM,KAAK,MAAM,CAAC,EAAE;AAAA,EAC5F;AACA,MAAI,KAAK,CAAC,MAAM,YAAY,KAAK,UAAU,GAAG;AAC5C,aAAS,KAAK,CAAC;AACf,QAAI;AAAA,EACN;AACA,QAAM,UAAUC,UAAS,KAAK,CAAC,KAAK,EAAE;AACtC,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,EAAE,SAAS,aAAa,QAAQ,MAAM,KAAK,MAAM,IAAI,CAAC,EAAE;AACjE;;;ACxGA,SAAS,cAAAC,aAAY,gBAAAC,sBAAoB;AACzC,SAAS,sBAAAC,qBAAoB,aAAAC,kBAAiB;AAGvC,SAAS,mBAAmB,UAAyC;AAC1E,QAAM,SAAS,oBAAI,IAAsB;AACzC,MAAI,CAACH,YAAW,QAAQ,EAAG,QAAO;AAClC,MAAI;AACF,UAAM,OAAOE,oBAAmBC,WAAUF,eAAa,UAAU,MAAM,CAAC,CAAC;AACzE,eAAW,OAAO,KAAK,WAAW,CAAC,EAAG,QAAO,IAAI,IAAI,MAAM,CAAC,GAAI,OAAO,IAAI,IAAI,IAAI,KAAK,CAAC,GAAI,IAAI,OAAO,CAAC;AAAA,EAC3G,QAAQ;AAAA,EAER;AACA,SAAO;AACT;;;AFwBA,IAAMG,eAAc;AACpB,IAAMC,cAAqC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,EAAE;AAWnE,IAAM,yBAAN,MAA6D;AAAA,EAClE,YAA6B,MAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EAE7B,MAAM,KAAK,QAAuB,SAA2C;AAC3E,UAAM,WAAW,MAAM,KAAK,KAAK,aAAa,OAAO,iBAAiB,OAAO,IAAI;AACjF,UAAM,MAAM,SAAS,SAAS,KAAK,CAAC,MAAM,SAASC,OAAK,EAAE,eAAe,IAAI,GAAG,OAAO,IAAI,CAAC;AAC5F,QAAI,CAAC,IAAK,QAAO,EAAE,YAAY,CAAC,GAAG,SAAS,CAAC,EAAE;AAE/C,UAAM,MAAM,iBAAiB,IAAI,aAAa;AAC9C,UAAM,QAAQ,mBAAmBA,OAAK,SAAS,gBAAgB,YAAY,CAAC;AAC5E,UAAM,eAAeA,OAAK,SAAS,gBAAgB,YAAY;AAC/D,UAAM,OAAO,iBAAiB,YAAY;AAC1C,UAAM,SAAS,kBAAkB,IAAI,YAAY;AAEjD,UAAM,WAAW,MAAM,UAAU,QAAQF,cAAa,OAAO,UAA4B;AACvF,YAAM,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI,KAAK,MAAM,CAAC;AAC7D,YAAM,MAAM,QAAQ,UAAU,QAAQ;AACtC,YAAM,OAAO,gBAAgB,KAAK,KAAK,OAAO;AAC9C,YAAM,UAAU,OAAO,MAAM,MAAM,KAAK,QAAQ,SAAS,IAAI,eAAe,YAAY;AACxF,YAAM,QAAQ,MAAM,MAAM,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,QAAQ;AAC7D,YAAM,YAAY,QAAQ,WAAW,QAAQ,SAAS,UAAU,UAAU;AAC1E,YAAM,SAAS,EAAE,OAAO,UAAU;AAElC,UAAI,QAAQ,WAAW,QAAQ,QAAQ,MAAM;AAE3C,cAAM,SAAS,CAAC,GAAG,QAAQ,UAAU,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,SAAS,EAAE,MAAM,QAAQ,IAAK,CAAC;AAC1F,eAAO,SAAS,UAAU,SAAS,QAAQ,SAAS,MAAM,IAAI;AAAA,MAChE;AACA,UAAI,CAAC,QAAQ,UAAU,QAAQ,OAAO,WAAW,MAAM,EAAG,QAAO;AACjE,YAAM,UAAU,MAAM,KAAK,gBAAgB,SAAS,SAAS,KAAK,UAAU,OAAO,QAAQ,OAAO;AAClG,YAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,MAAM,WAAW,CAAC,gBAAgB,EAAE,KAAK,QAAQ,GAAG,CAAC;AACrF,UAAI,WAAW,eAAe,WAAW,OAAO;AAE9C,gBAAQ,OAAO;AAAA,UACb,YAAY,QAAQ;AAAA,UACpB,QAAQ,QAAQ,UAAU,OAAO;AAAA,UACjC,QAAQ;AAAA,UACR,QAAQ,GAAG,UAAU,KAAK,CAAC,aAAa,MAAM,GAAG;AAAA,QACnD;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,aAAgC,CAAC;AACvC,UAAM,UAA+B,CAAC;AACtC,eAAW,WAAW,UAAU;AAC9B,UAAI,CAAC,QAAS;AACd,UAAI,eAAe,SAAS;AAC1B,mBAAW,KAAK,QAAQ,SAAS;AACjC,YAAI,QAAQ,KAAM,SAAQ,KAAK,QAAQ,IAAI;AAAA,MAC7C,MACK,SAAQ,KAAK,QAAQ,OAAO;AAAA,IACnC;AACA,eAAW,KAAK,CAAC,GAAG,OAAOC,YAAW,EAAE,IAAI,KAAK,MAAMA,YAAW,EAAE,IAAI,KAAK,EAAE;AAC/E,WAAO,EAAE,YAAY,QAAQ;AAAA,EAC/B;AAAA,EAEA,MAAc,gBACZ,KACA,SACA,KACA,UACA,OACA,QACA,SACkB;AAClB,UAAM,UAAU,SAAS,QAAQ,SAAS,IAAI;AAC9C,QAAI,CAAC,wBAAwB,OAAO,EAAG,QAAO;AAE9C,QAAI,CAAC,WAAW,CAAC,gBAAgB,QAAQ,QAAQ,OAAO,IAAI,GAAG,GAAG;AAChE,aAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,UAAU,QAAQ,wBAAwB,QAAQ,GAAG,OAAO,qBAAqB,IAAI,GAAG,aAAa,EAAE;AAAA,IAC3J;AAEA,QAAI,SAA2B,EAAE,MAAM,SAAS;AAChD,QAAI,IAAI,SAAU,UAAS,EAAE,MAAM,WAAW,WAAW,mBAAmB,UAAU,IAAI,SAAS;AAAA,aAC1F,qBAAqB,IAAI,MAAM,SAAS,QAAQ,cAAc,EAAG,UAAS,EAAE,MAAM,WAAW,WAAW,iBAAiB;AAElI,UAAM,WAAW,MAAM,KAAK,KAAK,SAAS,IAAI,YAAY,QAAW,QAAQ,OAAO;AACpF,QAAI,OAAO,SAAS,aAAa,SAAS,UAAU;AAElD,aAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,WAAW,QAAQ,8BAA8B,QAAQ,SAAS,MAAM,EAAE;AAAA,IAC9H;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,KAAK,KAAK,MAAM,SAAS,SAAS,OAAO,IAAI,IAAI;AAAA,IACpE,SAAS,KAAK;AACZ,aAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,iBAAiB,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,EAAE;AAAA,IACrJ;AAEA,UAAM,SAAS,cAAc,UAAU,EAAE,SAAS,QAAQ,SAAS,aAAa,IAAI,gBAAgB,OAAU,CAAC;AAC/G,UAAM,QAAQ,iBAAiB,OAAO;AACtC,QAAI,CAAC,OAAO,SAAS;AACnB,UAAI,OAAO,iBAAiB,OAAO;AACjC,cAAM,EAAE,SAAS,SAAS,IAAI,OAAO;AACrC,eAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,6BAA6B,QAAQ,KAAK,OAAO,eAAe,QAAQ,IAAI,EAAE;AAAA,MACvJ;AACA,aAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,iBAAiB,QAAQ,oCAAoC,EAAE;AAAA,IACxI;AAEA,UAAM,SAAS,OAAO;AACtB,QAAI,CAAC,SAAS,CAACE,QAAO,GAAG,QAAQ,KAAK,GAAG;AAEvC,YAAM,OAAO,OAAO;AACpB,UAAI,SAAS,QAAQA,QAAO,GAAG,KAAK,SAAS,KAAK,GAAG;AACnD,eAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,6BAA6B,QAAQ,KAAK,KAAK,OAAO,eAAe,KAAK,QAAQ,IAAI,EAAE;AAAA,MACjK;AACA,aAAO,WAAW,KAAK,SAAS,QAAQ,UAAU,KAAK;AAAA,IACzD;AACA,UAAM,WAAW,mBAAmB,SAAS,MAAM;AAEnD,QAAI,aAAa,QAAS,QAAO,YAAY,KAAK,SAAS,QAAQ,UAAU,KAAK,UAAU,OAAO,QAAQ,OAAO;AAElH,UAAM,MAAMA,QAAO,WAAW,MAAM,IAAK,qBAAqB,MAAM,KAAK,QAAS;AAClF,UAAM,OAAO,UAAU,OAAO,MAAM;AACpC,UAAM,YAA6B;AAAA,MACjC,YAAY,EAAE,YAAY,IAAI,MAAM,UAAU,IAAI,MAAM,WAAW,SAAS,GAAI,IAAI,WAAW,EAAE,UAAU,IAAI,SAAS,IAAI,CAAC,EAAG;AAAA,MAChI,cAAc;AAAA,MACd,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,OAAO;AAAA,MACd,UAAU,SAAS;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,MACR,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,eAAe;AAAA,MACf,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,MAC1D,GAAI,QAAQ,YAAY,EAAE,YAAY,UAAU,UAAU,KAAK,IAAI,UAAU,IAAI,IAAI,EAAE,IAAI,CAAC;AAAA,IAC9F;AACA,WAAO,EAAE,UAAU;AAAA,EACrB;AACF;AAMA,SAAS,YACP,KACA,aACA,QACA,UACA,KACA,UACA,OACA,QACA,SACS;AACT,QAAM,UAAU,MAAM,IAAI,IAAI,IAAI,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,qBAAqB,aAAa,CAAC,CAAC,EAAE,KAAKA,QAAO,QAAQ,EAAE,CAAC;AACtH,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,UAAU,EAAE,SAAS,QAAQ,SAAS,aAAa,IAAI,gBAAgB,OAAU;AACvF,QAAM,UAAU,SAAS,OAAO,CAAC,MAAM,qBAAqB,aAAa,EAAE,OAAO,CAAC;AACnF,QAAM,QAAQ,iBAAiB,SAAS,OAAO,EAAE,OAAO,CAAC,MAAMA,QAAO,GAAG,GAAG,MAAM,CAAC;AACnF,QAAM,SAAS,MAAM,CAAC;AACtB,MAAI,CAAC,OAAQ,QAAO,WAAW,KAAK,aAAa,QAAQ,UAAU,KAAK;AAExE,QAAM,WAAWD,OAAK,SAAS,gBAAgB,YAAY;AAC3D,SAAO;AAAA,IACL,WAAW;AAAA,MACT,YAAY,EAAE,YAAY,IAAI,MAAM,UAAU,IAAI,MAAM,WAAW,SAAS,GAAI,IAAI,WAAW,EAAE,UAAU,IAAI,SAAS,IAAI,CAAC,EAAG;AAAA,MAChI,cAAc;AAAA,MACd,cAAc;AAAA,MACd;AAAA,MACA,UAAU;AAAA,MACV,MAAM,UAAU,QAAQ,MAAM;AAAA,MAC9B,OAAO,OAAO;AAAA;AAAA,MAEd,UAAU;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,MACR,aAAa,EAAE,MAAM,UAAU,MAAM,YAAY,aAAa,QAAQ,QAAQ,SAAS,QAAQ,EAAE;AAAA,MACjG,mBAAmB;AAAA,MACnB,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,IAC5D;AAAA,EACF;AACF;AAMA,SAAS,WACP,KACA,aACA,QACA,UACA,OACS;AACT,QAAM,UAAU,MAAM,IAAI,IAAI,IAAI,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,qBAAqB,aAAa,CAAC,CAAC,EAAE,KAAKC,QAAO,QAAQ,EAAE,CAAC;AACtH,MAAI,CAAC,UAAU,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,MAAM,EAAG,QAAO;AAC/E,SAAO,EAAE,SAAS,EAAE,YAAY,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,yBAAyB,QAAQ,OAAO,EAAE;AACnH;AAQA,SAAS,UACP,KACA,QACA,SACA,QACS;AACT,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,WAAW,CAAC,SAAS,CAACA,QAAO,MAAM,KAAK,EAAG,QAAO;AACvD,QAAM,UAAU,QAAQ,QAAQ;AAChC,MAAI,CAAC,wBAAwB,OAAO,KAAK,qBAAqB,SAAS,KAAK,EAAG,QAAO;AAEtF,QAAM,QAAQ,iBAAiB,OAAO,KAAK;AAC3C,QAAM,OAAO,UAAU,OAAO,KAAK;AACnC,QAAM,MAAMA,QAAO,WAAW,KAAK,IAAK,qBAAqB,KAAK,KAAK,QAAS;AAChF,SAAO;AAAA,IACL,WAAW;AAAA,MACT,YAAY,EAAE,YAAY,IAAI,MAAM,UAAU,IAAI,MAAM,WAAW,QAAQ;AAAA,MAC3E,cAAc;AAAA,MACd,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,UAAU,mBAAmB,SAAS,KAAK;AAAA,MAC3C;AAAA,MACA,OAAO,OAAO;AAAA,MACd,UAAU,SAAS;AAAA,MACnB,QAAQ,EAAE,MAAM,aAAa,UAAU,OAAO,IAAI,eAAe,OAAO,QAAQ;AAAA,MAChF,QAAQ;AAAA,MACR,aAAa,QAAQ;AAAA,MACrB,mBAAmB,CAAC,KAAK;AAAA,MACzB,cAAc,QAAQ;AAAA,MACtB,eAAe;AAAA,MACf,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,IAC5D;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,MAAoD;AAC7E,QAAM,SAAS,oBAAI,IAAkC;AACrD,aAAW,OAAO,MAAM;AACtB,UAAM,KAAK,GAAG,IAAI,UAAU,IAAI,IAAI;AACpC,WAAO,IAAI,IAAI,CAAC,GAAI,OAAO,IAAI,EAAE,KAAK,CAAC,GAAI,GAAG,CAAC;AAAA,EACjD;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;AAEA,SAAS,iBAAiB,cAA+C;AACvE,MAAI;AACF,WAAO,mBAAmBC,eAAa,cAAc,MAAM,CAAC;AAAA,EAC9D,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,IAAM,YAAY,CAAC,QACjB,IAAI,SAAS,QAAQ,qBAAqB,IAAI,SAAS,UAAU,uBAAuB;AAE1F,SAAS,gBAAgB,OAAgC,KAAa,KAAyB;AAC7F,QAAM,aAAa,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,QAAQ,GAAG;AACtE,SACE,WAAW,KAAK,CAAC,MAAM,EAAE,YAAY,UAAU,GAAG,MAAM,EAAE,UAAU,UAAU,IAAI,MAAM,KAAK,WAAW,CAAC;AAE7G;AAEA,SAAS,OACP,MACA,MACA,KACA,UACA,cACA,cACqB;AACrB,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,WAAW;AAClB,UAAM,SAAS,KAAK,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,QAAQ,GAAG;AAC9D,QAAI,CAAC,QAAQ,QAAS,QAAO;AAC7B,WAAO;AAAA,MACL,SAAS,OAAO;AAAA,MAChB,WAAW;AAAA,MACX,aAAa,EAAE,MAAM,cAAc,MAAM,yBAAyB,aAAa,QAAQ,UAAU,YAAY,EAAE;AAAA,IACjH;AAAA,EACF;AACA,MAAI,CAAC,KAAK,QAAS,QAAO;AAC1B,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd,WAAW;AAAA,IACX,aAAa,EAAE,MAAM,cAAc,MAAM,cAAc,aAAa,QAAQ,UAAU,YAAY,EAAE;AAAA,EACtG;AACF;AAGA,SAAS,UAAU,UAAyB,MAAuB,KAAuB;AACxF,SAAO,SAAS,SACb,OAAO,CAAC,MAAM,MAAM,IAAI,EACxB,OAAO,CAAC,MAAM,iBAAiB,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,OAAO,EAAE,SAAS,CAAC,EACzF,IAAI,CAAC,MAAM,EAAE,IAAI;AACtB;AAEA,IAAM,UAAU,CAAC,UAAkB,SAAiBC,UAAS,UAAU,IAAI,EAAE,QAAQ,OAAO,GAAG;AAC/F,IAAM,WAAW,CAAC,GAAW,MAAcA,UAAS,GAAG,CAAC,MAAM;AAE9D,SAAS,gBAAgB,SAAiB,KAAsB;AAC9D,QAAM,IAAI,cAAc,OAAO;AAC/B,QAAM,IAAI,cAAc,GAAG;AAC3B,SAAO,MAAM,QAAQ,MAAM,QAAQF,QAAO,WAAW,CAAC,MAAMA,QAAO,WAAW,CAAC;AACjF;;;AG5VA,SAAS,cAAAG,aAAY,gBAAAC,gBAAc,iBAAAC,sBAAqB;AACxD,SAAS,QAAAC,QAAM,WAAAC,gBAAe;AAC9B,OAAOC,aAAY;;;ACJnB,SAAS,mBAAmB;AAkBrB,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YAAY,SAA0B,MAAe;AACnD,UAAM,OAAO,GAAG,IAAI,KAAK,OAAO,KAAK,OAAO;AADR;AAEpC,SAAK,OAAO;AAAA,EACd;AAAA,EAHsC;AAIxC;AAQO,SAAS,SAAS,QAAgB,MAA2B;AAClE,QAAM,SAAS,IAAI,YAAY,EAAE,UAAU,KAAK,CAAC;AACjD,QAAM,QAAsB,CAAC;AAC7B,QAAM,WAAqB,CAAC;AAC5B,MAAI;AACJ,MAAI;AAEJ,SAAO,GAAG,SAAS,CAAC,QAAQ;AAC1B,gBAAY;AAAA,EACd,CAAC;AAED,SAAO,GAAG,WAAW,CAAC,QAAQ;AAC5B,UAAM,aAAqC,CAAC;AAC5C,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,UAAU,GAAG;AACzD,iBAAW,GAAG,IAAI,OAAO,UAAU,WAAW,QAAQ,MAAM;AAAA,IAC9D;AACA,UAAM,UAAsB;AAAA,MAC1B,MAAM,UAAU,IAAI,IAAI;AAAA,MACxB;AAAA,MACA,UAAU,CAAC;AAAA,MACX,MAAM;AAAA,IACR;AACA,UAAM,SAAS,MAAM,MAAM,SAAS,CAAC;AACrC,QAAI,OAAQ,QAAO,SAAS,KAAK,OAAO;AAAA,QACnC,UAAS;AAEd,UAAM,KAAK,OAAO;AAElB,aAAS,KAAK,OAAO,QAAQ;AAAA,EAC/B,CAAC;AAED,SAAO,GAAG,YAAY,CAAC,QAAQ;AAC7B,UAAM,UAAU,MAAM,IAAI;AAC1B,UAAM,UAAU,SAAS,IAAI;AAC7B,QAAI,CAAC,WAAW,YAAY,UAAa,IAAI,cAAe;AAK5D,UAAM,WAAW,OAAO;AACxB,UAAM,aAAa,OAAO,YAAY,MAAM,WAAW,CAAC;AACxD,QAAI,cAAc,SAAS;AACzB,cAAQ,eAAe,EAAE,OAAO,SAAS,KAAK,WAAW;AAAA,IAC3D;AAAA,EACF,CAAC;AAED,SAAO,GAAG,QAAQ,CAAC,SAAS;AAC1B,UAAM,UAAU,MAAM,MAAM,SAAS,CAAC;AACtC,QAAI,QAAS,SAAQ,QAAQ;AAAA,EAC/B,CAAC;AAED,SAAO,GAAG,SAAS,CAAC,SAAS;AAC3B,UAAM,UAAU,MAAM,MAAM,SAAS,CAAC;AACtC,QAAI,QAAS,SAAQ,QAAQ;AAAA,EAC/B,CAAC;AAED,MAAI;AACF,WAAO,MAAM,MAAM,EAAE,MAAM;AAAA,EAC7B,SAAS,KAAK;AACZ,gBAAY;AAAA,EACd;AAEA,MAAI,QAAS,OAAM,IAAI,cAAc,QAAQ,SAAS,IAAI;AAC1D,MAAI,CAAC,KAAM,OAAM,IAAI,cAAc,gCAAgC,IAAI;AACvE,SAAO;AACT;AAGO,SAAS,MAAM,SAAiC,MAAsC;AAC3F,SAAO,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACtD;AAGO,SAAS,SAAS,SAAiC,MAA4B;AACpF,SAAO,UAAU,QAAQ,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI,CAAC;AACtE;AAGO,SAAS,QAAQ,YAAoC,MAAwC;AAClG,MAAI,UAAU;AACd,aAAW,QAAQ,KAAM,WAAU,MAAM,SAAS,IAAI;AACtD,SAAO;AACT;AAGO,SAAS,UAAU,SAAiC,MAAkC;AAC3F,QAAM,QAAQ,MAAM,SAAS,IAAI,GAAG,KAAK,KAAK;AAC9C,SAAO,QAAQ,QAAQ;AACzB;AAWO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAUO,SAAS,eAAe,QAAgB,OAA2B;AACxE,QAAM,UAAU,MAAM,IAAI,CAAC,SAAS;AAClC,UAAM,QAAQ,KAAK,QAAQ;AAC3B,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,eAAe,IAAI,KAAK,QAAQ,IAAI,iCAAiC;AAAA,IACjF;AACA,UAAM,MAAM,OAAO,MAAM,MAAM,OAAO,MAAM,GAAG;AAC/C,UAAM,UAAU,IAAI,SAAS,IAAI,UAAU,EAAE;AAC7C,UAAM,QAAQ,IAAI,KAAK;AACvB,QAAI,UAAU,KAAK,UAAU;AAC3B,YAAM,IAAI;AAAA,QACR,IAAI,KAAK,QAAQ,IAAI,eAAe,KAAK,gBAAgB,KAAK,QAAQ;AAAA,MACxE;AAAA,IACF;AACA,UAAM,QAAQ,MAAM,QAAQ;AAC5B,WAAO,EAAE,OAAO,KAAK,QAAQ,MAAM,QAAQ,aAAa,KAAK,YAAY;AAAA,EAC3E,CAAC;AAGD,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACxC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,QAAI,QAAQ,CAAC,EAAG,MAAM,QAAQ,IAAI,CAAC,EAAG,OAAO;AAC3C,YAAM,IAAI,eAAe,wCAAwC;AAAA,IACnE;AAAA,EACF;AAEA,MAAI,SAAS;AACb,aAAW,UAAU,SAAS;AAC5B,aAAS,OAAO,MAAM,GAAG,OAAO,KAAK,IAAI,OAAO,cAAc,OAAO,MAAM,OAAO,GAAG;AAAA,EACvF;AACA,SAAO;AACT;AAGO,SAAS,UAAU,OAAuB;AAC/C,SAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM;AAChF;AAMO,SAAS,aAAa,SAAqB,SAAS,IAAY;AACrE,QAAM,QAAQ,OAAO,QAAQ,QAAQ,UAAU,EAC5C,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,KAAK,UAAU,KAAK,EAAE,QAAQ,MAAM,QAAQ,CAAC,GAAG,EAC7E,KAAK,EAAE;AACV,MAAI,QAAQ,SAAS,WAAW,GAAG;AACjC,WAAO,GAAG,MAAM,IAAI,QAAQ,IAAI,GAAG,KAAK,IAAI,UAAU,QAAQ,KAAK,KAAK,CAAC,CAAC,KAAK,QAAQ,IAAI;AAAA,EAC7F;AACA,QAAM,QAAQ,QAAQ,SAAS,IAAI,CAAC,MAAM,aAAa,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI;AACnF,SAAO,GAAG,MAAM,IAAI,QAAQ,IAAI,GAAG,KAAK;AAAA,EAAM,KAAK;AAAA,EAAK,MAAM,KAAK,QAAQ,IAAI;AACjF;AAEA,SAAS,UAAU,WAA2B;AAC5C,QAAM,QAAQ,UAAU,QAAQ,GAAG;AACnC,SAAO,SAAS,IAAI,UAAU,MAAM,QAAQ,CAAC,IAAI;AACnD;;;ACnMO,SAAS,gBAAgB,QAAgB,OAAqC;AACnF,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,KAAK,GAAG;AAC/C,QAAI,UAAU,KAAK,UAAU;AAC3B,YAAM,IAAI,eAAe,UAAU,KAAK,gBAAgB,KAAK,QAAQ,2CAA2C;AAAA,IAClH;AAAA,EACF;AACA,QAAM,UAAU,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3D,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,QAAI,QAAQ,CAAC,EAAG,MAAM,QAAQ,IAAI,CAAC,EAAG,MAAO,OAAM,IAAI,eAAe,qCAAqC;AAAA,EAC7G;AACA,MAAI,SAAS;AACb,aAAW,QAAQ,QAAS,UAAS,OAAO,MAAM,GAAG,KAAK,KAAK,IAAI,KAAK,cAAc,OAAO,MAAM,KAAK,GAAG;AAC3G,SAAO;AACT;;;AFJA,IAAM,oBAAoB,KAAK;AAE/B,IAAM,eAAe,CAAC,QAAuB,YAAoB,OAAO,iBAAiB,OAAO,QAAQ;AAEjG,IAAM,sBAAN,MAA2D;AAAA,EAChE,cAAc,QAAuB,SAAiB,SAAsC;AAC1F,UAAM,QAAQ,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAMC,SAAQ,EAAE,aAAa,QAAQC,OAAK,OAAO,MAAM,YAAY,CAAC,CAAC,CAAC;AACzG,UAAM,IAAIA,OAAK,aAAa,QAAQ,OAAO,GAAG,YAAY,CAAC;AAC3D,WAAO,CAAC,GAAG,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,aACJ,QACA,SACA,SACA,YACuB;AACvB,UAAM,MAAM,aAAa,QAAQ,OAAO;AACxC,UAAM,WAAWA,OAAK,KAAK,YAAY;AACvC,UAAM,eAAe,mBAAmB,QAAQ;AAIhD,UAAM,cAAc,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM;AAC7D,cAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM;AACnD,SAAK,iBAAiB,aAAa,UAAU,YAAY;AAGzD,UAAM,SAAS,oBAAI,IAA+B;AAClD,eAAW,UAAU,SAAS;AAC5B,YAAM,OAAOD,SAAQ,OAAO,aAAa,QAAQC,OAAK,OAAO,MAAM,YAAY,CAAC;AAChF,aAAO,IAAI,MAAM,CAAC,GAAI,OAAO,IAAI,IAAI,KAAK,CAAC,GAAI,MAAM,CAAC;AAAA,IACxD;AACA,UAAM,SAA8C,CAAC;AACrD,eAAW,CAAC,MAAM,WAAW,KAAK,QAAQ;AACxC,iBAAW,aAAa,YAAY,MAAM,iBAAiB,IAAI,QAAG;AAClE,YAAM,SAASC,eAAa,MAAM,MAAM;AACxC,YAAM,QAAQ,mBAAmB,MAAM;AACvC,YAAM,QAAqB,CAAC;AAC5B,iBAAW,UAAU,aAAa;AAChC,cAAM,cAAc,OAAO,aAAa,SAAS;AACjD,cAAM,OAAO,OAAO,WAAW;AAC/B,cAAM,QAAQ,MAAM;AAAA,UAClB,CAAC,MAAM,EAAE,gBAAgB,gBAAgB,EAAE,WAAW,EAAE,SAAS,QAAQ,EAAE,SAAS,UAAU,OAAO;AAAA,QACvG;AACA,YAAI,MAAM,WAAW,GAAG;AACtB,gBAAM,IAAI,aAAa,GAAG,IAAI,gCAAgC,IAAI,KAAK,OAAO,YAAY,gCAAgC;AAAA,QAC5H;AACA,mBAAW,KAAK,OAAO;AACrB,gBAAM,KAAK,EAAE,OAAO,EAAE,QAAS,OAAO,KAAK,EAAE,QAAS,KAAK,UAAU,EAAE,QAAS,OAAO,aAAa,OAAO,SAAS,CAAC;AAAA,QACvH;AAAA,MACF;AACA,UAAI;AACF,eAAO,KAAK,EAAE,MAAM,SAAS,gBAAgB,QAAQ,KAAK,EAAE,CAAC;AAAA,MAC/D,SAAS,KAAK;AACZ,YAAI,eAAe,eAAgB,OAAM,IAAI,aAAa,GAAG,IAAI,KAAK,IAAI,OAAO,EAAE;AACnF,cAAM;AAAA,MACR;AAAA,IACF;AACA,eAAW,gCAA2B;AACtC,eAAW,SAAS,OAAQ,CAAAC,eAAc,MAAM,MAAM,MAAM,SAAS,MAAM;AAE3E,UAAM,kBAAkB,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ;AACnE,QAAIC,YAAW,QAAQ,KAAK,gBAAgB,SAAS,GAAG;AACtD,YAAM,KAAK,YAAY,KAAK,UAAU,cAAc,iBAAiB,UAAU;AAAA,IACjF;AAEA,eAAW,UAAU,aAAa;AAChC,YAAM,OAAO,OAAO,WAAW;AAC/B,iBAAW,WAAW,IAAI,OAAO,OAAO,MAAM,QAAG;AACjD,YAAM,KAAK,YAAY,KAAK,CAAC,MAAM,GAAG,IAAI,IAAI,OAAO,YAAY,IAAI,aAAa,OAAO,MAAM,CAAC;AAAA,IAClG;AAEA,UAAM,QAAkB,CAAC;AACzB,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,KAAK,WAAW,QAAQ,MAAM,sBAAsB,OAAO,MAAM,sBAAsBA,YAAW,QAAQ,IAAI,2BAA2B,EAAE,EAAE;AAAA,IACrJ;AACA,QAAI,YAAY,SAAS,EAAG,OAAM,KAAK,UAAU,YAAY,MAAM,4CAA4C;AAC/G,UAAM,UAAU,MAAM,KAAK,IAAI;AAE/B,WAAO;AAAA,MACL,cAAc,QAAQ,SAAS,YAAY;AAAA,MAC3C,cAAc,GAAG,QAAQ,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,QAAQ,MAAM,CAAC,CAAC;AAAA,MACnE,eAAe;AAAA,MACf,qBAAqB,CAAC;AAAA,IACxB;AAAA,EACF;AAAA;AAAA,EAGQ,iBAAiB,aAAgC,UAAkB,QAAqC;AAC9G,QAAI,YAAY,WAAW,EAAG;AAC9B,QAAI,CAACA,YAAW,QAAQ,GAAG;AACzB,YAAM,IAAI,aAAa,GAAG,QAAQ,8CAA8C;AAAA,IAClF;AACA,eAAW,UAAU,aAAa;AAChC,YAAM,OAAO,OAAO,WAAW;AAC/B,UAAI,EAAE,OAAO,IAAI,IAAI,KAAK,CAAC,GAAG,SAAS,OAAO,YAAY,GAAG;AAC3D,cAAM,IAAI,aAAa,8BAA8B,IAAI,OAAO,OAAO,YAAY,sBAAsB;AAAA,MAC3G;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,SAAwB;AAAA,EAE9B;AAAA,EAEA,MAAc,YACZ,KACA,UACA,QACA,SACA,YACe;AACf,UAAM,QAAkB,CAAC;AACzB,eAAW,UAAU,SAAS;AAC5B,YAAM,OAAO,OAAO,WAAW;AAC/B,YAAM,WAAW,OAAO,IAAI,IAAI,KAAK,CAAC;AAEtC,YAAM,MAAM,SAAS,KAAK,CAAC,MAAM,qBAAqB,OAAO,cAAc,CAAC,CAAC,KAAK,SAAS,CAAC;AAC5F,UAAI,IAAK,OAAM,KAAK,GAAG,IAAI,IAAI,GAAG,EAAE;AAAA,IACtC;AACA,QAAI,MAAM,WAAW,EAAG;AAExB,eAAW,2BAAsB;AACjC,UAAM,KAAK,YAAY,KAAK,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AAE3D,UAAM,QAAQ,mBAAmB,QAAQ;AACzC,eAAW,UAAU,SAAS;AAC5B,YAAM,OAAO,OAAO,WAAW;AAC/B,YAAM,UAAU,MAAM,IAAI,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,qBAAqB,OAAO,UAAU,CAAC,CAAC;AAC3F,UAAI,UAAUC,QAAO,MAAM,OAAO,MAAM,KAAK,WAAW,OAAO,QAAQ;AACrE,mBAAW,WAAW,IAAI,OAAO,OAAO,MAAM,QAAG;AACjD,cAAM,KAAK,YAAY,KAAK,CAAC,MAAM,GAAG,IAAI,IAAI,MAAM,IAAI,aAAa,OAAO,MAAM,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,YAAY,KAAa,MAA+B;AACpE,UAAM,SAAS,MAAM,WAAW,SAAS,CAAC,UAAU,GAAG,IAAI,GAAG,EAAE,KAAK,KAAK,WAAW,kBAAkB,CAAC;AACxG,QAAI,OAAO,aAAa,GAAG;AACzB,YAAM,SAAS,OAAO,WAAW,2BAA2B;AAC5D,YAAM,IAAI,aAAa,QAAQ,KAAK,OAAO,UAAU,OAAO,MAAM,CAAC;AAAA,IACrE;AAAA,EACF;AACF;;;AG9JA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,QAAM,YAAAC,WAAU,WAAAC,gBAAe;AAQxC,IAAMC,qBAAoB,KAAK;AAE/B,IAAM,OAAO,CAAC,GAAW,MAAcC,UAASC,SAAQ,CAAC,GAAGA,SAAQ,CAAC,CAAC,MAAM;AAGrE,SAAS,UAAU,UAAyB,QAAuB,cAAiC,QAA2B;AACpI,QAAM,OAAO,CAAC,SAAS,iBAAiB,GAAI,SAAS,CAAC,UAAU,IAAI,CAAC,CAAE;AACvE,QAAM,eAAeC,OAAK,SAAS,gBAAgB,YAAY;AAC/D,QAAM,WAAWA,OAAK,SAAS,gBAAgB,YAAY;AAC3D,QAAM,kBAAkB,IAAI,IAAI,SAAS,SAAS,IAAI,CAAC,MAAMD,SAAQ,EAAE,aAAa,CAAC,CAAC;AAEtF,MAAI,aAAa,KAAK,CAAC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG;AAEnD,UAAM,gBAAgB,CAAC,gBAAgB,IAAIA,SAAQ,YAAY,CAAC;AAChE,QAAI,iBAAiB,SAAS,SAAS,SAAS,EAAG,QAAO,CAAC,GAAG,MAAM,aAAa;AAAA,EACnF;AAGA,MAAI,aAAa,SAAS,KAAK,aAAa,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAG,QAAO,CAAC,GAAG,MAAM,aAAa;AAE3G,QAAM,UAAU,IAAI;AAAA,IAClB,SAAS,SAAS,OAAO,CAAC,MAAM,aAAa,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EACvG;AACA,MAAI,QAAQ,SAAS,EAAG,SAAQ,IAAI,OAAO,EAAE;AAG7C,WAAS,OAAO,MAAM,QAAQ;AAC5B,WAAO;AACP,eAAW,KAAK,SAAS,UAAU;AACjC,UAAI,QAAQ,IAAI,EAAE,IAAI,EAAG;AACzB,UAAI,EAAE,aAAa,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE,QAAQ,QAAQ,IAAI,EAAE,IAAI,CAAC,GAAG;AAClF,gBAAQ,IAAI,EAAE,IAAI;AAClB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,QAAM,UAAU,SAAS,SAAS,OAAO,CAAC,MAAM,QAAQ,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AACtF,SAAO,CAAC,GAAG,MAAM,GAAG,QAAQ,QAAQ,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC;AAC7D;AAOO,IAAM,2BAAN,MAA2D;AAAA,EAChE,YACmB,OAA0B,EAAE,cAAc,SAAS,CAAC,QAAQE,YAAWD,OAAK,KAAK,YAAY,CAAC,EAAE,GACjH;AADiB;AAAA,EAChB;AAAA,EADgB;AAAA,EAGnB,MAAM,OAAO,QAAuB,SAAiB,UAA+B,CAAC,GAAgC;AACnH,UAAM,MAAM,OAAO,iBAAiB,OAAO,QAAQ;AAEnD,QAAI,QAAQ,cAAc;AACxB,YAAME,SAAQ,QAAQ,eAAe,QAAQ;AAC7C,YAAMC,UAAS,MAAM,eAAe,QAAQ,cAAc,EAAE,KAAK,KAAK,WAAWN,mBAAkB,CAAC;AACpG,aAAOM,QAAO,aAAa,IACvB,EAAE,QAAQ,SAAS,SAAS,kCAAkC,OAAAD,OAAM,IACpE,EAAE,QAAQ,QAAQ,SAAS,KAAKC,QAAO,UAAUA,QAAO,MAAM,GAAG,OAAAD,OAAM;AAAA,IAC7E;AAEA,UAAM,WAAW,MAAM,KAAK,KAAK,aAAa,GAAG;AACjD,UAAM,OAAO,UAAU,UAAU,QAAQ,QAAQ,gBAAgB,CAAC,GAAG,KAAK,KAAK,QAAQ,GAAG,CAAC;AAC3F,UAAM,QAAQ,sBAAsB,KAAK,KAAK,GAAG,CAAC;AAClD,UAAM,SAAS,MAAM,SAAS,MAAM,EAAE,KAAK,KAAK,WAAWL,mBAAkB,CAAC;AAC9E,QAAI,OAAO,aAAa,EAAG,QAAO,EAAE,QAAQ,SAAS,SAAS,oDAAoD,MAAM;AACxH,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,OAAO,WAAW,2BAA2B,YAAY,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM,EAAE;AAAA,MACtG;AAAA,IACF;AAAA,EACF;AACF;;;AhB9EO,IAAM,qBAAoC;AAAA,EAC/C,WAAW,CAAC,MAAMO,SAAO,MAAM,CAAC;AAAA,EAChC,SAAS;AAAA,EACT,MAAM,CAAC,SAAS,WAAYA,SAAO,MAAM,OAAO,KAAKA,SAAO,MAAM,MAAM,IAAKA,SAAO,GAAG,SAAS,MAAM,IAAI,UAAU,UAAU,SAAS,MAAM,IAAK;AAAA;AAAA,EAElJ,qBAAqB;AACvB;AAEO,IAAM,yBAAN,MAA0D;AAAA,EACtD,YAAuB;AAAA,EACvB,cAAc;AAAA,EACd,OAAO;AAAA,EACP,eAAe;AAAA,EACf,aAAa;AAAA,EAEL,SAAS,IAAI,kBAAkB;AAAA,EAC/B,QAAQ,IAAI,iBAAiB;AAAA,EAC7B,WAAW,CAAC,UAA8B,QAAgB,KAAK,OAAO,QAAQ,UAAU,GAAG;AAAA,EAEnG,YAAY,IAAI,4BAA4B;AAAA,EAC5C,WAAW,IAAI,qBAAqB,EAAE,OAAO,KAAK,OAAO,UAAU,KAAK,SAAS,CAAC;AAAA,EAClF,SAAS,IAAI,uBAAuB,EAAE,cAAc,OAAO,KAAK,OAAO,UAAU,KAAK,SAAS,CAAC;AAAA,EAChG,UAAU,IAAI,oBAAoB;AAAA,EAClC,WAAW,IAAI,yBAAyB;AAAA,EAEjD,aAAa,QAAgE,GAAmB;AAC9F,WAAO;AAAA,MACL,KAAK,EAAE,KAAK,IAAI,OAAO,KAAK;AAAA,MAC5B,MAAM,EAAE,KAAK,aAAa,OAAO,SAAS;AAAA,MAC1C,KAAK,EAAE,KAAK,gBAAgB,OAAO,QAAQ;AAAA,IAC7C;AAAA,EACF;AACF;;;AiB1CA,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,WAAAC,UAAS,QAAAC,QAAM,YAAAC,WAAU,WAAAC,iBAAe;;;ACDjD,SAAS,cAAAC,cAAY,eAAAC,cAAa,YAAAC,iBAAgB;AAClD,SAAS,QAAAC,QAAM,WAAAC,gBAAe;;;ACC9B,SAAS,cAAAC,cAAY,gBAAAC,gBAAc,gBAAgB;AACnD,SAAS,WAAAC,UAAS,QAAAC,QAAM,WAAAC,gBAAe;AAkDhC,SAAS,QAAQ,MAAwB;AAC9C,QAAM,SAASC,eAAa,MAAM,MAAM;AACxC,SAAO,SAAS,QAAQ,IAAI;AAC9B;AAGO,SAAS,SAAS,QAAgB,MAAwB;AAC/D,QAAM,UAAU,SAAS,QAAQ,IAAI;AAErC,QAAM,gBAAgB,MAAM,SAAS,QAAQ;AAC7C,QAAM,SAAgC,gBAClC;AAAA,IACE,SAAS,UAAU,eAAe,SAAS,KAAK;AAAA,IAChD,YAAY,UAAU,eAAe,YAAY,KAAK;AAAA,IACtD,SAAS,UAAU,eAAe,SAAS,KAAK;AAAA,IAChD,cAAc,MAAM,eAAe,cAAc,GAAG,KAAK,KAAK;AAAA,IAC9D,gBAAgB,MAAM,eAAe,SAAS;AAAA,EAChD,IACA;AAEJ,QAAM,aAAa,oBAAI,IAAyB;AAChD,aAAW,WAAW,MAAM,SAAS,YAAY,GAAG,YAAY,CAAC,GAAG;AAClE,eAAW,IAAI,QAAQ,MAAM,EAAE,OAAO,QAAQ,KAAK,KAAK,GAAG,QAAQ,CAAC;AAAA,EACtE;AAEA,SAAO;AAAA,IACL;AAAA,IACA,KAAKC,SAAQ,IAAI;AAAA,IACjB,SAAS,UAAU,SAAS,SAAS;AAAA,IACrC,YAAY,UAAU,SAAS,YAAY,KAAK;AAAA,IAChD,SAAS,UAAU,SAAS,SAAS;AAAA,IACrC,gBAAgB,MAAM,SAAS,SAAS;AAAA,IACxC,MAAM,UAAU,SAAS,MAAM;AAAA,IAC/B,WAAW,UAAU,SAAS,WAAW,KAAK;AAAA,IAC9C;AAAA,IACA;AAAA,IACA,cAAc,iBAAiB,MAAM,SAAS,cAAc,CAAC;AAAA,IAC7D,qBAAqB,iBAAiB,QAAQ,SAAS,wBAAwB,cAAc,CAAC;AAAA,IAC9F,SAAS,SAAS,MAAM,SAAS,SAAS,GAAG,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,EACjG;AACF;AAEA,SAAS,iBAAiB,WAAoD;AAC5E,SAAO,SAAS,WAAW,YAAY,EAAE,IAAI,CAAC,aAAa;AAAA,IACzD,SAAS,UAAU,SAAS,SAAS,KAAK;AAAA,IAC1C,YAAY,UAAU,SAAS,YAAY,KAAK;AAAA,IAChD,SAAS,UAAU,SAAS,SAAS;AAAA,IACrC,MAAM,UAAU,SAAS,MAAM;AAAA,IAC/B,YAAY,UAAU,SAAS,YAAY;AAAA,IAC3C,OAAO,UAAU,SAAS,OAAO;AAAA,IACjC,gBAAgB,MAAM,SAAS,SAAS;AAAA,EAC1C,EAAE;AACJ;AAOO,SAAS,cAAc,KAAmC;AAC/D,MAAI,CAAC,IAAI,OAAQ,QAAO;AACxB,QAAM,eAAe,IAAI,OAAO,gBAAgB;AAChD,MAAI,iBAAiB,GAAI,QAAO;AAChC,MAAI,YAAYC,SAAQ,IAAI,KAAK,YAAY;AAC7C,MAAIC,aAAW,SAAS,KAAK,SAAS,SAAS,EAAE,YAAY,EAAG,aAAYC,OAAK,WAAW,SAAS;AACrG,SAAOD,aAAW,SAAS,IAAI,YAAY;AAC7C;AAGA,SAAS,gBAAgB,MAAc,QAAsC;AAC3E,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO,WAAW,OAAO,QAAQ;AAAA,IAC1C,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO,WAAW,OAAO,QAAQ;AAAA,IAC1C,KAAK;AACH,aAAO,OAAO,QAAQ;AAAA,IACxB,KAAK;AACH,aAAO,OAAO,QAAQ;AAAA,IACxB;AACE,aAAO;AAAA,EACX;AACF;AAGO,SAAS,aACd,MACA,OACsD;AACtD,aAAW,OAAO,OAAO;AACvB,UAAM,WAAW,IAAI,WAAW,IAAI,IAAI;AACxC,QAAI,SAAU,QAAO,EAAE,KAAK,SAAS;AAAA,EACvC;AACA,SAAO;AACT;AAOO,SAAS,YAAY,MAAc,OAA4B,QAAQ,GAAW;AACvF,MAAI,QAAQ,MAAM,CAAC,KAAK,SAAS,IAAI,EAAG,QAAO;AAC/C,QAAM,SAAS,MAAM,CAAC;AACtB,QAAM,WAAW,KAAK,QAAQ,kBAAkB,CAAC,YAAY,SAAiB;AAC5E,UAAM,UAAU,SAAS,gBAAgB,MAAM,MAAM,IAAI;AACzD,QAAI,YAAY,OAAW,QAAO;AAClC,WAAO,aAAa,MAAM,KAAK,GAAG,SAAS,SAAS;AAAA,EACtD,CAAC;AACD,SAAO,aAAa,OAAO,OAAO,YAAY,UAAU,OAAO,QAAQ,CAAC;AAC1E;AAGO,SAAS,kBAAkB,MAAkC;AAClE,SAAO,KAAK,MAAM,iBAAiB,IAAI,CAAC;AAC1C;;;ADxKA,IAAM,YAAY;AAClB,IAAM,eAAe,oBAAI,IAAI,CAAC,gBAAgB,UAAU,SAAS,QAAQ,KAAK,CAAC;AAexE,IAAM,eAAN,MAAM,cAAa;AAAA,EAIhB,YACG,SACA,MACT;AAFS;AACA;AAET,eAAW,OAAO,KAAM,MAAK,OAAO,IAAI,IAAI,MAAM,GAAG;AACrD,SAAK,kBAAkB;AAAA,EACzB;AAAA,EALW;AAAA,EACA;AAAA,EALM,SAAS,oBAAI,IAAsB;AAAA,EACnC,cAAc,oBAAI,IAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAevD,OAAO,KAAK,SAA+B;AACzC,UAAM,OAAmB,CAAC;AAC1B,UAAM,QAAQ,aAAa,OAAO;AAClC,UAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,OAAO,MAAM,MAAM;AACzB,UAAI;AACJ,UAAI;AACF,cAAM,QAAQ,IAAI;AAAA,MACpB,QAAQ;AAEN;AAAA,MACF;AACA,WAAK,KAAK,GAAG;AACb,iBAAW,SAAS,IAAI,SAAS;AAC/B,cAAM,SAASE,SAAQ,IAAI,KAAK,KAAK;AACrC,cAAM,aAAa,OAAO,SAAS,MAAM,IAAI,SAASC,OAAK,QAAQ,SAAS;AAC5E,YAAI,CAAC,KAAK,IAAI,UAAU,KAAKC,aAAW,UAAU,GAAG;AACnD,eAAK,IAAI,UAAU;AACnB,gBAAM,KAAK,UAAU;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AACA,WAAO,IAAI,cAAa,SAAS,IAAI;AAAA,EACvC;AAAA,EAEA,MAAM,MAAoC;AACxC,WAAO,KAAK,OAAO,IAAIF,SAAQ,IAAI,CAAC;AAAA,EACtC;AAAA;AAAA,EAGA,QAAQ,KAAyB;AAC/B,UAAM,OAAmB,CAAC,GAAG;AAC7B,QAAI,UAAU;AACd,WAAO,QAAQ,QAAQ;AACrB,YAAM,SAAS,KAAK,cAAc,OAAO;AACzC,UAAI,CAAC,UAAU,KAAK,SAAS,MAAM,GAAG;AACpC,eAAO,EAAE,MAAM,gBAAgB,SAAS,SAAY,QAAQ,OAAO;AAAA,MACrE;AACA,WAAK,KAAK,MAAM;AAChB,gBAAU;AAAA,IACZ;AACA,WAAO,EAAE,KAAK;AAAA,EAChB;AAAA;AAAA,EAGA,cAAc,KAA+B;AAC3C,UAAM,QAAQ,KAAK,QAAQ,GAAG,EAAE;AAChC,UAAM,UAAU,IAAI,WAAW,IAAI,QAAQ,WAAW;AACtD,UAAM,aAAa,IAAI,WAAW,IAAI,QAAQ;AAC9C,UAAM,UAAU,aAAa,YAAY,YAAY,KAAK,IAAI;AAC9D,WAAO;AAAA,MACL,SAAS,YAAY,SAAS,KAAK;AAAA,MACnC,YAAY,IAAI;AAAA,MAChB,SAAS,WAAW,CAAC,QAAQ,SAAS,IAAI,IAAI,UAAU;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA,EAGA,gBAAgB,KAAmC;AACjD,WAAO,KAAK,YAAY,IAAI,IAAI,IAAI;AAAA,EACtC;AAAA,EAEQ,cAAc,KAAqC;AACzD,UAAM,SAAS,IAAI;AACnB,QAAI,CAAC,OAAQ,QAAO;AAKpB,UAAM,UAAU,CAAC,cAAoC;AACnD,UAAI,CAAC,UAAW,QAAO;AACvB,YAAM,UAAU,YAAY,UAAU,WAAW,UAAU,QAAQ,WAAW,IAAI,CAAC,SAAS,CAAC;AAC7F,YAAM,UAAU,YAAY,UAAU,WAAW,UAAU,QAAQ,WAAW,IAAI,CAAC,SAAS,CAAC;AAC7F,YAAM,WAAW,YAAY,OAAO,SAAS,CAAC,GAAG,CAAC;AAClD,aACE,YAAY,OAAO,WACnB,UAAU,eAAe,OAAO,eAC/B,QAAQ,SAAS,IAAI,KAAK,SAAS,SAAS,IAAI,KAAK,YAAY;AAAA,IAEtE;AAIA,UAAM,OAAO,cAAc,GAAG;AAC9B,UAAM,SAAS,OAAO,KAAK,OAAO,IAAIA,SAAQ,IAAI,CAAC,IAAI;AACvD,WAAO,QAAQ,MAAM,IAAI,SAAS;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAA0B;AAChC,UAAM,iBAAiB,KAAK,KACzB,OAAO,CAAC,QAAQ,IAAI,QAAQ,SAAS,CAAC,EACtC,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,SAAS,EAAE,IAAI,MAAM;AAE7C,eAAW,cAAc,gBAAgB;AACvC,UAAI,KAAK,YAAY,IAAI,WAAW,IAAI,EAAG;AAC3C,YAAM,QAAoB,CAAC,UAAU;AACrC,aAAO,MAAM,SAAS,GAAG;AACvB,cAAM,MAAM,MAAM,MAAM;AACxB,YAAI,KAAK,YAAY,IAAI,IAAI,IAAI,EAAG;AACpC,aAAK,YAAY,IAAI,IAAI,MAAM,WAAW,GAAG;AAC7C,mBAAW,SAAS,IAAI,SAAS;AAC/B,gBAAM,SAASA,SAAQ,IAAI,KAAK,KAAK;AACrC,gBAAM,OAAO,OAAO,SAAS,MAAM,IAAI,SAASC,OAAK,QAAQ,SAAS;AACtE,gBAAM,YAAY,KAAK,OAAO,IAAI,IAAI;AACtC,cAAI,UAAW,OAAM,KAAK,SAAS;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,aAAa,SAA2B;AAC/C,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAAUA,OAAK,SAAS,SAAS;AACvC,MAAIC,aAAW,OAAO,EAAG,SAAQ,KAAKF,SAAQ,OAAO,CAAC;AAEtD,QAAM,OAAO,CAAC,KAAa,UAAkB;AAC3C,QAAI,QAAQ,UAAW;AACvB,QAAIG;AACJ,QAAI;AACF,MAAAA,WAAUC,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IACpD,QAAQ;AACN;AAAA,IACF;AACA,UAAM,YAAYF,aAAWD,OAAK,KAAK,SAAS,CAAC;AACjD,eAAW,SAASE,UAAS;AAC3B,UAAI,CAAC,MAAM,YAAY,KAAK,MAAM,KAAK,WAAW,GAAG,KAAK,aAAa,IAAI,MAAM,IAAI,EAAG;AAGxF,UAAI,aAAa,MAAM,SAAS,MAAO;AACvC,YAAM,SAASF,OAAK,KAAK,MAAM,IAAI;AACnC,YAAM,MAAMA,OAAK,QAAQ,SAAS;AAClC,UAAIC,aAAW,GAAG,KAAKG,UAAS,GAAG,EAAE,OAAO,EAAG,SAAQ,KAAKL,SAAQ,GAAG,CAAC;AACxE,WAAK,QAAQ,QAAQ,CAAC;AAAA,IACxB;AAAA,EACF;AAEA,OAAK,SAAS,CAAC;AACf,SAAO;AACT;;;ADlLO,IAAM,8BAAN,MAAiE;AAAA;AAAA;AAAA;AAAA;AAAA,EAKtE,SAAS,UAAkB,aAAqD;AAC9E,QAAI,MAAMM,UAAQ,QAAQ;AAC1B,QAAI,CAACC,aAAWC,OAAK,KAAK,SAAS,CAAC,EAAG,QAAO;AAC9C,UAAM,WAAW,cAAcF,UAAQ,WAAW,IAAI;AACtD,eAAS;AACP,YAAM,QAAQ,SAAS,KAAK,QAAQ;AACpC,UAAI,CAAC,MAAO,QAAO;AACnB,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,SAA2C;AACxD,UAAM,UAAU,aAAa,KAAK,OAAO;AAEzC,UAAM,UAAU,QAAQ,KAAK,IAAI,CAAC,QAAuB;AACvD,YAAM,cAAc,QAAQ,cAAc,GAAG;AAC7C,YAAM,UAAUG,UAAS,SAAS,IAAI,GAAG,EAAE,QAAQ,OAAO,GAAG;AAC7D,aAAO;AAAA,QACL,IAAI,YAAY,UAAU,GAAG,YAAY,OAAO,IAAI,YAAY,UAAU,KAAK,YAAY;AAAA,QAC3F,MAAM,IAAI,OAAO,YAAY,IAAI,MAAM,QAAQ,QAAQ,GAAG,EAAE,IAAI,IAAI,IAAI;AAAA,QACxE,MAAM,IAAI;AAAA,QACV,SAAS,WAAW;AAAA,QACpB,WAAW;AAAA,QACX,QAAQ,YAAY;AAAA,QACpB,SAAS,YAAY;AAAA,QACrB,eAAe,QAAQ,gBAAgB,GAAG;AAAA,MAC5C;AAAA,IACF,CAAC;AAED,YAAQ,KAAK,CAAC,GAAG,MAAO,EAAE,SAAS,KAAK,EAAE,SAAS,IAAI,EAAE,QAAQ,cAAc,EAAE,OAAO,CAAE;AAC1F,WAAO;AAAA,EACT;AACF;AAGA,SAAS,WAAW,MAAoC;AACtD,MAAI;AACF,WAAO,QAAQ,IAAI;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,gBAAgB,KAAa,UAAwC;AAC5E,QAAM,SAAmB,CAAC;AAC1B,MAAI,UAAU;AACd,SAAO,YAAY,UAAU;AAC3B,UAAM,SAASC,SAAQ,OAAO;AAC9B,QAAI,WAAW,QAAS;AACxB,WAAO,KAAK,MAAM;AAClB,cAAU;AAAA,EACZ;AACA,SAAO;AACT;AAMA,SAAS,SAAS,KAAa,UAAkD;AAC/E,QAAM,MAAM,WAAWF,OAAK,KAAK,SAAS,CAAC;AAC3C,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,YAAY,gBAAgB,KAAK,QAAQ;AAC/C,QAAM,QAAkB,CAAC;AAEzB,QAAM,aAAa,cAAc,GAAG;AACpC,MAAI,cAAc,IAAI,UAAU,UAAU,SAASE,SAAQ,UAAU,CAAC,GAAG;AACvE,UAAM,SAAS,WAAW,UAAU;AACpC,UAAM,UAAU,QAAQ,WAAW,QAAQ,QAAQ;AACnD,QAAI,UAAU,OAAO,eAAe,IAAI,OAAO,cAAc,YAAY,IAAI,OAAO,SAAS;AAC3F,YAAM,KAAKA,SAAQ,UAAU,CAAC;AAAA,IAChC;AAAA,EACF;AAEA,QAAM,UAAUF,OAAK,KAAK,SAAS;AACnC,QAAM,aAAa,UAAU;AAAA,IAAK,CAAC,aACjC,WAAWA,OAAK,UAAU,SAAS,CAAC,GAAG,QAAQ,KAAK,CAAC,UAAU;AAC7D,YAAM,SAASF,UAAQ,UAAU,KAAK;AACtC,aAAO,WAAW,OAAO,WAAW;AAAA,IACtC,CAAC;AAAA,EACH;AACA,MAAI,WAAY,OAAM,KAAK,UAAU;AAGrC,SAAO,MAAM,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACpD;;;AGhGA,SAAS,cAAAK,oBAAkB;AAC3B,SAAS,QAAAC,cAAY;;;ACFrB,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,WAAAC,UAAS,cAAAC,aAAY,QAAAC,QAAM,YAAAC,WAAU,WAAAC,WAAS,WAAW;AAQ3D,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAC/C,cAAc;AACZ,UAAM,0FAA0F;AAChG,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC3C,YAAY,SAA0B,QAAgB;AACpD,UAAM,OAAO;AADuB;AAEpC,SAAK,OAAO;AAAA,EACd;AAAA,EAHsC;AAIxC;AAEA,IAAMC,cAAa,QAAQ,aAAa;AACxC,IAAM,UAAUA,cAAa,aAAa;AAG1C,IAAM,aAAa,CAAC,MAAM,wBAAwB;AAElD,IAAI;AAMG,SAAS,iBAAiB,SAAiB,SAAqC;AACrF,MAAI,MAAMC,UAAQ,OAAO;AACzB,QAAM,OAAOA,UAAQ,OAAO;AAC5B,aAAS;AACP,UAAM,YAAYC,OAAK,KAAK,OAAO;AACnC,QAAIC,aAAW,SAAS,EAAG,QAAO;AAClC,QAAI,QAAQ,QAAQC,UAAS,MAAM,GAAG,EAAE,WAAW,IAAI,EAAG,QAAO;AACjE,UAAM,SAASC,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;AAYA,eAAsB,SAAS,MAAgB,SAA8C;AAC3F,QAAM,UAAU,iBAAiB,QAAQ,KAAK,QAAQ,OAAO;AAC7D,QAAM,MAAM,EAAE,KAAK,QAAQ,KAAK,WAAW,QAAQ,UAAU;AAE7D,MAAI,SAAS;AAGX,UAAM,kBAAkB,cAAc,QAAQ,KAAK,OAAO;AAC1D,UAAM,OAAOC,YAAW,eAAe,KAAK,gBAAgB,SAAS,GAAG,IAAI,kBAAkB,IAAI,GAAG,GAAG,eAAe;AAEvH,WAAON,cACH,WAAW,MAAM,CAAC,GAAG,YAAY,GAAG,IAAI,GAAG,GAAG,IAC9C,WAAW,MAAM,CAAC,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,GAAG;AAAA,EAC1D;AAEA,gBAAc,WAAW,OAAO,CAAC,IAAI,GAAG,EAAE,KAAK,QAAQ,KAAK,WAAW,IAAO,CAAC,EAAE;AAAA,IAC/E,CAAC,WAAW,OAAO,aAAa;AAAA,IAChC,MAAM;AAAA,EACR;AACA,MAAI,CAAE,MAAM,UAAY,OAAM,IAAI,sBAAsB;AAExD,SAAO,WAAW,OAAO,CAAC,GAAG,YAAY,GAAG,IAAI,GAAG,GAAG;AACxD;AAGO,SAAS,YAAY,QAAwB;AAClD,QAAM,SAAS,OACZ,MAAM,OAAO,EACb,OAAO,CAAC,SAAS,KAAK,WAAW,SAAS,CAAC,EAC3C,IAAI,CAAC,SAAS,KAAK,QAAQ,iBAAiB,EAAE,CAAC,EAC/C,OAAO,CAAC,SAAS,KAAK,KAAK,KAAK,CAAC,KAAK,WAAW,IAAI,KAAK,CAAC,KAAK,SAAS,cAAc,CAAC;AAC3F,UAAQ,OAAO,SAAS,IAAI,SAAS,OAAO,KAAK,EAAE,MAAM,OAAO,EAAE,MAAM,GAAG,GAAG,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI;AACtG;;;ACjFA,SAAS,kBAAkB;AAC3B,SAAS,cAAAO,cAAY,WAAW,gBAAAC,gBAAc,eAAAC,cAAa,QAAQ,iBAAAC,sBAAqB;AACxF,SAAS,QAAAC,cAAY;AAcd,IAAM,wBAA6C,EAAE,MAAM,SAAS,UAAU,SAAS;AAE9F,IAAM,iBAAiB;AACvB,IAAM,qBAAqB;AAG3B,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,8BAAN,cAA0C,kBAAkB;AAAA,EACjE,YACE,QACA,QACA;AACA;AAAA,MACE,4BAA4B,OAAO,EAAE,IAAI,OAAO,OAAO,2BAA2B,OAAO,OAAO,+JAEvB,OAAO,GAAG;AAAA,EACrD,YAAY,MAAM,CAAC;AAAA,MACjD;AAAA,IACF;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAGA,SAAS,oBAAoB,QAAgB,UAA2B;AACtE,SAAO,OAAO,MAAM,OAAO,EAAE,KAAK,CAAC,SAAS;AAC1C,UAAM,QAAQ,KAAK,YAAY;AAC/B,WAAO,KAAK,SAAS,QAAQ,KAAK,kBAAkB,KAAK,CAAC,WAAW,MAAM,SAAS,MAAM,CAAC;AAAA,EAC7F,CAAC;AACH;AAEA,IAAM,mBAAmB,IAAI;AAuCtB,IAAM,mBAAN,MAAuB;AAAA,EACnB;AAAA,EACQ;AAAA,EACA;AAAA,EAEjB,YAAY,WAAmB;AAC7B,SAAK,SAASC,OAAK,WAAW,QAAQ;AACtC,SAAK,gBAAgB,CAACC,aAAW,KAAK,MAAM;AAC5C,SAAK,OAAOD,OAAK,KAAK,QAAQ,YAAY,WAAW,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE;AACpE,cAAU,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AAAA,EAEA,UAAgB;AACd,WAAO,KAAK,MAAM,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAClD,QAAI;AACF,UAAI,KAAK,iBAAiBE,aAAY,KAAK,MAAM,EAAE,WAAW,EAAG,QAAO,KAAK,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1G,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAQA,eAAsB,kBACpB,SACA,WACA,SACA,SACA,SACA,YAAY,OAC0B;AACtC,QAAM,SAASF,OAAK,QAAQ,MAAM,mBAAmB;AAGrD,QAAM,OAAO;AAAA,IACX;AAAA,IACA,cAAc,WAAW,OAAO;AAAA,IAChC,GAAG,cAAc,IAAI,QAAQ,IAAI;AAAA,IACjC,YAAY,cAAc,WAAW,MAAM,CAAC;AAAA,EAC9C;AACA,QAAM,SAAS,MAAM,SAAS,YAAY,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG;AAAA,IAChE,KAAK;AAAA,IACL;AAAA,IACA,WAAW;AAAA,EACb,CAAC;AAED,MAAI,OAAO,aAAa,KAAK,CAACC,aAAW,MAAM,GAAG;AAChD,UAAM,OAAO,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM;AAC/C,QAAI,oBAAoB,MAAM,cAAc,GAAG;AAC7C,YAAM,IAAI;AAAA,QACR,EAAE,IAAI,gBAAgB,SAAS,QAAQ,MAAM,KAAK,QAAQ,SAAS,yBAAyB;AAAA,QAC5F;AAAA,MACF;AAAA,IACF;AACA,UAAM,IAAI,kBAAkB;AAAA,EAA6C,YAAY,IAAI,CAAC,IAAI,IAAI;AAAA,EACpG;AACA,SAAO,mBAAmBE,eAAa,QAAQ,MAAM,CAAC;AACxD;AAGO,SAAS,mBAAmB,QAA6C;AAC9E,QAAM,OAAO,SAAS,MAAM;AAC5B,QAAM,WAAW,KAAK,SAAS,aAAa,SAAS,MAAM,SAAS,IAAI,CAAC,IAAI;AAC7E,QAAM,SAAS,oBAAI,IAA4B;AAC/C,aAAW,WAAW,UAAU;AAC9B,WAAO,IAAI,GAAG,UAAU,SAAS,SAAS,CAAC,IAAI,UAAU,SAAS,YAAY,CAAC,IAAI,iBAAiB,OAAO,CAAC;AAAA,EAC9G;AACA,SAAO;AACT;AAUO,SAAS,kBAAkB,QAAmD;AACnF,QAAMC,SAAQ,CAAC,MAAc,SAAgF;AAC3G,UAAM,OAAO,oBAAI,IAAwB;AACzC,eAAW,WAAW,OAAO,IAAI,IAAI,GAAG;AACtC,iBAAW,cAAc,SAAS,YAAY,CAAC,GAAG;AAChD,cAAM,KAAK,UAAU,YAAY,IAAI,KAAK,UAAU,YAAY,KAAK,KAAK;AAC1E,YAAI,CAAC,KAAK,IAAI,EAAE,EAAG,MAAK,IAAI,IAAI,UAAU;AAAA,MAC5C;AAAA,IACF;AACA,WAAO,KAAK,OAAO,IAAI,EAAE,MAAM,YAAY,CAAC,GAAG,UAAU,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI;AAAA,EAC5F;AACA,SAAO;AAAA,IACL,cAAc,CAAC;AAAA,IACf,qBAAqB,CAAC;AAAA,IACtB,cAAcA,OAAM,gBAAgB,CAAC,MAAM,EAAE,YAAY;AAAA,IACzD,oBAAoBA,OAAM,sBAAsB,CAAC,MAAM,EAAE,kBAAkB;AAAA,EAC7E;AACF;AAEA,SAAS,iBAAiB,SAAqC;AAC7D,SAAO;AAAA,IACL,cAAc,0BAA0B,MAAM,SAAS,cAAc,CAAC;AAAA,IACtE,qBAAqB,0BAA0B,QAAQ,SAAS,wBAAwB,cAAc,CAAC;AAAA,IACvG,cAAc,MAAM,SAAS,cAAc;AAAA,IAC3C,oBAAoB,MAAM,SAAS,oBAAoB;AAAA,EACzD;AACF;AAEA,SAAS,0BAA0B,WAA0D;AAC3F,SAAO,SAAS,WAAW,YAAY,EAAE,IAAI,CAAC,aAAa;AAAA,IACzD,SAAS,UAAU,SAAS,SAAS,KAAK;AAAA,IAC1C,YAAY,UAAU,SAAS,YAAY,KAAK;AAAA,IAChD,SAAS,UAAU,SAAS,SAAS,KAAK;AAAA,IAC1C,OAAO,UAAU,SAAS,OAAO,KAAK;AAAA,IACtC,MAAM,UAAU,SAAS,MAAM,KAAK;AAAA,IACpC,YAAY,UAAU,SAAS,YAAY;AAAA,EAC7C,EAAE;AACJ;AAGO,SAAS,cAAc,WAAqC,OAA+B;AAChG,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAMC,WAAoB,CAAC;AAC3B,aAAW,YAAY,WAAW;AAChC,UAAM,MAAM,GAAG,SAAS,OAAO,IAAI,SAAS,UAAU,IAAI,SAAS,QAAQ,KAAK,IAAI,SAAS,cAAc,EAAE;AAC7G,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,UAAM,SAAS;AAAA,MACb,YAAY,UAAU,SAAS,OAAO,CAAC;AAAA,MACvC,eAAe,UAAU,SAAS,UAAU,CAAC;AAAA,MAC7C,YAAY,UAAU,SAAS,OAAO,CAAC;AAAA,MACvC,SAAS,QAAQ,SAAS,SAAS,QAAQ,SAAS,UAAU,SAAS,IAAI,CAAC,YAAY;AAAA,MACxF,SAAS,aAAa,eAAe,UAAU,SAAS,UAAU,CAAC,kBAAkB;AAAA,IACvF,EAAE,OAAO,OAAO;AAChB,IAAAA,SAAQ,KAAK,qBAAqB,OAAO,KAAK,EAAE,CAAC,eAAe;AAAA,EAClE;AAEA,QAAM,eAAe,CAAC,MAAM,cAAc,MAAM,kBAAkB,EAC/D,OAAO,CAAC,YAAmC,YAAY,MAAS,EAChE,IAAI,CAAC,YAAY,aAAa,SAAS,IAAI,CAAC,EAC5C,KAAK,IAAI;AAEZ,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAGA;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EACG,OAAO,CAAC,SAAS,SAAS,EAAE,EAC5B,KAAK,IAAI;AACd;AAGA,eAAsB,mBACpB,WACA,OACA,WACA,SACA,SACA,SACwB;AACxB,MAAI,UAAU,WAAW,EAAG,QAAO,EAAE,eAAe,oBAAI,IAAI,GAAG,eAAe,oBAAI,IAAI,EAAE;AAExF,QAAM,WAAWC,OAAK,QAAQ,MAAM,OAAO;AAC3C,YAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AACvC,QAAM,WAAWA,OAAK,UAAU,SAAS;AACzC,EAAAC,eAAc,UAAU,cAAc,WAAW,KAAK,GAAG,MAAM;AAE/D,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,MACE;AAAA,MACA;AAAA,MACA,cAAc,WAAW,QAAQ;AAAA,MACjC,GAAG,kBAAkB,IAAI,QAAQ,QAAQ;AAAA,MACzC;AAAA,MACA;AAAA,IACF;AAAA,IACA,EAAE,KAAK,WAAW,SAAS,WAAW,iBAAiB;AAAA,EACzD;AAEA,QAAM,MAAM,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM;AAC9C,QAAM,aAAaD,OAAK,UAAU,UAAU,+BAA+B;AAC3E,MAAI,OAAO,aAAa,KAAK,CAACE,aAAW,UAAU,GAAG;AACpD,QAAI,oBAAoB,KAAK,kBAAkB,GAAG;AAChD,YAAM,IAAI;AAAA,QACR,EAAE,IAAI,oBAAoB,SAAS,QAAQ,UAAU,KAAK,YAAY,SAAS,yBAAyB;AAAA,QACxG;AAAA,MACF;AAAA,IACF;AACA,UAAM,IAAI,kBAAkB;AAAA,EAA4C,YAAY,GAAG,CAAC,IAAI,GAAG;AAAA,EACjG;AAEA,SAAO;AAAA,IACL,eAAe,mBAAmBC,eAAa,YAAY,MAAM,CAAC;AAAA,IAClE,eAAe,mBAAmB,GAAG;AAAA,EACvC;AACF;AAGO,SAAS,mBAAmB,QAAuC;AACxE,QAAM,SAAS,SAAS,MAAM;AAC9B,QAAM,WAAW;AAAA,IACf,GAAG,SAAS,MAAM,QAAQ,uBAAuB,GAAG,sBAAsB;AAAA,IAC1E,GAAG,SAAS,MAAM,QAAQ,cAAc,GAAG,YAAY;AAAA,EACzD;AAEA,QAAM,SAAS,oBAAI,IAAsB;AACzC,aAAW,SAAS,UAAU;AAC5B,UAAM,MAAM,GAAG,UAAU,OAAO,SAAS,CAAC,IAAI,UAAU,OAAO,YAAY,CAAC;AAC5E,UAAM,WAAW;AAAA,MACf,GAAG,QAAQ,OAAO,mBAAmB,gBAAgB;AAAA,MACrD,GAAG,QAAQ,OAAO,gBAAgB,aAAa;AAAA,MAC/C,GAAG,QAAQ,OAAO,UAAU,OAAO;AAAA,MACnC,GAAG,QAAQ,OAAO,UAAU,OAAO;AAAA,IACrC;AACA,UAAM,QAAQ,OAAO,IAAI,GAAG,KAAK,CAAC;AAClC,eAAW,WAAW,SAAU,KAAI,CAAC,MAAM,SAAS,OAAO,EAAG,OAAM,KAAK,OAAO;AAChF,WAAO,IAAI,KAAK,KAAK;AAAA,EACvB;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAmB,WAAmB,MAAwB;AAC7E,SAAO,SAAS,MAAM,OAAO,SAAS,GAAG,IAAI,EAC1C,IAAI,CAAC,YAAY,QAAQ,KAAK,KAAK,CAAC,EACpC,OAAO,OAAO;AACnB;AAOO,SAAS,mBAAmB,KAA0B;AAC3D,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,UAAU;AAChB,aAAW,SAAS,IAAI,SAAS,OAAO,EAAG,QAAO,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE;AAC/E,SAAO;AACT;;;AFxVA,IAAM,gBAAgB;AAEtB,IAAM,kBAAkC,EAAE,cAAc,CAAC,GAAG,qBAAqB,CAAC,EAAE;AAE7E,IAAM,uBAAN,MAAmD;AAAA,EACxD,YAA6B,UAA+B,uBAAuB;AAAtD;AAAA,EAAuD;AAAA,EAAvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,MAAM,kBAA6C;AACjD,WAAO,EAAE,KAAK,yDAAyD,UAAU,MAAM;AAAA,EACzF;AAAA,EAEA,MAAM,iBACJ,YACA,UAA0B,UAC1B,MAAM,QAAQ,IAAI,GACM;AACxB,UAAM,WAAW,MAAM,KAAK,eAAe,YAAY,GAAG;AAC1D,WAAO,SAAS,KAAK,CAAC,MAAM,YAAY,SAAS,CAAC,oBAAoB,CAAC,CAAC,KAAK;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,eAAe,YAAkC,MAAM,QAAQ,IAAI,GAAsB;AAC7F,QAAI,CAAC,WAAW,SAAS,CAAC,WAAW,SAAU,QAAO,CAAC;AACvD,UAAM,MAAM,GAAG,WAAW,KAAK,IAAI,WAAW,QAAQ;AAEtD,UAAM,UAAU,IAAI,iBAAiB,GAAG;AACxC,QAAI;AACF,YAAM,eAAe,MAAM,oBAAoB,KAAK,SAAS,KAAK,OAAO;AACzE,YAAM,SAAS,MAAM;AAAA,QACnB,CAAC,EAAE,SAAS,WAAW,OAAO,YAAY,WAAW,UAAU,SAAS,cAAc,CAAC;AAAA,QACvF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,MACP;AACA,YAAM,WAAW,OAAO,cAAc,IAAI,GAAG,KAAK,CAAC;AACnD,UAAI,SAAS,WAAW,KAAK,OAAO,cAAc,IAAI,GAAG,GAAG;AAC1D,cAAM,IAAI,kBAAkB,wDAAwD,GAAG,KAAK,EAAE;AAAA,MAChG;AACA,aAAO,CAAC,GAAG,QAAQ,EAAE,QAAQ;AAAA,IAC/B,UAAE;AACA,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AACF;AAOA,eAAe,oBACb,KACA,SACA,SACyB;AACzB,QAAM,UAAUC,OAAK,KAAK,SAAS;AACnC,MAAI,CAACC,aAAW,OAAO,EAAG,QAAO;AACjC,QAAM,SAAS,MAAM,kBAAkB,SAAS,KAAK,KAAK,SAAS,OAAO;AAC1E,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,CAAC,KAAK;AACpC;;;AGtEA,SAAS,QAAAC,cAAY;AAWrB,OAAOC,cAAY;;;ACjBnB,SAAS,YAAAC,iBAAgB;AAwBlB,SAAS,wBACd,OACA,QACA,SACmB;AACnB,aAAW,OAAO,OAAO;AACvB,UAAM,aAAa,eAAe,IAAI,cAAc,QAAQ,KAAK;AACjE,QAAI,CAAC,WAAY;AAEjB,QAAI,CAAC,WAAW,eAAgB;AAChC,WAAO,eAAe,KAAK,cAAc,WAAW,gBAAgB,OAAO,QAAQ,OAAO;AAAA,EAC5F;AACA,SAAO,qBAAqB,OAAO,QAAQ,OAAO;AACpD;AAGO,SAAS,qBACd,OACA,QACA,SACmB;AACnB,aAAW,OAAO,OAAO;AACvB,UAAM,UAAU,eAAe,IAAI,qBAAqB,QAAQ,KAAK;AACrE,QAAI,SAAS,gBAAgB;AAC3B,aAAO,eAAe,KAAK,yBAAyB,QAAQ,gBAAgB,OAAO,QAAQ,OAAO;AAAA,IACpG;AAAA,EACF;AACA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;AAGO,SAAS,oBAAoB,QAAkB,QAAgB,SAAoC;AACxG,QAAM,UAAU,OAAO,QAAQ;AAC/B,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,OAAO,OAAO,QAAQ,wBAAwB,QAAQ,kCAAkC;AAAA,EACnG;AACA,SAAO,eAAe,QAAQ,UAAU,SAAS,CAAC,MAAM,GAAG,QAAQ,OAAO;AAC5E;AAEA,SAAS,eACP,cACA,QACA,OAC2B;AAC3B,SAAO,aAAa;AAAA,IAClB,CAAC,QACC,IAAI,UAAU,YACd,YAAY,IAAI,SAAS,KAAK,MAAM,OAAO,WAC3C,YAAY,IAAI,YAAY,KAAK,MAAM,OAAO;AAAA,EAClD;AACF;AAQA,SAAS,eACP,KACA,MACA,gBACA,OACA,QACA,SACmB;AACnB,MAAI,OAAO,IAAI;AACf,MAAI,UAAU;AACd,MAAI,QAAQ,eAAe,KAAK,KAAK;AACrC,MAAI;AAEJ,WAAS,QAAQ,GAAG,QAAQ,IAAI,SAAS;AACvC,UAAM,YAAY,kBAAkB,KAAK;AACzC,QAAI,CAAC,UAAW;AAChB,QAAI,UAAU,WAAW,UAAU,KAAK,UAAU,WAAW,MAAM,GAAG;AACpE,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,gCAAgC,SAAS;AAAA,MACnD;AAAA,IACF;AACA,UAAM,aAAa,aAAa,WAAW,KAAK;AAChD,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,eAAe,SAAS;AAAA,MAClC;AAAA,IACF;AACA,WAAO,WAAW,IAAI;AACtB,cAAU,WAAW,SAAS;AAC9B,YAAQ,WAAW,SAAS;AAC5B,mBAAe;AAAA,EACjB;AAEA,MAAI,MAAM,SAAS,IAAI,GAAG;AACxB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ,YAAY,KAAK;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,UAAU,OAAO,kBAAkB;AACrC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ,aAAa,KAAK,yBAAyB,OAAO,gBAAgB;AAAA,IAC5E;AAAA,EACF;AAEA,QAAM,cAAkC;AAAA,IACtC;AAAA,IACA,MAAM,eAAe,aAAa;AAAA,IAClC;AAAA,IACA,aAAaC,UAAS,SAAS,IAAI,EAAE,QAAQ,OAAO,GAAG;AAAA,EACzD;AACA,SAAO,EAAE,OAAO,MAAM,aAAa,SAAS,MAAM;AACpD;;;ADtHA,IAAMC,cAAqC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,EAAE;AA+BnE,IAAM,yBAAN,MAA6D;AAAA,EAClE,YAA6B,UAA+B,uBAAuB;AAAtD;AAAA,EAAuD;AAAA,EAAvD;AAAA,EAE7B,MAAM,KAAK,QAAuB,SAA2C;AAC3E,UAAM,UAAU,MAAM,KAAK,SAAS,CAAC,MAAM,GAAG,OAAO;AACrD,WAAO,QAAQ,IAAI,MAAM,KAAK,EAAE,YAAY,CAAC,GAAG,SAAS,CAAC,EAAE;AAAA,EAC9D;AAAA,EAEA,MAAM,SAAS,SAAmC,SAA+D;AAC/G,UAAM,UAAU,aAAa,KAAK,QAAQ,OAAO;AACjD,UAAM,UAAU,oBAAI,IAA+B;AAEnD,eAAW,SAAS,aAAa,SAAS,OAAO,GAAG;AAClD,YAAM,UAAU,IAAI,iBAAiB,MAAM,GAAG;AAC9C,UAAI;AACF,mBAAW,CAAC,QAAQ,MAAM,KAAK,MAAM,KAAK,UAAU,SAAS,OAAO,SAAS,OAAO,GAAG;AACrF,kBAAQ,IAAI,QAAQ,MAAM;AAAA,QAC5B;AAAA,MACF,UAAE;AACA,gBAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,UACZ,SACA,OACA,SACA,SACyC;AACzC,UAAM,UAAU,QAAQ;AACxB,UAAM,kBAAkB,MAAM,gBAC1B,MAAM,kBAAkB,MAAM,eAAe,MAAM,KAAK,SAAS,SAAS,KAAK,SAAS,IAAI,IAC5F,MAAM,kBAAkB,MAAM,QAAQ,CAAC,EAAG,IAAI,MAAM,MAAM,KAAK,SAAS,SAAS,KAAK,OAAO;AAEjG,UAAM,QAAsB,CAAC;AAC7B,eAAW,EAAE,QAAQ,IAAI,KAAK,MAAM,SAAS;AAC3C,YAAM,cAAc,QAAQ,cAAc,GAAG;AAG7C,YAAM,YACJ,gBAAgB,IAAI,GAAG,YAAY,OAAO,IAAI,YAAY,UAAU,EAAE,MACrE,MAAM,gBACH,CAAC,IAAI,MAAM,kBAAkB,IAAI,MAAM,OAAO,MAAM,SAAS,SAAS,KAAK,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC,IAChG,CAAC,GAAG,gBAAgB,OAAO,CAAC,EAAE,CAAC;AACrC,UAAI,CAAC,UAAW;AAChB,YAAM,KAAK,WAAW,SAAS,KAAK,QAAQ,WAAW,OAAO,CAAC;AAAA,IACjE;AAEA,UAAM,QAAQ,MAAM,QAAQ,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,EAAE,QAAQ,MAAM,OAAO,CAAC;AAChF,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,kBAAkB,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC;AAAA,MACrD,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAEA,WAAO,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,QAAQ,aAAa,MAAM,QAAQ,QAAQ,OAAO,CAAC,CAAC,CAAC;AAAA,EAChG;AACF;AAOA,SAAS,aAAa,SAAuB,SAAgD;AAC3F,QAAM,SAAS,oBAAI,IAAuB;AAC1C,QAAM,eAAe,oBAAI,IAAoB;AAC7C,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,cAAe,cAAa,IAAI,OAAO,gBAAgB,aAAa,IAAI,OAAO,aAAa,KAAK,KAAK,CAAC;AAAA,EACpH;AAEA,aAAW,UAAU,SAAS;AAC5B,UAAM,MAAM,QAAQ,MAAMC,OAAK,OAAO,MAAM,SAAS,CAAC;AACtD,QAAI,CAAC,IAAK;AACV,UAAM,UAAU,OAAO;AACvB,UAAM,UAAU,YAAY,WAAc,aAAa,IAAI,OAAO,KAAK,KAAK;AAC5E,UAAM,MAAM,UAAU,WAAW,OAAO,KAAK,UAAU,OAAO,IAAI;AAClE,UAAM,QAAQ,OAAO,IAAI,GAAG,KAAK;AAAA,MAC/B,KAAK,UAAU,UAAU,OAAO;AAAA,MAChC,eAAe,UAAUA,OAAK,SAAS,SAAS,IAAI;AAAA,MACpD,SAAS,CAAC;AAAA,IACZ;AACA,UAAM,QAAQ,KAAK,EAAE,QAAQ,IAAI,CAAC;AAClC,WAAO,IAAI,KAAK,KAAK;AAAA,EACvB;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;AAGA,SAAS,WACP,SACA,KACA,QACA,WACA,SACY;AACZ,QAAM,EAAE,MAAM,OAAO,eAAe,IAAI,QAAQ,QAAQ,GAAG;AAC3D,QAAM,UAAU,QAAQ;AACxB,QAAM,WAAW,oBAAI,IAAqB;AAE1C,aAAW,OAAO,UAAU,cAAc;AACxC,UAAM,MAAM,GAAG,IAAI,OAAO,IAAI,IAAI,UAAU;AAC5C,QAAI,SAAS,IAAI,GAAG,EAAG;AACvB,UAAM,SAAS,EAAE,SAAS,IAAI,SAAS,YAAY,IAAI,WAAW;AAClE,aAAS,IAAI,KAAK;AAAA,MAChB,GAAG;AAAA,MACH,OAAO,IAAI,UAAU,SAAS,SAAS;AAAA,MACvC,QAAQ,CAAC,qBAAqB,wBAAwB,OAAO,EAAE,GAAG,QAAQ,iBAAiB,GAAG,OAAO;AAAA,IACvG,CAAC;AAAA,EACH;AAGA,aAAW,WAAW,IAAI,qBAAqB;AAC7C,UAAM,UAAU,YAAY,QAAQ,SAAS,KAAK;AAClD,UAAM,aAAa,YAAY,QAAQ,YAAY,KAAK;AACxD,UAAM,MAAM,GAAG,OAAO,IAAI,UAAU;AACpC,QAAI,SAAS,IAAI,GAAG,KAAK,CAAC,QAAQ,QAAS;AAE3C,UAAM,WAAW,QAAQ,UAAU;AACnC,UAAM,UAAU,WACZ,YAAY,QAAQ,SAAS,KAAK,IAClC,UAAU,oBAAoB,KAAK,CAAC,MAAM,EAAE,YAAY,WAAW,EAAE,eAAe,UAAU,GAAG;AACrG,QAAI,CAAC,WAAW,QAAQ,SAAS,IAAI,EAAG;AAExC,UAAM,SAAS,EAAE,SAAS,WAAW;AACrC,aAAS,IAAI,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,WAAW,QAAQ,QAAQ;AAAA,MACjC,YAAY,QAAQ;AAAA,MACpB,OAAO;AAAA,MACP,QAAQ,CAAC,qBAAqB,qBAAqB,OAAO,EAAE,GAAG,QAAQ,iBAAiB,GAAG,OAAO;AAAA,IACpG,CAAC;AAAA,EACH;AAGA,MAAI,IAAI,UAAU,mBAAmB,IAAI,QAAQ;AAC/C,UAAM,EAAE,SAAS,WAAW,IAAI,IAAI;AACpC,UAAM,UAAU,YAAY,IAAI,OAAO,SAAS,KAAK;AACrD,aAAS,IAAI,GAAG,OAAO,IAAI,UAAU,IAAI;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ,CAAC,qBAAqB,oBAAoB,KAAK,EAAE,SAAS,YAAY,iBAAiB,GAAG,OAAO;AAAA,IAC3G,CAAC;AAAA,EACH;AAEA,QAAM,OAAmB,EAAE,QAAQ,WAAW,YAAY,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE;AACvF,aAAW,CAAC,KAAK,OAAO,KAAK,UAAU;AACrC,UAAM,SAAS,eAAe,KAAK,SAAS,OAAO;AACnD,QAAI,OAAO,SAAS,aAAa;AAC/B,WAAK,QAAQ,KAAK,EAAE,SAAS,OAAO,CAAC;AACrC;AAAA,IACF;AAEA,UAAM,SAAS,QAAQ,UAAU,IAAI,GAAG;AACxC,QAAI,UAAU,cAAc,QAAQ,MAAM,GAAG;AAC3C,UAAI,OAAO,WAAW,OAAO,YAAY,QAAQ,SAAS;AACxD,QAAAC,SAAQC,oBAAmB,SAAS,OAAO,SAAS,MAAM,GAAG,KAAK,YAAY,KAAK,OAAO;AAAA,MAC5F;AAAA,IACF,OAAO;AAIL,WAAK,QAAQ,KAAK,EAAE,SAAS,QAAQ,eAAe,KAAK,SAAS,EAAE,GAAG,SAAS,WAAW,oBAAI,IAAI,EAAE,CAAC,EAAE,CAAC;AAAA,IAC3G;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,cAAc,GAAkB,GAA2B;AAClE,SAAO,EAAE,kBAAkB,UAAa,EAAE,kBAAkB,EAAE;AAChE;AAGA,SAAS,aAAa,MAAkB,QAAuB,SAAqC;AAClG,QAAM,EAAE,YAAY,QAAQ,IAAI;AAChC,aAAW,EAAE,SAAS,OAAO,KAAK,KAAK,SAAS;AAC9C,UAAM,MAAM,GAAG,QAAQ,OAAO,IAAI,QAAQ,UAAU;AACpD,UAAM,QAAQ,UAAU,QAAQ,SAAS,OAAO,cAAc,IAAI,GAAG,KAAK,CAAC,CAAC;AAC5E,UAAM,SAAS,WAAW,QAAQ,SAAS,OAAO,OAAO;AACzD,QAAI,CAAC,QAAQ;AACX,UAAI,OAAO,cAAc,IAAI,GAAG,GAAG;AACjC,gBAAQ,KAAK,EAAE,YAAY,KAAK,QAAQ,OAAO,MAAM,QAAQ,iBAAiB,QAAQ,mBAAmB,CAAC;AAAA,MAC5G;AACA;AAAA,IACF;AACA,IAAAD,SAAQ,gBAAgB,SAAS,QAAQ,OAAO,MAAM,GAAG,YAAY,OAAO;AAAA,EAC9E;AAEA,yBAAuB,UAAU;AACjC,aAAW,KAAK,CAAC,GAAG,OAAOF,YAAW,EAAE,IAAI,KAAK,MAAMA,YAAW,EAAE,IAAI,KAAK,EAAE;AAC/E,SAAO,EAAE,YAAY,QAAQ;AAC/B;AAOO,SAAS,UAAU,SAAiB,WAAwC;AACjF,QAAM,QAAQ,UAAU,QAAQ,OAAO;AACvC,SAAO,SAAS,IAAI,UAAU,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS;AAChE;AAIA,SAASE,SAAQ,OAAc,YAA+B,SAAoC;AAChG,MAAI,eAAe,MAAO,YAAW,KAAK,MAAM,SAAS;AAAA,MACpD,SAAQ,KAAK,MAAM,OAAO;AACjC;AAEA,SAAS,gBAAgB,SAAkB,QAAgB,OAAiB,QAAiC;AAC3G,QAAM,OAAO,eAAe,SAAS,QAAQ,QAAQ,QAAQ;AAC7D,MAAI,eAAe,MAAM;AACvB,SAAK,UAAU,oBAAoB,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,OAAO,QAAQ,OAAO;AAAA,EAChF;AACA,SAAO;AACT;AAEA,SAASC,oBAAmB,SAAkB,cAAsB,QAAiC;AACnG,QAAM,QAAQ,eAAe,SAAS,cAAc,QAAQ,OAAO;AACnE,MAAI,eAAe,MAAO,OAAM,UAAU,oBAAoB,CAAC,YAAY;AAC3E,SAAO;AACT;AAEA,SAAS,eACP,SACA,QACA,QACA,QACO;AACP,QAAM,aAAa,GAAG,QAAQ,OAAO,IAAI,QAAQ,UAAU;AAC3D,QAAM,WAAW,QAAQ,OAAO,QAAQ,OAAO;AAC/C,MAAI,CAAC,SAAS,OAAO;AACnB,WAAO,EAAE,SAAS,EAAE,YAAY,QAAQ,OAAO,MAAM,QAAQ,SAAS,QAAQ,QAAQ,SAAS,OAAO,EAAE;AAAA,EAC1G;AAEA,QAAM,eAAe,iBAAiB,QAAQ,OAAO,KAAK;AAC1D,QAAM,cAAc,iBAAiB,MAAM,KAAK;AAChD,QAAM,OAAOC,SAAO,GAAG,cAAc,WAAW,IAAI,UAAU,aAAa,cAAc,WAAW;AACpG,QAAM,eAAe,oBAAoB,MAAM;AAE/C,SAAO;AAAA,IACL,WAAW;AAAA,MACT,YAAY,EAAE,YAAY,OAAO,QAAQ,SAAS,UAAU,QAAQ,YAAY,WAAW,QAAQ;AAAA,MACnG,cAAc,QAAQ;AAAA,MACtB;AAAA,MACA,QAAQ;AAAA,MACR,UAAU;AAAA,MACV;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,UAAU,SAAS;AAAA,MACnB;AAAA,MACA;AAAA,MACA,aAAa,SAAS;AAAA,MACtB;AAAA,MACA,eAAe,eAAe,qBAAqB,MAAM,IAAI;AAAA,IAC/D;AAAA,EACF;AACF;AAQO,SAAS,WAAW,SAAiB,OAA0B,SAA6C;AACjH,QAAM,UAAU,MAAM,OAAO,CAAC,MAAM,YAAY,SAAS,CAAC,oBAAoB,CAAC,CAAC;AAChF,QAAM,UAAU,UAAU,OAAO;AACjC,QAAM,cAAc,UAAU,QAAQ,OAAO,CAAC,MAAM,UAAU,CAAC,MAAM,OAAO,IAAI,CAAC;AACjF,QAAM,OAAO,YAAY,SAAS,IAAI,cAAc;AACpD,SAAO,KAAK,KAAK,SAAS,CAAC;AAC7B;AAEA,SAAS,UAAU,SAAqC;AACtD,QAAM,SAAS,QAAQ,MAAM,eAAe,IAAI,CAAC;AACjD,SAAO,UAAU,CAAC,oBAAoB,OAAO,IAAI,OAAO,YAAY,IAAI;AAC1E;AAMA,SAAS,uBAAuB,YAAqC;AACnE,QAAM,SAAS,oBAAI,IAA+B;AAClD,aAAW,aAAa,YAAY;AAClC,UAAM,cAAc,UAAU;AAC9B,QAAI,aAAa,SAAS,WAAY;AACtC,UAAM,MAAM,GAAG,YAAY,IAAI,IAAI,YAAY,YAAY;AAC3D,WAAO,IAAI,KAAK,CAAC,GAAI,OAAO,IAAI,GAAG,KAAK,CAAC,GAAI,SAAS,CAAC;AAAA,EACzD;AACA,aAAW,SAAS,OAAO,OAAO,GAAG;AACnC,QAAI,MAAM,SAAS,EAAG;AACtB,eAAW,aAAa,OAAO;AAC7B,gBAAU,aAAa,MACpB,OAAO,CAAC,UAAU,UAAU,SAAS,EACrC,IAAI,CAAC,UAAU,MAAM,WAAW,UAAU;AAAA,IAC/C;AAAA,EACF;AACF;;;AEnXA,SAAS,gBAAAC,gBAAc,iBAAAC,sBAAqB;AAC5C,SAAS,QAAAC,QAAM,WAAAC,iBAAe;AAUvB,IAAM,sBAAN,MAA2D;AAAA,EAChE,cAAc,QAAuB,UAAkB,SAAsC;AAC3F,UAAM,QAAQ,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAMC,UAAQ,EAAE,aAAa,QAAQC,OAAK,OAAO,MAAM,SAAS,CAAC,CAAC,CAAC;AACtG,WAAO,CAAC,GAAG,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,aACJ,QACA,SACA,SACA,YACuB;AACvB,UAAM,UAAU,aAAa,KAAK,OAAO;AACzC,UAAM,SAAS,oBAAI,IAA+B;AAClD,eAAW,UAAU,SAAS;AAC5B,UAAI,CAAC,OAAO,aAAa;AACvB,cAAM,IAAI,aAAa,oCAAoC,OAAO,WAAW,UAAU,sBAAsB;AAAA,MAC/G;AACA,YAAM,OAAOD,UAAQ,OAAO,YAAY,IAAI;AAC5C,aAAO,IAAI,MAAM,CAAC,GAAI,OAAO,IAAI,IAAI,KAAK,CAAC,GAAI,MAAM,CAAC;AAAA,IACxD;AAIA,UAAM,SAA8C,CAAC;AACrD,eAAW,CAAC,MAAM,WAAW,KAAK,QAAQ;AACxC,iBAAW,aAAa,YAAY,MAAM,iBAAiB,YAAY,CAAC,EAAG,YAAa,WAAW,QAAG;AACtG,YAAM,SAASE,eAAa,MAAM,MAAM;AACxC,YAAM,MAAM,SAAS,QAAQ,IAAI;AACjC,YAAM,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,QAAQ,QAAQ,MAAM,IAAI,CAAE,EAAE,OAAO,CAAC,GAAG;AACrF,YAAM,QAAQ,aAAa,KAAK,CAAC,KAAK,GAAG,MAAM,MAAM,CAAC,CAAC,GAAG,WAAW;AACrE,UAAI;AACF,eAAO,KAAK,EAAE,MAAM,SAAS,eAAe,QAAQ,KAAK,EAAE,CAAC;AAAA,MAC9D,SAAS,KAAK;AACZ,YAAI,eAAe,eAAgB,OAAM,IAAI,aAAa,GAAG,IAAI,KAAK,IAAI,OAAO,EAAE;AACnF,cAAM;AAAA,MACR;AAAA,IACF;AAEA,eAAW,yBAAoB;AAC/B,eAAW,SAAS,OAAQ,CAAAC,eAAc,MAAM,MAAM,MAAM,SAAS,MAAM;AAE3E,WAAO;AAAA,MACL,cAAc,QAAQ;AAAA,MACtB,cAAc,WAAW,QAAQ,MAAM,8BAA8B,OAAO,MAAM;AAAA,MAClF,eAAe;AAAA,MACf,qBAAqB,CAAC;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAM,SAAwB;AAAA,EAE9B;AACF;AAGA,SAAS,aAAa,KAAe,OAA4B,SAAwC;AACvG,QAAM,QAAQ,oBAAI,IAAmD;AAErE,aAAW,UAAU,SAAS;AAC5B,UAAM,UAAU,uBAAuB,KAAK,OAAO,MAAM;AACzD,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR,GAAG,OAAO,YAAa,WAAW,gCAAgC,OAAO,WAAW,UAAU;AAAA,MAChG;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,IAAI,OAAO;AAClC,QAAI,UAAU;AACZ,UAAI,SAAS,gBAAgB,OAAO,UAAU;AAC5C,cAAM,IAAI;AAAA,UACR,GAAG,OAAO,WAAW,UAAU,QAAQ,SAAS,UAAU,UAAU,SAAS,OAAO,WAAY,CAAC,mCAC7D,OAAO,QAAQ,OAAO,SAAS,WAAW;AAAA,QAChF;AAAA,MACF;AACA;AAAA,IACF;AACA,UAAM,IAAI,SAAS;AAAA,MACjB;AAAA,MACA,UAAU,OAAO;AAAA,MACjB,aAAa,OAAO;AAAA,MACpB,YAAY,OAAO,WAAW;AAAA,IAChC,CAAC;AAAA,EACH;AACA,SAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAC3B;AAEA,SAAS,uBACP,KACA,OACA,QACwB;AACxB,QAAM,cAAc,OAAO;AAC3B,QAAM,EAAE,OAAO,SAAS,IAAI,OAAO;AAEnC,QAAM,UAAU,CAAC,QACf,YAAY,IAAI,SAAS,KAAK,MAAM,SAAS,YAAY,IAAI,YAAY,KAAK,MAAM;AAEtF,UAAQ,YAAY,MAAM;AAAA,IACxB,KAAK;AACH,aAAO,YAAY,eAAe,IAAI,WAAW,IAAI,YAAY,YAAY,GAAG,UAAU;AAAA,IAC5F,KAAK;AACH,aAAO,IAAI,QAAQ;AAAA,IACrB,KAAK;AACH,aAAO,IAAI,aAAa,KAAK,OAAO,GAAG;AAAA,IACzC,KAAK;AACH,aAAO,IAAI,oBAAoB,KAAK,OAAO,GAAG;AAAA,EAClD;AACF;AAEA,SAAS,SAAS,aAAyC;AACzD,SAAO,YAAY,SAAS,aACxB,mBAAmB,YAAY,YAAY,QAAQ,YAAY,WAAW,KAC1E,gBAAgB,YAAY,WAAW;AAC7C;;;AC/HA,SAAS,WAAAC,UAAS,QAAAC,QAAM,YAAAC,YAAU,WAAAC,iBAAe;AAQjD,IAAMC,qBAAoB,KAAK;AAExB,IAAM,2BAAN,MAA2D;AAAA,EAChE,MAAM,OAAO,QAAuB,SAAiB,UAA+B,CAAC,GAAgC;AACnH,QAAI,QAAQ,cAAc;AACxB,YAAMC,SAAQ,QAAQ,eAAe,QAAQ;AAC7C,YAAM,SAAS,MAAM,eAAe,QAAQ,cAAc,EAAE,KAAK,OAAO,MAAM,WAAWD,mBAAkB,CAAC;AAC5G,aAAO,OAAO,aAAa,IACvB,EAAE,QAAQ,SAAS,SAAS,kCAAkC,OAAAC,OAAM,IACpE,EAAE,QAAQ,QAAQ,SAASC,gBAAe,MAAM,GAAG,OAAAD,OAAM;AAAA,IAC/D;AAEA,UAAM,OAAO,UAAU,QAAQ,SAAS,QAAQ,gBAAgB,CAAC,CAAC;AAClE,UAAM,QAAQ,gBAAgB,CAAC,gBAAgB,GAAG,KAAK,IAAI,EAAE,KAAK,GAAG,CAAC;AAEtE,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAAI,GAAG;AAAA,QAClE,KAAK,KAAK;AAAA,QACV;AAAA,QACA,WAAWD;AAAA,MACb,CAAC;AACD,UAAI,OAAO,aAAa,GAAG;AACzB,eAAO,EAAE,QAAQ,SAAS,SAAS,kDAAkD,MAAM;AAAA,MAC7F;AACA,YAAM,UAAU,OAAO,WAAW,2BAA2BE,gBAAe,MAAM;AAClF,aAAO,EAAE,QAAQ,QAAQ,SAAS,MAAM;AAAA,IAC1C,SAAS,KAAK;AACZ,UAAI,eAAe,sBAAuB,QAAO,EAAE,QAAQ,QAAQ,SAAS,IAAI,SAAS,MAAM;AAC/F,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAGA,SAASA,gBAAe,QAA2B;AACjD,QAAM,SAAS,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM,GAAG,KAAK;AACzD,SAAO,SAAS,YAAY,MAAM,IAAI,oBAAoB,OAAO,QAAQ;AAC3E;AAQO,SAAS,UAAU,QAAuB,SAAiB,cAA4C;AAC5G,QAAM,gBAAgB,OAAO;AAC7B,MAAI,CAAC,cAAe,QAAO,EAAE,KAAK,OAAO,MAAM,MAAM,CAAC,EAAE;AAExD,QAAM,UAAU,aAAa,KAAK,OAAO;AACzC,QAAM,QAAQ,aAAa,SAAS,IAAI,eAAe,CAACC,OAAK,OAAO,MAAM,SAAS,CAAC;AACpF,QAAM,WAAW,oBAAI,IAAY;AAEjC,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,QAAQ,MAAM,IAAI;AAC9B,UAAM,MAAMC,UAAQC,SAAQ,IAAI,CAAC;AAEjC,QAAI,CAAC,OAAO,QAAQ,gBAAgB,GAAG,MAAM,iBAAiB,QAAQD,UAAQ,aAAa,GAAG;AAC5F,aAAO,EAAE,KAAK,eAAe,MAAM,CAAC,EAAE;AAAA,IACxC;AACA,aAAS,IAAIE,WAAS,eAAe,GAAG,EAAE,QAAQ,OAAO,GAAG,CAAC;AAAA,EAC/D;AAEA,SAAO,EAAE,KAAK,eAAe,MAAM,CAAC,OAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,GAAG,GAAG,MAAM,EAAE;AAC9E;;;ACpEO,IAAM,yBAAN,MAA0D;AAAA,EACtD,YAAuB;AAAA,EACvB,cAAc;AAAA,EACd,OAAO;AAAA,EACP,eAAe;AAAA,EACf,aAAa;AAAA,EAEb,YAAY,IAAI,4BAA4B;AAAA,EAC5C;AAAA,EACA;AAAA,EACA,UAAU,IAAI,oBAAoB;AAAA,EAClC,WAAW,IAAI,yBAAyB;AAAA;AAAA,EAGjD,YAAY,UAA+B,uBAAuB;AAChE,SAAK,WAAW,IAAI,qBAAqB,OAAO;AAChD,SAAK,SAAS,IAAI,uBAAuB,OAAO;AAAA,EAClD;AAAA,EAEA,aACE,QACA,IACW;AACX,WAAO;AAAA,MACL,KAAK,aAAa,OAAO,KAAK;AAAA,MAC9B,MAAM,gBAAgB,OAAO,SAAS;AAAA,MACtC,KAAK,aAAa,OAAO,QAAQ;AAAA,IACnC;AAAA,EACF;AACF;;;ACnCA,SAAS,cAAAC,cAAY,gBAAAC,gBAAc,eAAAC,cAAa,oBAAoB;AACpE,SAAS,UAAU,WAAAC,WAAS,QAAAC,QAAM,YAAAC,YAAU,WAAAC,iBAAe;;;ACA3D,SAAS,mBAAmB;AAC5B,SAAS,cAAAC,cAAY,aAAAC,YAAW,gBAAAC,gBAAc,eAAAC,cAAa,UAAAC,SAAQ,WAAW,iBAAAC,sBAAqB;AACnG,SAAS,QAAAC,cAAY;;;ACDrB,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,WAAAC,WAAS,cAAAC,aAAY,QAAAC,QAAM,YAAAC,YAAU,WAAAC,WAAS,OAAAC,YAAW;AAIlE,IAAM,gBACJ;AAGK,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,YAAY,UAAkB,eAAe;AAC3C,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,SAA0B,QAAgB;AACpD,UAAM,OAAO;AADuB;AAEpC,SAAK,OAAO;AAAA,EACd;AAAA,EAHsC;AAIxC;AAGO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAMC,cAAa,QAAQ,aAAa;AACxC,IAAMC,WAAUD,cAAa,gBAAgB;AAE7C,IAAI;AAWG,SAAS,kBAAkB,SAAiB,SAAqC;AACtF,MAAI,MAAME,UAAQ,OAAO;AACzB,QAAM,OAAOA,UAAQ,OAAO;AAC5B,aAAS;AACP,UAAM,YAAYC,OAAK,KAAKC,QAAO;AACnC,QAAIC,aAAW,SAAS,EAAG,QAAO;AAClC,QAAI,QAAQ,QAAQC,WAAS,MAAM,GAAG,EAAE,WAAW,IAAI,EAAG,QAAO;AACjE,UAAM,SAASC,UAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;AAWA,SAAS,gBAAgB,MAAsB;AAC7C,SAAO,KACJ,MAAM,OAAO,EACb,OAAO,CAAC,SAAS,CAAC,KAAK,WAAW,YAAY,CAAC,EAC/C,KAAK,IAAI;AACd;AAEA,eAAe,kBAAkB,KAA4B;AAC3D,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAW,UAAU,CAAC,WAAW,GAAG,EAAE,KAAK,WAAW,IAAO,CAAC;AAAA,EAC/E,QAAQ;AACN,UAAM,IAAI,uBAAuB;AAAA,EACnC;AACA,MAAI,OAAO,UAAU;AACnB,UAAM,IAAI,uBAAuB,0DAA0D;AAAA,EAC7F;AACA,MAAI,OAAO,aAAa,OAAQ,OAAO,aAAa,KAAK,CAAC,OAAO,OAAO,KAAK,KAAK,CAAC,OAAO,OAAO,KAAK,GAAI;AACxG,UAAM,IAAI,uBAAuB;AAAA,EACnC;AACA,MAAI,OAAO,aAAa,GAAG;AACzB,UAAM,SAAS,gBAAgB,OAAO,UAAU,OAAO,MAAM,EAC1D,MAAM,OAAO,EACb,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC;AAC7B,UAAM,IAAI,uBAAuB,gCAAgC,UAAU,0BAA0B,EAAE;AAAA,EACzG;AACF;AAGA,eAAsB,UAAU,MAAgB,SAA+C;AAC7F,QAAM,UAAU,kBAAkB,QAAQ,KAAK,QAAQ,OAAO;AAC9D,QAAM,MAAM,EAAE,KAAK,QAAQ,KAAK,WAAW,QAAQ,UAAU;AAE7D,MAAI,SAAS;AAGX,UAAM,kBAAkB,cAAc,QAAQ,KAAK,OAAO;AAC1D,UAAM,OACJC,YAAW,eAAe,KAAK,gBAAgB,SAASC,IAAG,IAAI,kBAAkB,IAAIA,IAAG,GAAG,eAAe;AAE5G,WAAOC,cAAa,WAAW,MAAM,MAAM,GAAG,IAAI,WAAW,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG,GAAG;AAAA,EACzF;AAEA,mBAAiB,kBAAkB,QAAQ,GAAG;AAC9C,MAAI;AACF,UAAM;AAAA,EACR,SAAS,OAAO;AAEd,mBAAe;AACf,UAAM;AAAA,EACR;AACA,SAAO,WAAW,UAAU,MAAM,GAAG;AACvC;AAOO,SAAS,aAAa,QAAsD;AACjF,MAAI,OAAO,gBAAgB,OAAO,MAAM;AACxC,MAAI,CAAC,KAAK,KAAK,EAAG,QAAO,gBAAgB,OAAO,MAAM;AACtD,QAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,QAAM,QAAQ,MAAM,UAAU,CAAC,SAAS,KAAK,WAAW,QAAQ,CAAC;AACjE,QAAM,QAAQ,SAAS,IAAI,MAAM,MAAM,GAAG,KAAK,IAAI,OAAO,MAAM,GAAG;AACnE,SAAO,KAAK,KAAK,IAAI,EAAE,KAAK;AAC9B;AAMO,SAAS,uBACd,QACA,SACoB;AACpB,QAAM,OAAO,OAAO;AACpB,MAAI,CAAC,yBAAyB,KAAK,IAAI,EAAG,QAAO;AACjD,QAAM,YAAY,mCAAmC,KAAK,IAAI,IAAI,CAAC,GAAG,KAAK;AAC3E,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,UAAU,kBAAkB,QAAQ,KAAK,QAAQ,OAAO;AAC9D,QAAM,iBAAiBP,OAAKI,UAAQ,WAAWJ,OAAK,QAAQ,KAAKC,QAAO,CAAC,GAAG,UAAU,WAAW,2BAA2B;AAC5H,MAAI,MAAM;AACV,MAAI;AACF,UAAM,OAAOO,eAAa,gBAAgB,MAAM,EAC7C,MAAM,OAAO,EACb,KAAK,CAAC,MAAM,EAAE,WAAW,kBAAkB,CAAC;AAC/C,QAAI,KAAM,OAAM,KAAK,MAAM,mBAAmB,MAAM,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAAA,EAClF,QAAQ;AAAA,EAER;AACA,SACE,qDAAqD,GAAG,KAAK,SAAS;AAG1E;AASO,SAAS,cACd,QACA,SACA,MACA,SACA,SACoB;AACpB,QAAM,SAAS,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM,GAAG,KAAK;AACzD,MAAI,OAAO,UAAU;AACnB,WAAO,IAAI,mBAAmB,0BAA0B,OAAO,kBAAkB,IAAI,KAAK,MAAM;AAAA,EAClG;AACA,QAAM,WAAW,uBAAuB,QAAQ,OAAO;AACvD,MAAI,SAAU,QAAO,IAAI,mBAAmB,UAAU,MAAM;AAC5D,SAAO,IAAI,mBAAmB,GAAG,OAAO;AAAA,EAAM,aAAa,MAAM,CAAC,IAAI,MAAM;AAC9E;;;ACrLO,IAAM,oBAA4B,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["existsSync","readFileSync","dirname","join","resolve","semver","semver","existsSync","dirname","join","resolve","resolve","child","resolve","dirname","existsSync","join","readFileSync","dirname","join","relative","resolve","readFileSync","join","readFileSync","resolve","join","dirname","relative","semver","semver","readFileSync","join","semver","readFileSync","join","semver","readFileSync","join","relative","existsSync","readFileSync","join","existsSync","readFileSync","join","parse","join","readFileSync","audit","relative","semver","existsSync","readFileSync","dirname","join","relative","resolve","resolve","entries","join","readFileSync","dirname","existsSync","relative","existsSync","readFileSync","dirname","isAbsolute","join","resolve","semver","semver","semver","semver","readFileSync","join","relative","semver","parseTOML","SECTIONS","existsSync","readFileSync","getStaticTOMLValue","parseTOML","CONCURRENCY","DIFF_ORDER","join","semver","readFileSync","relative","existsSync","readFileSync","writeFileSync","join","resolve","semver","resolve","join","readFileSync","writeFileSync","existsSync","semver","existsSync","join","relative","resolve","VERIFY_TIMEOUT_MS","relative","resolve","join","existsSync","label","result","semver","existsSync","dirname","join","relative","resolve","existsSync","readdirSync","statSync","join","resolve","existsSync","readFileSync","dirname","join","resolve","readFileSync","dirname","resolve","existsSync","join","resolve","join","existsSync","entries","readdirSync","statSync","resolve","existsSync","join","relative","dirname","existsSync","join","existsSync","dirname","isAbsolute","join","relative","resolve","IS_WINDOWS","resolve","join","existsSync","relative","dirname","isAbsolute","existsSync","readFileSync","readdirSync","writeFileSync","join","join","existsSync","readdirSync","readFileSync","merge","entries","join","writeFileSync","existsSync","readFileSync","join","existsSync","join","semver","relative","relative","DIFF_ORDER","join","collect","alignmentCandidate","semver","readFileSync","writeFileSync","join","resolve","resolve","join","readFileSync","writeFileSync","dirname","join","relative","resolve","VERIFY_TIMEOUT_MS","label","failureDetails","join","resolve","dirname","relative","existsSync","readFileSync","readdirSync","dirname","join","relative","resolve","existsSync","mkdirSync","readFileSync","readdirSync","rmSync","writeFileSync","join","existsSync","readFileSync","dirname","isAbsolute","join","relative","resolve","sep","IS_WINDOWS","WRAPPER","resolve","join","WRAPPER","existsSync","relative","dirname","isAbsolute","sep","IS_WINDOWS","readFileSync","join","existsSync","mkdirSync","writeFileSync","rmSync","readdirSync","readFileSync","MAX_DEPTH","existsSync","join","readdirSync","resolve","readFileSync","ancestorsWithin","dirname","relative","resolve","PUBLIC_HOSTS","resolve","loadConfig","existsSync","readFileSync","realpathSync","relative","resolve","semver","join","relative","parse","parse","entries","resolve","require","relative","SETTINGS_FILES","join","entry","DIFF_ORDER","planModule","finishModule","existsSync","readFileSync","canonical","realpathSync","resolve","isOutside","relative","entries","located","origin","buildCandidate","same","pickLatest","markSharedDeclarations","semver","flavourOf","readFileSync","writeFileSync","relative","resolve","existsSync","readdirSync","join","resolve","SKIPPED_DIRECTORIES","entries","readdirSync","join","resolve","existsSync","display","relative","resolve","displayPath","readFileSync","writeFileSync","resolve","sep","failureDetails","resolve","sep","affected","resolve","existsSync","join","dirname","loadConfig","readFileSync"]}
|