deadwood-scan 0.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../../core/src/index.ts","../../core/src/errors.ts","../../core/src/graph/parser.ts","../../core/src/graph/moduleGraph.ts","../../core/src/graph/resolver.ts","../../core/src/util/paths.ts","../../core/src/workspace/workspaces.ts","../../core/src/workspace/entrypoints.ts","../../core/src/manifest/fileRefs.ts","../../core/src/manifest/crontab.ts","../../core/src/manifest/githubActions.ts","../../core/src/manifest/k8s.ts","../../core/src/manifest/configRefs.ts","../../core/src/model/signals.ts","../../core/src/model/finding.ts","../../core/src/util/hash.ts","../../core/src/detectors/types.ts","../../core/src/detectors/unreachableFiles.ts","../../core/src/detectors/unusedExports.ts","../../core/src/detectors/unusedDeps.ts","../../core/src/detectors/routes/express.ts","../../core/src/detectors/routes/nest.ts","../../core/src/detectors/routes/next.ts","../../core/src/evidence/dynamicImports.ts","../../core/src/evidence/types.ts","../../core/src/evidence/stringDispatch.ts","../../core/src/evidence/packageScripts.ts","../../core/src/evidence/jobRegistration.ts","../../core/src/evidence/comments.ts","../../core/src/evidence/manifestReference.ts","../../core/src/scoring/score.ts","../src/failOn.ts","../src/reporters/json.ts","../src/reporters/md.ts","../src/reporters/pretty.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * deadwood CLI — thin shell over @deadwood/core. Parses args, runs scan(),\n * renders a report, sets the exit code. Analysis logic belongs in core.\n *\n * Exit codes (CI contract): 0 clean, 1 --fail-on gate tripped, 2 scan error.\n */\nimport { createRequire } from 'node:module';\nimport process from 'node:process';\nimport { Command, Option } from 'commander';\nimport ora from 'ora';\nimport pc from 'picocolors';\nimport {\n scan,\n ScanError,\n type ConfidenceLevel,\n type Finding,\n type FindingCategory,\n type ScanResult,\n} from '@deadwood/core';\nimport { parseFailOn, evaluateFailOn } from './failOn.js';\nimport { renderJson } from './reporters/json.js';\nimport { renderMd } from './reporters/md.js';\nimport { renderPretty } from './reporters/pretty.js';\n\nconst pkg = createRequire(import.meta.url)('../package.json') as { version: string };\n\nconst CATEGORIES: FindingCategory[] = [\n 'dead-route',\n 'unused-export',\n 'unused-dependency',\n 'unreachable-file',\n];\nconst LEVEL_RANK: Record<ConfidenceLevel, number> = { low: 0, medium: 1, high: 2 };\n\nconst program = new Command();\n\nprogram\n .name('deadwood')\n .description('Find dead code and prove it — scans a JS/TS repo and prints a shock report')\n .version(pkg.version)\n .argument('[path]', 'directory to scan', '.')\n .option('--json', 'machine-readable ScanResult on stdout')\n .option('--md', 'markdown report (PR comments / Slack)')\n .option('--fail-on <spec>', \"CI gate: 'high', 'medium', or 'high:5' (exit 1 when tripped)\")\n .option('--include <glob...>', 'extra include globs')\n .option('--exclude <glob...>', 'extra exclude globs')\n .addOption(new Option('--category <category...>', 'limit findings').choices(CATEGORIES))\n .option('--workspace <name...>', 'limit monorepo scan to these packages')\n .addOption(\n new Option('--framework <framework...>', 'force route framework detection').choices([\n 'express',\n 'fastify',\n 'nest',\n 'next',\n ]),\n )\n .option('--entry <file...>', 'extra entry points (false-positive escape hatch)')\n .addOption(\n new Option('--min-confidence <level>', 'hide findings below this level')\n .choices(['low', 'medium', 'high'])\n .default('low'),\n )\n .option('--no-color', 'disable colors')\n .action(async (path: string, opts: CliOptions) => {\n await run(path, opts);\n });\n\ninterface CliOptions {\n json?: boolean;\n md?: boolean;\n failOn?: string;\n include?: string[];\n exclude?: string[];\n category?: FindingCategory[];\n workspace?: string[];\n framework?: string[];\n entry?: string[];\n minConfidence: ConfidenceLevel;\n color: boolean;\n}\n\nasync function run(path: string, opts: CliOptions): Promise<void> {\n if (opts.json && opts.md) {\n process.stderr.write('error: --json and --md are mutually exclusive\\n');\n process.exitCode = 2;\n return;\n }\n // Validate the gate spec before doing any work.\n const failOnSpec = (() => {\n try {\n return opts.failOn ? parseFailOn(opts.failOn) : undefined;\n } catch (err) {\n process.stderr.write(`error: ${(err as Error).message}\\n`);\n process.exitCode = 2;\n return null;\n }\n })();\n if (failOnSpec === null) return;\n\n const machineOutput = Boolean(opts.json || opts.md);\n const spinner = ora({\n text: 'scanning…',\n stream: process.stderr,\n isEnabled: !machineOutput && process.stderr.isTTY === true,\n });\n\n try {\n spinner.start();\n const result = await scan({\n path,\n include: opts.include,\n exclude: opts.exclude,\n categories: opts.category,\n frameworks: opts.framework,\n entries: opts.entry,\n workspaces: opts.workspace,\n toolVersion: pkg.version,\n });\n spinner.stop();\n\n // The gate sees everything; display filters apply only to the report (G6).\n const gate = failOnSpec ? evaluateFailOn(result.findings, failOnSpec) : undefined;\n const displayed = filterForDisplay(result, opts.minConfidence);\n\n const useColor = opts.color && pc.isColorSupported && process.stdout.isTTY === true;\n const output = opts.json\n ? renderJson(displayed)\n : opts.md\n ? renderMd(displayed)\n : renderPretty(displayed, useColor);\n process.stdout.write(output);\n\n // Warnings already render inside pretty/md reports and the JSON payload;\n // surface them on stderr for --json so piped consumers still see them.\n if (opts.json) {\n for (const warning of result.warnings) process.stderr.write(`warning: ${warning}\\n`);\n }\n\n if (gate?.tripped) {\n process.stderr.write(\n `deadwood: --fail-on ${opts.failOn} tripped (${gate.count} finding${gate.count === 1 ? '' : 's'} at/above '${failOnSpec!.level}')\\n`,\n );\n process.exitCode = 1;\n }\n } catch (err) {\n spinner.stop();\n if (err instanceof ScanError) {\n process.stderr.write(`error (${err.code}): ${err.message}\\n`);\n } else {\n process.stderr.write(\n `error: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`,\n );\n }\n process.exitCode = 2;\n }\n}\n\nfunction filterForDisplay(result: ScanResult, minConfidence: ConfidenceLevel): ScanResult {\n if (minConfidence === 'low') return result;\n const min = LEVEL_RANK[minConfidence];\n const findings: Finding[] = result.findings.filter((f) => LEVEL_RANK[f.confidence.level] >= min);\n return { ...result, findings };\n}\n\nawait program.parseAsync(process.argv);\n","/**\n * @deadwood/core — public API.\n *\n * Pure library: no console, no network, no process.exit. The CLI and the\n * future SaaS worker both call scan() and consume the same ScanResult.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { glob } from 'tinyglobby';\nimport type { Finding, FindingCategory, ScanResult, ScanStats } from './model/finding.js';\nimport { ScanError } from './errors.js';\nimport { parseFile } from './graph/parser.js';\nimport { ModuleGraph } from './graph/moduleGraph.js';\nimport { Resolver, tryFile, type WorkspaceEntry } from './graph/resolver.js';\nimport { discoverWorkspaces, unitForFile, type ScanUnit } from './workspace/workspaces.js';\nimport { discoverEntryPoints, resolveEntryRef, type EntryPoint } from './workspace/entrypoints.js';\nimport type { ManifestCaller } from './manifest/types.js';\nimport { isCrontabFile, parseCrontab } from './manifest/crontab.js';\nimport { parseGithubWorkflow } from './manifest/githubActions.js';\nimport { parseK8sManifest } from './manifest/k8s.js';\nimport { parseDockerfile, parseServerless, parseWebpackConfig } from './manifest/configRefs.js';\nimport type { Detector, ScanContext, ResolvedScanOptions } from './detectors/types.js';\nimport { unreachableFiles } from './detectors/unreachableFiles.js';\nimport { unusedExports } from './detectors/unusedExports.js';\nimport { unusedDeps } from './detectors/unusedDeps.js';\nimport { expressRoutes } from './detectors/routes/express.js';\nimport { nestRoutes } from './detectors/routes/nest.js';\nimport { nextRoutes } from './detectors/routes/next.js';\nimport type { EvidenceProvider, ProviderContext } from './evidence/types.js';\nimport { dynamicImports } from './evidence/dynamicImports.js';\nimport { stringDispatch } from './evidence/stringDispatch.js';\nimport { packageScripts } from './evidence/packageScripts.js';\nimport { jobRegistration } from './evidence/jobRegistration.js';\nimport { comments } from './evidence/comments.js';\nimport { manifestReference } from './evidence/manifestReference.js';\nimport { scoreFinding } from './scoring/score.js';\nimport { absPosix, relPosix, toPosix } from './util/paths.js';\n\nexport * from './model/finding.js';\nexport { SIGNALS, STATIC_CAPS, STATIC_CAP_REASON, evidenceFor } from './model/signals.js';\nexport { ScanError, type ScanErrorCode } from './errors.js';\nexport { scoreFinding } from './scoring/score.js';\nexport type { EntryPoint } from './workspace/entrypoints.js';\nexport type { ManifestCaller } from './manifest/types.js';\n\nexport interface ScanOptions {\n /** Directory to scan. */\n path: string;\n /** Extra include globs (added to the default source-file set). */\n include?: string[];\n /** Extra exclude globs. */\n exclude?: string[];\n /** Restrict findings to these categories. */\n categories?: FindingCategory[];\n /** Force-enable route frameworks regardless of dependency detection. */\n frameworks?: string[];\n /** Extra entry files, relative to `path` — the false-positive escape hatch. */\n entries?: string[];\n /** Restrict analysis to these workspace package names. */\n workspaces?: string[];\n /** Reported in ScanResult.tool (the CLI injects its own version). */\n toolVersion?: string;\n}\n\nconst DEFAULT_INCLUDE = ['**/*.{js,jsx,ts,tsx,mjs,cjs,mts,cts}'];\nconst DEFAULT_EXCLUDE = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/out/**',\n '**/coverage/**',\n '**/.git/**',\n '**/.next/**',\n '**/vendor/**',\n '**/*.d.ts',\n '**/*.min.js',\n];\n\nconst ALL_CATEGORIES: FindingCategory[] = [\n 'dead-route',\n 'unused-export',\n 'unused-dependency',\n 'unreachable-file',\n];\n\nconst DETECTORS: Detector[] = [\n expressRoutes,\n nestRoutes,\n nextRoutes,\n unreachableFiles,\n unusedExports,\n unusedDeps,\n];\n\n/**\n * Maps a `--framework` value to the detector it force-enables (bypassing the\n * dependency-signature detect() gate). Lets users scan a repo that declares the\n * framework oddly or vendors it.\n */\nconst FRAMEWORK_DETECTORS: Record<string, Detector> = {\n express: expressRoutes,\n fastify: expressRoutes,\n nest: nestRoutes,\n next: nextRoutes,\n};\n\n// Order matters mildly: structural spares first, comments last so dedupe\n// favors the more specific evidence details.\nconst PROVIDERS: EvidenceProvider[] = [\n dynamicImports,\n stringDispatch,\n packageScripts,\n jobRegistration,\n manifestReference,\n comments,\n];\n\nexport async function scan(options: ScanOptions): Promise<ScanResult> {\n const startedAt = Date.now();\n const root = absPosix(options.path);\n if (!fs.existsSync(root) || !fs.statSync(root).isDirectory()) {\n throw new ScanError('INVALID_PATH', `Not a directory: ${options.path}`);\n }\n\n const warnings: string[] = [];\n const { units: allUnits, warnings: wsWarnings } = await discoverWorkspaces(root);\n warnings.push(...wsWarnings);\n\n const units =\n options.workspaces && options.workspaces.length > 0\n ? allUnits.filter((u, i) => i === 0 || options.workspaces!.includes(u.name))\n : allUnits;\n\n // --- 1. collect + parse source files (one pass per file) -------------------\n const files = await glob([...DEFAULT_INCLUDE, ...(options.include ?? [])], {\n cwd: root,\n ignore: [...DEFAULT_EXCLUDE, ...(options.exclude ?? [])],\n absolute: true,\n dot: true,\n });\n if (files.length === 0) {\n throw new ScanError('NO_SOURCE_FILES', `No JS/TS source files found under ${options.path}`);\n }\n\n const graph = new ModuleGraph();\n for (const file of files.map(toPosix).sort()) {\n try {\n graph.addFile(parseFile(file, fs.readFileSync(file, 'utf8')));\n } catch {\n warnings.push(`Could not parse ${relPosix(root, file)}; it is excluded from analysis.`);\n }\n }\n const scannedFiles = new Set(graph.files.keys());\n\n // --- 2. resolve imports (global graph — cross-workspace edges included) ----\n const wsEntries: WorkspaceEntry[] = units\n .filter((u) => u.name !== '.')\n .map((u) => ({ name: u.name, dir: u.dir, entryFile: guessUnitEntry(u, scannedFiles) }));\n graph.link(new Resolver(root, wsEntries, scannedFiles, warnings));\n\n // --- 3. caller manifests (cron / CI / k8s / docker / serverless / webpack) -\n const manifestCallers = await collectManifestCallers(root, scannedFiles, warnings);\n\n // --- 4. entry points --------------------------------------------------------\n const entriesByUnit = new Map<ScanUnit, EntryPoint[]>();\n for (const unit of units) {\n entriesByUnit.set(unit, discoverEntryPoints(unit, scannedFiles, warnings));\n }\n const rootUnit = units[0]!;\n for (const caller of manifestCallers) {\n pushEntry(entriesByUnit, unitForFile(units, caller.file), {\n file: caller.file,\n reason: 'manifest',\n detail: caller.detail,\n });\n }\n for (const ref of options.entries ?? []) {\n const resolved = resolveEntryRef(root, ref, scannedFiles) ?? tryFile(path.resolve(root, ref));\n if (resolved) {\n pushEntry(entriesByUnit, unitForFile(units, toPosix(resolved)), {\n file: toPosix(resolved),\n reason: 'cli-flag',\n detail: '--entry',\n });\n } else {\n warnings.push(`--entry '${ref}' does not match a scanned file.`);\n }\n }\n // Units with no production entries get a conventional-entry guess so their\n // subtrees don't all look unreachable.\n for (const unit of units) {\n const eps = entriesByUnit.get(unit)!;\n if (!eps.some((e) => e.tag !== 'test' && e.reason !== 'config')) {\n const guess = guessUnitEntry(unit, scannedFiles);\n if (guess)\n pushEntry(entriesByUnit, unit, { file: guess, reason: 'main', detail: 'convention' });\n }\n }\n\n const allEntryPoints = [...entriesByUnit.values()].flat();\n const reach = {\n all: graph.reachable(allEntryPoints.map((e) => e.file)),\n prod: graph.reachable(allEntryPoints.filter((e) => e.tag !== 'test').map((e) => e.file)),\n };\n\n // --- 5. detectors -----------------------------------------------------------\n const resolvedOptions: ResolvedScanOptions = {\n categories: new Set(options.categories?.length ? options.categories : ALL_CATEGORIES),\n frameworks: new Set(options.frameworks ?? []),\n };\n\n const fileOwner = new Map<string, ScanUnit>();\n for (const file of scannedFiles) fileOwner.set(file, unitForFile(units, file));\n\n let findings: Finding[] = [];\n let routesTotal = 0;\n for (const unit of units) {\n const ctx: ScanContext = {\n root,\n units,\n unit,\n graph,\n entryPoints: allEntryPoints,\n unitEntryPoints: entriesByUnit.get(unit) ?? [],\n manifestCallers,\n reach,\n options: resolvedOptions,\n warnings,\n rel: (file) => relPosix(root, file),\n unitFiles: () => [...scannedFiles].filter((f) => fileOwner.get(f) === unit),\n };\n const forcedDetectors = new Set(\n [...resolvedOptions.frameworks].map((f) => FRAMEWORK_DETECTORS[f]).filter(Boolean),\n );\n for (const detector of DETECTORS) {\n if (!forcedDetectors.has(detector) && !detector.detect(unit)) continue;\n const result = detector.extract(ctx);\n findings.push(...result.findings);\n routesTotal += result.counted?.routes ?? 0;\n }\n }\n\n // --- 6. evidence providers --------------------------------------------------\n const providerCtx: ProviderContext = {\n root,\n units,\n graph,\n manifestCallers,\n entryPoints: allEntryPoints,\n warnings,\n rel: (file) => relPosix(root, file),\n abs: (relPath) => `${root}/${relPath}`,\n };\n for (const provider of PROVIDERS) {\n provider.provide(providerCtx, findings);\n }\n\n // --- 7. score, prune, sort ---------------------------------------------------\n for (const finding of findings) {\n finding.confidence = scoreFinding(finding.category, finding.evidence);\n }\n // Routes with nothing beyond base evidence are inventory, not findings —\n // reporting every route in the app as \"maybe dead\" would be noise.\n findings = findings.filter((f) => !(f.category === 'dead-route' && f.evidence.length === 1));\n findings = findings.filter((f) => resolvedOptions.categories.has(f.category));\n const categoryOrder = new Map(ALL_CATEGORIES.map((c, i) => [c, i]));\n findings.sort(\n (a, b) =>\n categoryOrder.get(a.category)! - categoryOrder.get(b.category)! ||\n b.confidence.score - a.confidence.score ||\n a.location.file.localeCompare(b.location.file) ||\n a.location.line - b.location.line,\n );\n\n return {\n schemaVersion: 1,\n tool: { name: 'deadwood', version: options.toolVersion ?? '0.0.0' },\n scannedAt: new Date().toISOString(),\n root,\n workspaces: units.map((u) => u.name),\n findings,\n stats: computeStats(graph, units, findings, routesTotal, Date.now() - startedAt),\n warnings: [...new Set(warnings)],\n };\n}\n\nfunction pushEntry(map: Map<ScanUnit, EntryPoint[]>, unit: ScanUnit, entry: EntryPoint): void {\n const list = map.get(unit);\n if (!list) {\n map.set(unit, [entry]);\n } else if (!list.some((e) => e.file === entry.file)) {\n list.push(entry);\n }\n}\n\n/** Conventional source entry for a package: src/index.*, index.*, src/main.*, or mapped main. */\nfunction guessUnitEntry(unit: ScanUnit, scannedFiles: ReadonlySet<string>): string | undefined {\n if (typeof unit.packageJson.main === 'string') {\n const mapped = resolveEntryRef(unit.dir, unit.packageJson.main, scannedFiles);\n if (mapped) return mapped;\n }\n for (const candidate of ['src/index', 'index', 'src/main', 'src/app', 'app', 'server', 'main']) {\n const hit = tryFile(path.join(unit.dir, candidate));\n if (hit && scannedFiles.has(toPosix(hit))) return toPosix(hit);\n }\n return undefined;\n}\n\nasync function collectManifestCallers(\n root: string,\n scannedFiles: ReadonlySet<string>,\n warnings: string[],\n): Promise<ManifestCaller[]> {\n const callers: ManifestCaller[] = [];\n const manifestFiles = await glob(\n [\n '.github/workflows/*.{yml,yaml}',\n '**/*.{yml,yaml}',\n '**/Dockerfile*',\n '**/crontab',\n '**/*.cron',\n '**/cron.d/**',\n 'webpack.config.{js,cjs,mjs,ts}',\n ],\n { cwd: root, ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'], dot: true },\n );\n\n for (const rel of manifestFiles.map(toPosix).sort()) {\n try {\n if (rel.startsWith('.github/workflows/')) {\n callers.push(...parseGithubWorkflow(root, rel, warnings));\n } else if (/(^|\\/)serverless\\.(yml|yaml)$/.test(rel)) {\n callers.push(...parseServerless(root, rel, warnings));\n } else if (/\\.(yml|yaml)$/.test(rel)) {\n callers.push(...parseK8sManifest(root, rel, warnings));\n } else if (/(^|\\/)Dockerfile/.test(rel)) {\n callers.push(...parseDockerfile(root, rel));\n } else if (isCrontabFile(rel)) {\n callers.push(...parseCrontab(root, rel));\n } else if (/(^|\\/)webpack\\.config\\./.test(rel)) {\n callers.push(...parseWebpackConfig(root, rel));\n }\n } catch {\n warnings.push(`Could not read manifest ${rel}; its callers are unknown.`);\n }\n }\n // Only callers that point at files we actually scanned matter downstream.\n return callers.filter((c) => scannedFiles.has(c.file));\n}\n\nfunction computeStats(\n graph: ModuleGraph,\n units: ScanUnit[],\n findings: Finding[],\n routesTotal: number,\n durationMs: number,\n): ScanStats {\n // \"Flagged\" for the headline = medium+ confidence. Low-confidence findings\n // stay visible in the report but don't inflate the shock stat — the shock\n // stat must survive scrutiny.\n const flagged = (category: FindingCategory) =>\n findings.filter((f) => f.category === category && f.confidence.score >= 50).length;\n\n let exportsTotal = 0;\n for (const pf of graph.files.values()) {\n exportsTotal += new Set(pf.exports.map((e) => e.name)).size;\n }\n let depsTotal = 0;\n for (const u of units) {\n depsTotal +=\n Object.keys(u.packageJson.dependencies ?? {}).length +\n Object.keys(u.packageJson.devDependencies ?? {}).length;\n }\n\n return {\n filesScanned: graph.files.size,\n durationMs,\n routes: { total: routesTotal, flagged: flagged('dead-route') },\n exports: { total: exportsTotal, flagged: flagged('unused-export') },\n dependencies: { total: depsTotal, flagged: flagged('unused-dependency') },\n files: { total: graph.files.size, flagged: flagged('unreachable-file') },\n };\n}\n","export type ScanErrorCode = 'INVALID_PATH' | 'NO_SOURCE_FILES';\n\n/**\n * Unrecoverable input problems. Anything the scan can survive degrades into\n * ScanResult.warnings instead — never throw for partial analysis failures.\n */\nexport class ScanError extends Error {\n constructor(\n readonly code: ScanErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'ScanError';\n }\n}\n","/**\n * Single syntactic parse pass per file. Deliberately NO ts.Program and no type\n * checker — the scanner must stay fast and work on repos that don't type-check.\n * Everything downstream (graph, detectors, evidence) consumes ParsedFile, so\n * each file's AST is walked exactly once here.\n */\nimport ts from 'typescript';\n\nexport interface ImportedName {\n /** Name as exported by the target module ('default' for default imports). */\n imported: string;\n local: string;\n}\n\nexport interface NamespaceUsage {\n /** Member names accessed off the namespace local (ns.foo → 'foo'). */\n members: Set<string>;\n /**\n * True when the namespace identifier is used as a value beyond direct\n * member access (passed around, computed access). Conservative: escapes\n * means every export of the target may be used.\n */\n escapes: boolean;\n}\n\nexport type ImportKind = 'static' | 'require' | 'dynamic' | 'reexport-named' | 'reexport-star';\n\nexport interface ImportRecord {\n specifier: string;\n kind: ImportKind;\n names: ImportedName[];\n namespaceLocal?: string;\n namespaceUsage?: NamespaceUsage;\n /** For reexport-named: the mapping `export { original as exported } from`. */\n reexported?: { exported: string; original: string }[];\n line: number;\n /** Filled by the resolver: absolute posix path when the target is in-repo. */\n resolvedFile?: string;\n /** Filled by the resolver: npm package name when the target is external. */\n resolvedPackage?: string;\n}\n\nexport type ExportKind = 'value' | 'type' | 'cjs';\n\nexport interface ExportRecord {\n name: string;\n kind: ExportKind;\n line: number;\n deprecated?: boolean;\n}\n\nexport interface DynamicPattern {\n kind: 'import' | 'require';\n /** Literal prefix of the specifier when partially static: `./handlers/${x}` → './handlers/'. */\n prefix?: string;\n line: number;\n}\n\nexport interface CommentMarker {\n line: number;\n type: 'deprecated' | 'removal';\n text: string;\n}\n\nexport interface PathLiteral {\n value: string;\n line: number;\n}\n\nexport interface ParsedFile {\n /** Absolute, posix-normalized. */\n file: string;\n ast: ts.SourceFile;\n imports: ImportRecord[];\n exports: ExportRecord[];\n dynamicPatterns: DynamicPattern[];\n commentMarkers: CommentMarker[];\n /** URL-ish string literals (start with '/') — the client-path index for route matching. */\n pathLiterals: PathLiteral[];\n /** module.exports[computed] seen — exports of this file are not fully knowable. */\n hasCjsDynamicExport: boolean;\n}\n\nconst DEPRECATED_RE = /@deprecated\\b/;\nconst REMOVAL_RE = /\\b(?:TODO:?\\s*(?:remove|delete|kill)|dead\\s*code|FIXME:?\\s*remove)\\b/i;\n\nfunction scriptKindFor(file: string): ts.ScriptKind {\n if (file.endsWith('.tsx')) return ts.ScriptKind.TSX;\n if (file.endsWith('.jsx')) return ts.ScriptKind.JSX;\n if (/\\.(ts|mts|cts)$/.test(file)) return ts.ScriptKind.TS;\n return ts.ScriptKind.JS;\n}\n\nexport function parseFile(filePosix: string, text: string): ParsedFile {\n const ast = ts.createSourceFile(\n filePosix,\n text,\n ts.ScriptTarget.Latest,\n true,\n scriptKindFor(filePosix),\n );\n const result: ParsedFile = {\n file: filePosix,\n ast,\n imports: [],\n exports: [],\n dynamicPatterns: [],\n commentMarkers: collectCommentMarkers(text),\n pathLiterals: [],\n hasCjsDynamicExport: false,\n };\n\n const lineOf = (node: ts.Node): number =>\n ast.getLineAndCharacterOfPosition(node.getStart(ast)).line + 1;\n\n const hasDeprecatedJsDoc = (node: ts.Node): boolean => {\n const ranges = ts.getLeadingCommentRanges(text, node.getFullStart()) ?? [];\n return ranges.some((r) => DEPRECATED_RE.test(text.slice(r.pos, r.end)));\n };\n\n // --- top-level import/export statements -----------------------------------\n for (const stmt of ast.statements) {\n if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier)) {\n const record: ImportRecord = {\n specifier: stmt.moduleSpecifier.text,\n kind: 'static',\n names: [],\n line: lineOf(stmt),\n };\n const clause = stmt.importClause;\n if (clause) {\n if (clause.name) record.names.push({ imported: 'default', local: clause.name.text });\n if (clause.namedBindings) {\n if (ts.isNamespaceImport(clause.namedBindings)) {\n record.namespaceLocal = clause.namedBindings.name.text;\n } else {\n for (const el of clause.namedBindings.elements) {\n record.names.push({\n imported: el.propertyName?.text ?? el.name.text,\n local: el.name.text,\n });\n }\n }\n }\n }\n result.imports.push(record);\n continue;\n }\n\n if (ts.isExportDeclaration(stmt)) {\n const spec = stmt.moduleSpecifier;\n if (spec && ts.isStringLiteral(spec)) {\n if (!stmt.exportClause) {\n result.imports.push({\n specifier: spec.text,\n kind: 'reexport-star',\n names: [],\n line: lineOf(stmt),\n });\n } else if (ts.isNamedExports(stmt.exportClause)) {\n const reexported = stmt.exportClause.elements.map((el) => ({\n exported: el.name.text,\n original: el.propertyName?.text ?? el.name.text,\n }));\n result.imports.push({\n specifier: spec.text,\n kind: 'reexport-named',\n names: [],\n reexported,\n line: lineOf(stmt),\n });\n // The barrel also *exports* these names; they are findings if unused.\n for (const r of reexported) {\n result.exports.push({ name: r.exported, kind: 'value', line: lineOf(stmt) });\n }\n } else if (ts.isNamespaceExport(stmt.exportClause)) {\n // export * as ns from './x' — the whole target may be used through us.\n result.imports.push({\n specifier: spec.text,\n kind: 'reexport-star',\n names: [],\n line: lineOf(stmt),\n });\n result.exports.push({\n name: stmt.exportClause.name.text,\n kind: 'value',\n line: lineOf(stmt),\n });\n }\n } else if (stmt.exportClause && ts.isNamedExports(stmt.exportClause)) {\n // export { a, b as c } — local names exported.\n for (const el of stmt.exportClause.elements) {\n result.exports.push({\n name: el.name.text,\n kind: 'value',\n line: lineOf(el),\n ...(hasDeprecatedJsDoc(stmt) ? { deprecated: true } : {}),\n });\n }\n }\n continue;\n }\n\n if (ts.isExportAssignment(stmt)) {\n // export default <expr> and `export =` both surface as 'default'.\n result.exports.push({ name: 'default', kind: 'value', line: lineOf(stmt) });\n continue;\n }\n\n collectModifierExports(stmt, result, lineOf, hasDeprecatedJsDoc);\n }\n\n // --- expression-level patterns (require, dynamic import, CJS exports, literals)\n const visit = (node: ts.Node): void => {\n if (ts.isCallExpression(node)) {\n handleCall(node, result, lineOf);\n } else if (\n ts.isBinaryExpression(node) &&\n node.operatorToken.kind === ts.SyntaxKind.EqualsToken\n ) {\n handleCjsExportAssignment(node, result, lineOf);\n } else if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {\n const v = node.text;\n // URL-ish literals feed route matching. '/' alone is kept — it's the\n // home route (a real <Link href=\"/\">), not noise; everything longer must\n // start with '/' and contain no whitespace.\n if (v.length < 200 && v.startsWith('/') && !/\\s/.test(v)) {\n result.pathLiterals.push({ value: v, line: lineOf(node) });\n }\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(ast, visit);\n\n // --- namespace usage tracking ----------------------------------------------\n const namespaceLocals = new Map<string, NamespaceUsage>();\n for (const imp of result.imports) {\n if (imp.namespaceLocal) {\n const usage: NamespaceUsage = { members: new Set(), escapes: false };\n imp.namespaceUsage = usage;\n namespaceLocals.set(imp.namespaceLocal, usage);\n }\n }\n if (namespaceLocals.size > 0) {\n trackNamespaceUsage(ast, namespaceLocals);\n }\n\n return result;\n}\n\nfunction collectModifierExports(\n stmt: ts.Statement,\n result: ParsedFile,\n lineOf: (n: ts.Node) => number,\n hasDeprecatedJsDoc: (n: ts.Node) => boolean,\n): void {\n const mods = ts.canHaveModifiers(stmt) ? ts.getModifiers(stmt) : undefined;\n if (!mods?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) return;\n const isDefault = mods.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword);\n const deprecated = hasDeprecatedJsDoc(stmt) ? true : undefined;\n const push = (name: string, kind: ExportKind, node: ts.Node) =>\n result.exports.push({ name, kind, line: lineOf(node), ...(deprecated ? { deprecated } : {}) });\n\n if (ts.isFunctionDeclaration(stmt) || ts.isClassDeclaration(stmt)) {\n push(isDefault ? 'default' : (stmt.name?.text ?? 'default'), 'value', stmt);\n } else if (ts.isVariableStatement(stmt)) {\n for (const decl of stmt.declarationList.declarations) {\n collectBindingNames(decl.name, (name) => push(name, 'value', decl));\n }\n } else if (ts.isInterfaceDeclaration(stmt) || ts.isTypeAliasDeclaration(stmt)) {\n push(stmt.name.text, 'type', stmt);\n } else if (ts.isEnumDeclaration(stmt) || ts.isModuleDeclaration(stmt)) {\n if (stmt.name && ts.isIdentifier(stmt.name)) push(stmt.name.text, 'value', stmt);\n }\n}\n\nfunction collectBindingNames(name: ts.BindingName, cb: (n: string) => void): void {\n if (ts.isIdentifier(name)) {\n cb(name.text);\n } else if (ts.isObjectBindingPattern(name) || ts.isArrayBindingPattern(name)) {\n for (const el of name.elements) {\n if (ts.isBindingElement(el)) collectBindingNames(el.name, cb);\n }\n }\n}\n\n/** Extract the static string prefix of a partially-dynamic specifier, if any. */\nfunction literalPrefixOf(arg: ts.Expression): string | undefined {\n if (ts.isTemplateExpression(arg) && arg.head.text.length > 0) return arg.head.text;\n if (\n ts.isBinaryExpression(arg) &&\n arg.operatorToken.kind === ts.SyntaxKind.PlusToken &&\n (ts.isStringLiteral(arg.left) || ts.isNoSubstitutionTemplateLiteral(arg.left))\n ) {\n return arg.left.text;\n }\n return undefined;\n}\n\nfunction handleCall(\n node: ts.CallExpression,\n result: ParsedFile,\n lineOf: (n: ts.Node) => number,\n): void {\n const line = lineOf(node);\n\n // require('...')\n if (\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'require' &&\n node.arguments.length === 1\n ) {\n const arg = node.arguments[0]!;\n if (ts.isStringLiteral(arg) || ts.isNoSubstitutionTemplateLiteral(arg)) {\n const record: ImportRecord = { specifier: arg.text, kind: 'require', names: [], line };\n bindRequireResult(node, record);\n result.imports.push(record);\n } else {\n const prefix = literalPrefixOf(arg);\n result.dynamicPatterns.push({ kind: 'require', line, ...(prefix ? { prefix } : {}) });\n }\n return;\n }\n\n // import('...')\n if (node.expression.kind === ts.SyntaxKind.ImportKeyword && node.arguments.length >= 1) {\n const arg = node.arguments[0]!;\n if (ts.isStringLiteral(arg) || ts.isNoSubstitutionTemplateLiteral(arg)) {\n // Dynamic import of a literal gives access to the whole namespace —\n // recorded as its own kind so usage analysis treats every export as used.\n result.imports.push({ specifier: arg.text, kind: 'dynamic', names: [], line });\n } else {\n const prefix = literalPrefixOf(arg);\n result.dynamicPatterns.push({ kind: 'import', line, ...(prefix ? { prefix } : {}) });\n }\n return;\n }\n\n // require.context('./dir', ...)\n if (\n ts.isPropertyAccessExpression(node.expression) &&\n ts.isIdentifier(node.expression.expression) &&\n node.expression.expression.text === 'require' &&\n node.expression.name.text === 'context' &&\n node.arguments.length >= 1\n ) {\n const arg = node.arguments[0]!;\n const prefix = ts.isStringLiteral(arg) ? arg.text : literalPrefixOf(arg);\n result.dynamicPatterns.push({ kind: 'require', line, ...(prefix ? { prefix } : {}) });\n }\n}\n\n/** const x = require('./y') / const { a, b } = require('./y') binding extraction. */\nfunction bindRequireResult(call: ts.CallExpression, record: ImportRecord): void {\n const parent = call.parent;\n if (parent && ts.isVariableDeclaration(parent) && parent.initializer === call) {\n if (ts.isIdentifier(parent.name)) {\n // Whole-module binding behaves like a namespace import for usage analysis.\n record.namespaceLocal = parent.name.text;\n } else if (ts.isObjectBindingPattern(parent.name)) {\n for (const el of parent.name.elements) {\n if (ts.isBindingElement(el) && ts.isIdentifier(el.name)) {\n const imported =\n el.propertyName && ts.isIdentifier(el.propertyName)\n ? el.propertyName.text\n : el.name.text;\n record.names.push({ imported, local: el.name.text });\n }\n }\n }\n }\n // `require('x').foo` or bare `require('x')` → side-effect/partial; names stay empty.\n}\n\nfunction handleCjsExportAssignment(\n node: ts.BinaryExpression,\n result: ParsedFile,\n lineOf: (n: ts.Node) => number,\n): void {\n const left = node.left;\n const line = lineOf(node);\n\n const isModuleExports = (e: ts.Expression): boolean =>\n ts.isPropertyAccessExpression(e) &&\n ts.isIdentifier(e.expression) &&\n e.expression.text === 'module' &&\n e.name.text === 'exports';\n\n // module.exports = ...\n if (isModuleExports(left)) {\n if (ts.isObjectLiteralExpression(node.right)) {\n // Named keys are the real export surface; a synthetic 'default' here\n // would false-positive on every `const { x } = require(...)` consumer.\n for (const prop of node.right.properties) {\n const name = prop.name;\n if (name && (ts.isIdentifier(name) || ts.isStringLiteral(name))) {\n result.exports.push({ name: name.text, kind: 'cjs', line });\n }\n }\n } else {\n result.exports.push({ name: 'default', kind: 'cjs', line });\n }\n return;\n }\n\n // module.exports.foo = ... | exports.foo = ...\n if (ts.isPropertyAccessExpression(left)) {\n const base = left.expression;\n const isExportsBase =\n (ts.isIdentifier(base) && base.text === 'exports') || isModuleExports(base);\n if (isExportsBase && left.name.text !== '__esModule') {\n result.exports.push({ name: left.name.text, kind: 'cjs', line });\n }\n return;\n }\n\n // module.exports[computed] = ... — exports not statically knowable.\n if (ts.isElementAccessExpression(left)) {\n const base = left.expression;\n if ((ts.isIdentifier(base) && base.text === 'exports') || isModuleExports(base)) {\n result.hasCjsDynamicExport = true;\n }\n }\n}\n\nfunction trackNamespaceUsage(ast: ts.SourceFile, locals: Map<string, NamespaceUsage>): void {\n const visit = (node: ts.Node): void => {\n if (ts.isIdentifier(node) && locals.has(node.text)) {\n const usage = locals.get(node.text)!;\n const parent = node.parent;\n const isDeclarationSite =\n parent &&\n ((ts.isNamespaceImport(parent) && parent.name === node) ||\n (ts.isVariableDeclaration(parent) && parent.name === node) ||\n (ts.isImportSpecifier(parent) && parent.name === node));\n if (!isDeclarationSite) {\n if (parent && ts.isPropertyAccessExpression(parent) && parent.expression === node) {\n usage.members.add(parent.name.text);\n } else {\n // Computed access, passed as argument, spread, returned… we can no\n // longer enumerate which members are used. Conservative: all used.\n usage.escapes = true;\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(ast, visit);\n}\n\nfunction collectCommentMarkers(text: string): CommentMarker[] {\n const markers: CommentMarker[] = [];\n const lines = text.split(/\\r?\\n/);\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n // Only look inside comment-ish content to avoid matching string literals.\n if (!/\\/\\/|\\/\\*|^\\s*\\*/.test(line)) continue;\n if (DEPRECATED_RE.test(line)) {\n markers.push({ line: i + 1, type: 'deprecated', text: line.trim() });\n } else if (REMOVAL_RE.test(line)) {\n markers.push({ line: i + 1, type: 'removal', text: line.trim() });\n }\n }\n return markers;\n}\n","/**\n * The shared substrate every detector queries: one global graph across all\n * workspace packages (per-unit graphs would false-positive exports that are\n * only used by a sibling package).\n */\nimport type { ImportRecord, ParsedFile } from './parser.js';\nimport type { Resolver } from './resolver.js';\n\nexport interface ImporterEdge {\n importer: string; // absolute posix\n record: ImportRecord;\n}\n\nexport class ModuleGraph {\n readonly files = new Map<string, ParsedFile>();\n private reverse = new Map<string, ImporterEdge[]>();\n\n addFile(pf: ParsedFile): void {\n this.files.set(pf.file, pf);\n }\n\n /** Resolve every import record and build the reverse index. Call once after all addFile(). */\n link(resolver: Resolver): void {\n for (const pf of this.files.values()) {\n for (const record of pf.imports) {\n const res = resolver.resolve(record.specifier, pf.file);\n if (res.file && this.files.has(res.file)) {\n record.resolvedFile = res.file;\n let edges = this.reverse.get(res.file);\n if (!edges) this.reverse.set(res.file, (edges = []));\n edges.push({ importer: pf.file, record });\n } else if (res.pkg) {\n record.resolvedPackage = res.pkg;\n }\n }\n }\n }\n\n importersOf(file: string): ImporterEdge[] {\n return this.reverse.get(file) ?? [];\n }\n\n /** BFS over resolved edges (all kinds — static, require, dynamic-literal, reexports). */\n reachable(entries: Iterable<string>): Set<string> {\n const seen = new Set<string>();\n const queue: string[] = [];\n for (const e of entries) {\n if (this.files.has(e) && !seen.has(e)) {\n seen.add(e);\n queue.push(e);\n }\n }\n while (queue.length > 0) {\n const file = queue.shift()!;\n const pf = this.files.get(file)!;\n for (const record of pf.imports) {\n const next = record.resolvedFile;\n if (next && !seen.has(next)) {\n seen.add(next);\n queue.push(next);\n }\n }\n }\n return seen;\n }\n\n /**\n * Is `name` (exported by `file`) forwarded by re-export chains into any of\n * the `targets` files? Used to detect public-API exposure through entry\n * barrels — external consumers of those are invisible to static analysis.\n */\n isReexportedThrough(\n file: string,\n name: string,\n targets: ReadonlySet<string>,\n visited = new Set<string>(),\n ): boolean {\n const key = `${file}#${name}`;\n if (visited.has(key)) return false;\n visited.add(key);\n\n for (const { importer, record } of this.importersOf(file)) {\n let forwardedAs: string | undefined;\n if (record.kind === 'reexport-star' && name !== 'default') {\n forwardedAs = name;\n } else if (record.kind === 'reexport-named') {\n forwardedAs = record.reexported?.find((r) => r.original === name)?.exported;\n }\n if (!forwardedAs) continue;\n if (targets.has(importer)) return true;\n if (this.isReexportedThrough(importer, forwardedAs, targets, visited)) return true;\n }\n return false;\n }\n\n /**\n * Is `name` exported by `file` consumed anywhere, following re-export chains\n * through barrels? Conservative by construction: namespace imports whose\n * usage can't be fully traced count as usage.\n */\n isExportUsed(file: string, name: string, visited = new Set<string>()): boolean {\n const key = `${file}#${name}`;\n if (visited.has(key)) return false; // re-export cycle\n visited.add(key);\n\n for (const { importer, record } of this.importersOf(file)) {\n switch (record.kind) {\n case 'static':\n case 'require': {\n if (record.names.some((n) => n.imported === name)) return true;\n const ns = record.namespaceUsage;\n if (ns && (ns.escapes || ns.members.has(name))) return true;\n break;\n }\n case 'dynamic':\n // import('./x') yields the whole namespace — every export reachable.\n return true;\n case 'reexport-named': {\n const match = record.reexported?.find((r) => r.original === name);\n if (match && this.isExportUsed(importer, match.exported, visited)) return true;\n break;\n }\n case 'reexport-star':\n // `export *` does not forward default exports.\n if (name !== 'default' && this.isExportUsed(importer, name, visited)) return true;\n break;\n }\n }\n return false;\n }\n}\n","/**\n * Import-specifier resolution. Uses ts.resolveModuleName against the *nearest*\n * tsconfig walking up from the importing file, so nested packages with their\n * own `paths` aliases resolve correctly. Degrades to plain relative resolution\n * (with a warning) rather than guessing when a tsconfig won't parse.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { builtinModules } from 'node:module';\nimport ts from 'typescript';\nimport { dirnamePosix, toPosix } from '../util/paths.js';\n\nconst BUILTINS = new Set(builtinModules);\n\nconst RESOLVE_EXTENSIONS = ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs'];\n\nexport interface Resolution {\n /** Absolute posix path when the import points at a file inside the repo. */\n file?: string;\n /** npm package name when the import is external (or simply not installed). */\n pkg?: string;\n}\n\nexport interface WorkspaceEntry {\n name: string;\n dir: string; // absolute posix\n entryFile?: string; // best-guess source entry, absolute posix\n}\n\nconst DEFAULT_OPTIONS: ts.CompilerOptions = {\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n module: ts.ModuleKind.ESNext,\n target: ts.ScriptTarget.Latest,\n allowJs: true,\n resolveJsonModule: true,\n};\n\nexport class Resolver {\n /** dir → compiler options of the nearest tsconfig (or defaults). */\n private optionsByDir = new Map<string, ts.CompilerOptions>();\n /** tsconfig path → parsed options. */\n private parsedConfigs = new Map<string, ts.CompilerOptions>();\n private warnedConfigs = new Set<string>();\n\n constructor(\n private readonly rootDir: string,\n private readonly workspacePackages: WorkspaceEntry[],\n private readonly scannedFiles: ReadonlySet<string>,\n private readonly warnings: string[],\n ) {}\n\n resolve(specifier: string, containingFile: string): Resolution {\n if (specifier.startsWith('node:')) return {};\n if (BUILTINS.has(specifier) || BUILTINS.has(specifier.split('/')[0]!)) return {};\n\n // Workspace packages take precedence over node_modules resolution: an\n // installed copy is a symlink to the package's dist/ build, which would\n // swallow real cross-package usage (the import would look external and\n // the edge to the source files would be lost).\n const wsFirst = this.resolveWorkspace(specifier);\n if (wsFirst?.file && this.scannedFiles.has(wsFirst.file)) return wsFirst;\n\n const options = this.optionsFor(dirnamePosix(containingFile));\n const r = ts.resolveModuleName(specifier, containingFile, options, ts.sys);\n const resolved = r.resolvedModule;\n if (resolved) {\n const file = toPosix(resolved.resolvedFileName);\n if (!resolved.isExternalLibraryImport && !file.includes('/node_modules/')) {\n if (this.scannedFiles.has(file)) return { file };\n // Resolution landed outside the scan set — typically a workspace\n // package's dist/ build or a .d.ts. Re-route to scanned sources so\n // the import edge isn't silently dropped (that loses real usage).\n const ws = this.resolveWorkspace(specifier);\n if (ws?.file && this.scannedFiles.has(ws.file)) return ws;\n if (specifier.startsWith('.')) {\n const manual = tryFile(path.resolve(path.dirname(containingFile), specifier));\n if (manual && this.scannedFiles.has(toPosix(manual))) return { file: toPosix(manual) };\n return {};\n }\n return { pkg: packageNameOf(specifier) };\n }\n return { pkg: resolved.packageId?.name ?? packageNameOf(specifier) };\n }\n\n // Workspace packages may not be installed (no node_modules) — resolve by name.\n const ws = this.resolveWorkspace(specifier);\n if (ws) return ws;\n\n if (specifier.startsWith('.') || specifier.startsWith('/')) {\n const manual = tryFile(path.resolve(path.dirname(containingFile), specifier));\n if (manual) return { file: toPosix(manual) };\n return {}; // broken relative import — not our finding to make\n }\n\n // Bare specifier that didn't resolve: still an npm package for unused-deps\n // analysis (deps don't need to be installed for us to reason about them).\n return { pkg: packageNameOf(specifier) };\n }\n\n private resolveWorkspace(specifier: string): Resolution | undefined {\n for (const ws of this.workspacePackages) {\n if (specifier === ws.name) {\n return ws.entryFile ? { file: ws.entryFile } : { pkg: ws.name };\n }\n if (specifier.startsWith(ws.name + '/')) {\n const sub = specifier.slice(ws.name.length + 1);\n const hit = tryFile(path.join(ws.dir, sub)) ?? tryFile(path.join(ws.dir, 'src', sub));\n return hit ? { file: toPosix(hit) } : { pkg: ws.name };\n }\n }\n return undefined;\n }\n\n private optionsFor(dirPosix: string): ts.CompilerOptions {\n const cached = this.optionsByDir.get(dirPosix);\n if (cached) return cached;\n\n let options = DEFAULT_OPTIONS;\n let dir = dirPosix;\n while (true) {\n const candidate = dir + '/tsconfig.json';\n if (fs.existsSync(candidate)) {\n options = this.parseConfig(candidate);\n break;\n }\n if (dir === this.rootDir || !dir.startsWith(this.rootDir)) break;\n const parent = dirnamePosix(dir);\n if (parent === dir) break;\n dir = parent;\n }\n this.optionsByDir.set(dirPosix, options);\n return options;\n }\n\n private parseConfig(tsconfigPath: string): ts.CompilerOptions {\n const cached = this.parsedConfigs.get(tsconfigPath);\n if (cached) return cached;\n\n let options = DEFAULT_OPTIONS;\n const read = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n if (read.error) {\n this.warnConfig(tsconfigPath);\n } else {\n const parsed = ts.parseJsonConfigFileContent(read.config, ts.sys, path.dirname(tsconfigPath));\n // Config-level errors (e.g. missing referenced files) don't invalidate\n // compilerOptions for resolution purposes; only warn on hard failures.\n if (\n parsed.errors.some((e) => e.category === ts.DiagnosticCategory.Error && e.code === 5083)\n ) {\n this.warnConfig(tsconfigPath);\n }\n options = {\n ...parsed.options,\n allowJs: true,\n resolveJsonModule: true,\n // Classic resolution predates node_modules conventions; never useful here.\n moduleResolution:\n !parsed.options.moduleResolution ||\n parsed.options.moduleResolution === ts.ModuleResolutionKind.Classic\n ? ts.ModuleResolutionKind.Bundler\n : parsed.options.moduleResolution,\n };\n }\n this.parsedConfigs.set(tsconfigPath, options);\n return options;\n }\n\n private warnConfig(tsconfigPath: string): void {\n if (this.warnedConfigs.has(tsconfigPath)) return;\n this.warnedConfigs.add(tsconfigPath);\n this.warnings.push(\n `Could not parse ${toPosix(path.relative(this.rootDir, tsconfigPath))}; path aliases from it are ignored.`,\n );\n }\n}\n\nexport function packageNameOf(specifier: string): string {\n const parts = specifier.split('/');\n return specifier.startsWith('@') && parts.length >= 2 ? `${parts[0]}/${parts[1]}` : parts[0]!;\n}\n\n/** Try a path as-is, with source extensions, and as a directory index. */\nexport function tryFile(p: string): string | undefined {\n if (fs.existsSync(p) && fs.statSync(p).isFile()) return p;\n for (const ext of RESOLVE_EXTENSIONS) {\n if (fs.existsSync(p + ext)) return p + ext;\n }\n for (const ext of RESOLVE_EXTENSIONS) {\n const idx = path.join(p, 'index' + ext);\n if (fs.existsSync(idx)) return idx;\n }\n return undefined;\n}\n","import path from 'node:path';\n\n/**\n * All paths inside the engine are posix-style. Normalization happens at every\n * filesystem boundary so Windows backslashes can never leak into findings,\n * reports, or snapshots.\n */\nexport function toPosix(p: string): string {\n return p.replace(/\\\\/g, '/');\n}\n\nexport function absPosix(p: string): string {\n return toPosix(path.resolve(p));\n}\n\nexport function relPosix(from: string, to: string): string {\n return toPosix(path.relative(from, to));\n}\n\nexport function dirnamePosix(p: string): string {\n return toPosix(path.dirname(p));\n}\n\nexport function joinPosix(...parts: string[]): string {\n return toPosix(path.join(...parts));\n}\n\nexport function isUnder(dir: string, file: string): boolean {\n return file === dir || file.startsWith(dir.endsWith('/') ? dir : dir + '/');\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { glob } from 'tinyglobby';\nimport { parse as parseYaml } from 'yaml';\nimport { toPosix } from '../util/paths.js';\n\nexport interface PackageJsonLike {\n name?: string;\n main?: string;\n module?: string;\n browser?: string | Record<string, unknown>;\n types?: string;\n bin?: string | Record<string, string>;\n exports?: unknown;\n scripts?: Record<string, string>;\n workspaces?: string[] | { packages?: string[] };\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nexport interface ScanUnit {\n /** Package name, or '.' for an unnamed root. */\n name: string;\n /** Absolute posix dir. */\n dir: string;\n packageJson: PackageJsonLike;\n}\n\nexport async function discoverWorkspaces(\n root: string,\n): Promise<{ units: ScanUnit[]; warnings: string[] }> {\n const warnings: string[] = [];\n const units: ScanUnit[] = [];\n\n const rootPkg = readPackageJson(path.join(root, 'package.json'), warnings);\n units.push({ name: rootPkg?.name ?? '.', dir: root, packageJson: rootPkg ?? {} });\n if (!rootPkg) {\n warnings.push('No package.json at the scan root; dependency analysis is limited.');\n }\n\n const globs = workspaceGlobs(root, rootPkg);\n if (globs.length > 0) {\n const pkgFiles = await glob(\n globs.map((g) => `${g.replace(/\\/$/, '')}/package.json`),\n { cwd: root, ignore: ['**/node_modules/**'], absolute: true },\n );\n for (const pkgFile of pkgFiles.sort()) {\n const pkg = readPackageJson(pkgFile, warnings);\n if (!pkg) continue;\n const dir = toPosix(path.dirname(pkgFile));\n units.push({ name: pkg.name ?? toPosix(path.relative(root, dir)), dir, packageJson: pkg });\n }\n }\n\n return { units, warnings };\n}\n\nfunction workspaceGlobs(root: string, rootPkg: PackageJsonLike | undefined): string[] {\n const pnpmWs = path.join(root, 'pnpm-workspace.yaml');\n if (fs.existsSync(pnpmWs)) {\n try {\n const parsed = parseYaml(fs.readFileSync(pnpmWs, 'utf8')) as { packages?: string[] };\n if (Array.isArray(parsed?.packages)) return parsed.packages.filter((p) => !p.startsWith('!'));\n } catch {\n // fall through to package.json workspaces\n }\n }\n const ws = rootPkg?.workspaces;\n if (Array.isArray(ws)) return ws;\n if (ws && Array.isArray(ws.packages)) return ws.packages;\n return [];\n}\n\nfunction readPackageJson(file: string, warnings: string[]): PackageJsonLike | undefined {\n if (!fs.existsSync(file)) return undefined;\n try {\n return JSON.parse(fs.readFileSync(file, 'utf8')) as PackageJsonLike;\n } catch {\n warnings.push(`Could not parse ${toPosix(file)}; treating package as empty.`);\n return undefined;\n }\n}\n\n/** Which unit owns a file: the deepest unit dir that contains it. */\nexport function unitForFile(units: ScanUnit[], file: string): ScanUnit {\n let best = units[0]!;\n for (const u of units) {\n if ((file === u.dir || file.startsWith(u.dir + '/')) && u.dir.length > best.dir.length) {\n best = u;\n }\n }\n // Root unit contains everything by construction.\n if (!(file === best.dir || file.startsWith(best.dir + '/'))) return units[0]!;\n return best;\n}\n","/**\n * Entry-point discovery — the main false-positive lever. Anything a framework,\n * script, or manifest treats as a program start must be an entry, otherwise\n * whole live subtrees look unreachable.\n */\nimport path from 'node:path';\nimport { extractFileRefs } from '../manifest/fileRefs.js';\nimport { tryFile } from '../graph/resolver.js';\nimport { toPosix } from '../util/paths.js';\nimport type { PackageJsonLike, ScanUnit } from './workspaces.js';\n\nexport type EntryReason =\n | 'main'\n | 'module'\n | 'browser'\n | 'bin'\n | 'exports'\n | 'script'\n | 'framework'\n | 'config'\n | 'manifest'\n | 'test'\n | 'cli-flag';\n\nexport interface EntryPoint {\n /** Absolute posix path, guaranteed to be in the scan set. */\n file: string;\n reason: EntryReason;\n /** 'test' entries count for reachability but test-only reachability is kill evidence. */\n tag?: 'test';\n detail?: string;\n}\n\nconst BUILD_DIRS = ['dist', 'build', 'lib', 'out', 'output', '.next'];\n\nconst TEST_FILE_RE = /(\\.|\\/)(test|spec)\\.[mc]?[jt]sx?$|\\/__tests__\\/|^tests?\\//;\n\nexport function isTestFile(relPath: string): boolean {\n return TEST_FILE_RE.test(relPath);\n}\n\nconst CONFIG_FILE_RE = /(^|\\/)[\\w.-]+\\.config\\.[mc]?[jt]s$|(^|\\/)\\.\\w+rc\\.[mc]?js$/;\n\nexport function discoverEntryPoints(\n unit: ScanUnit,\n scannedFiles: ReadonlySet<string>,\n warnings: string[],\n): EntryPoint[] {\n const entries: EntryPoint[] = [];\n const seen = new Set<string>();\n const pkg = unit.packageJson;\n\n const add = (file: string, reason: EntryReason, detail?: string, tag?: 'test') => {\n if (!seen.has(file) && scannedFiles.has(file)) {\n seen.add(file);\n entries.push({ file, reason, ...(tag ? { tag } : {}), ...(detail ? { detail } : {}) });\n }\n };\n\n const addRef = (ref: string, reason: EntryReason, detail?: string) => {\n const resolved = resolveEntryRef(unit.dir, ref, scannedFiles);\n if (resolved) {\n add(resolved, reason, detail);\n } else if (['main', 'module', 'bin', 'exports'].includes(reason)) {\n warnings.push(\n `Entry '${ref}' in ${unit.name}/package.json does not map to a scanned source file.`,\n );\n }\n };\n\n // package.json fields\n if (typeof pkg.main === 'string') addRef(pkg.main, 'main');\n if (typeof pkg.module === 'string') addRef(pkg.module, 'module');\n if (typeof pkg.browser === 'string') addRef(pkg.browser, 'browser');\n if (typeof pkg.bin === 'string') addRef(pkg.bin, 'bin');\n else if (pkg.bin && typeof pkg.bin === 'object') {\n for (const target of Object.values(pkg.bin)) addRef(target, 'bin');\n }\n for (const target of exportsTargets(pkg.exports)) addRef(target, 'exports');\n\n // scripts: `node src/x.js`, `tsx scripts/y.ts`, …\n for (const [scriptName, command] of Object.entries(pkg.scripts ?? {})) {\n for (const ref of extractFileRefs(command)) {\n addRef(ref, 'script', `package.json script '${scriptName}'`);\n }\n }\n\n // framework conventions\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps['next']) {\n for (const file of scannedFiles) {\n const rel = relTo(unit.dir, file);\n if (rel && /^(pages|app|src\\/pages|src\\/app)\\//.test(rel))\n add(file, 'framework', 'Next.js route convention');\n if (rel && /^(src\\/)?middleware\\.[jt]s$/.test(rel))\n add(file, 'framework', 'Next.js middleware');\n }\n }\n if (deps['@nestjs/core']) {\n const main = tryFile(path.join(unit.dir, 'src/main'));\n if (main) add(toPosix(main), 'framework', 'NestJS bootstrap');\n }\n\n // tool config files at the unit root are programs in their own right\n for (const file of scannedFiles) {\n const rel = relTo(unit.dir, file);\n if (rel && !rel.includes('/') && CONFIG_FILE_RE.test(rel)) {\n add(file, 'config', 'tool configuration file');\n }\n }\n\n // test files: entries (their imports are reachable) but tagged — test-only\n // reachability becomes kill evidence downstream.\n for (const file of scannedFiles) {\n const rel = relTo(unit.dir, file);\n if (rel && isTestFile(rel)) add(file, 'test', undefined, 'test');\n }\n\n return entries;\n}\n\n/**\n * Resolve a package.json-style file reference to a *scanned source* file.\n * Build-output references (dist/index.js) are mapped back to src candidates —\n * an entry pointing at compiled output must not poison reachability (G2).\n * When `scannedFiles` is given, a candidate that exists on disk but is outside\n * the scan set (e.g. an actual dist/ build) is rejected so the mapper can fall\n * through to the source-file candidates.\n */\nexport function resolveEntryRef(\n unitDir: string,\n ref: string,\n scannedFiles?: ReadonlySet<string>,\n): string | undefined {\n const accept = (p: string | undefined): string | undefined => {\n if (!p) return undefined;\n const posix = toPosix(p);\n return !scannedFiles || scannedFiles.has(posix) ? posix : undefined;\n };\n\n const clean = ref.replace(/^\\.\\//, '');\n const direct = accept(tryFile(path.join(unitDir, clean)));\n if (direct) return direct;\n\n const parts = clean.split('/');\n const first = parts[0]!;\n if (BUILD_DIRS.includes(first)) {\n const rest = parts.slice(1).join('/');\n const stripped = rest.replace(/\\.(js|mjs|cjs|d\\.ts)$/, '');\n for (const base of [`src/${stripped}`, stripped]) {\n const hit = accept(tryFile(path.join(unitDir, base)));\n if (hit) return hit;\n }\n }\n return undefined;\n}\n\n/** Collect every string leaf of a package.json `exports` map. */\nfunction exportsTargets(exp: unknown): string[] {\n const out: string[] = [];\n const walk = (value: unknown): void => {\n if (typeof value === 'string') {\n if (!value.endsWith('.d.ts')) out.push(value);\n } else if (value && typeof value === 'object') {\n for (const v of Object.values(value)) walk(v);\n }\n };\n walk(exp);\n return out;\n}\n\nfunction relTo(dir: string, file: string): string | undefined {\n return file.startsWith(dir + '/') ? file.slice(dir.length + 1) : undefined;\n}\n","/**\n * Shared extractor for \"this command runs that source file\" references found\n * in scripts, crontabs, CI workflows, container specs, etc.\n */\nconst RUNNER_RE =\n /(?:^|[\\s;&|(\"'`])(?:node|tsx|ts-node(?:-esm)?|nodemon|vite-node|bun)\\s+(?:-{1,2}[\\w-]+(?:[= ][^\\s;&|\"'`]+)?\\s+)*[\"']?([^\\s;&|\"'`)]+\\.(?:m?[jt]s|[jt]sx|c[jt]s))[\"']?/g;\n\nexport function extractFileRefs(text: string): string[] {\n const refs: string[] = [];\n for (const match of text.matchAll(RUNNER_RE)) {\n refs.push(match[1]!);\n }\n return refs;\n}\n","/**\n * Crontab parsing: files named `crontab`, `*.cron`, or living under `cron.d/`.\n * Every line that runs a JS/TS file is a hidden caller.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { extractFileRefs } from './fileRefs.js';\nimport { tryFile } from '../graph/resolver.js';\nimport { toPosix } from '../util/paths.js';\nimport type { ManifestCaller } from './types.js';\n\nexport function isCrontabFile(relPath: string): boolean {\n return /(^|\\/)crontab$|\\.cron$|(^|\\/)cron\\.d\\//.test(relPath);\n}\n\nexport function parseCrontab(root: string, manifestRel: string): ManifestCaller[] {\n const callers: ManifestCaller[] = [];\n const text = fs.readFileSync(path.join(root, manifestRel), 'utf8');\n for (const rawLine of text.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith('#')) continue;\n const fields = line.split(/\\s+/);\n // Standard crontab: 5 schedule fields then the command (@daily etc. = 1 field).\n const schedule = line.startsWith('@') ? fields[0]! : fields.slice(0, 5).join(' ');\n for (const ref of extractFileRefs(line)) {\n const resolved = tryFile(path.resolve(root, ref));\n if (resolved) {\n callers.push({\n file: toPosix(resolved),\n manifest: manifestRel,\n kind: 'crontab',\n detail: `cron '${schedule}' runs ${ref}`,\n });\n }\n }\n }\n return callers;\n}\n","/**\n * GitHub Actions workflows: any `run:` step that executes a JS/TS file makes\n * that file a hidden caller target (it runs in CI even if nothing imports it).\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { extractFileRefs } from './fileRefs.js';\nimport { tryFile } from '../graph/resolver.js';\nimport { toPosix } from '../util/paths.js';\nimport type { ManifestCaller } from './types.js';\n\ninterface WorkflowStep {\n run?: unknown;\n name?: unknown;\n}\ninterface WorkflowJob {\n steps?: WorkflowStep[];\n}\ninterface Workflow {\n jobs?: Record<string, WorkflowJob>;\n}\n\nexport function parseGithubWorkflow(\n root: string,\n manifestRel: string,\n warnings: string[],\n): ManifestCaller[] {\n const callers: ManifestCaller[] = [];\n let doc: Workflow;\n try {\n doc = parseYaml(fs.readFileSync(path.join(root, manifestRel), 'utf8')) as Workflow;\n } catch {\n warnings.push(`Could not parse workflow ${manifestRel}; its callers are unknown.`);\n return callers;\n }\n for (const [jobName, job] of Object.entries(doc?.jobs ?? {})) {\n for (const step of job?.steps ?? []) {\n if (typeof step?.run !== 'string') continue;\n for (const ref of extractFileRefs(step.run)) {\n const resolved = tryFile(path.resolve(root, ref));\n if (resolved) {\n callers.push({\n file: toPosix(resolved),\n manifest: manifestRel,\n kind: 'github-actions',\n detail: `GitHub Actions job '${jobName}' runs ${ref}`,\n });\n }\n }\n }\n }\n return callers;\n}\n","/**\n * Kubernetes manifests: CronJob/Job/Deployment container command+args that run\n * a JS/TS file are hidden callers. Any yaml with apiVersion+kind qualifies.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { parseAllDocuments } from 'yaml';\nimport { extractFileRefs } from './fileRefs.js';\nimport { tryFile } from '../graph/resolver.js';\nimport { toPosix } from '../util/paths.js';\nimport type { ManifestCaller } from './types.js';\n\ninterface Container {\n command?: unknown[];\n args?: unknown[];\n}\n\nexport function parseK8sManifest(\n root: string,\n manifestRel: string,\n warnings: string[],\n): ManifestCaller[] {\n const callers: ManifestCaller[] = [];\n let docs;\n try {\n docs = parseAllDocuments(fs.readFileSync(path.join(root, manifestRel), 'utf8'));\n } catch {\n warnings.push(`Could not parse yaml ${manifestRel}; its callers are unknown.`);\n return callers;\n }\n for (const doc of docs) {\n const obj = doc?.toJS?.() as Record<string, unknown> | undefined;\n if (!obj || typeof obj !== 'object' || !obj['apiVersion'] || !obj['kind']) continue;\n const kind = String(obj['kind']);\n for (const container of containersOf(obj)) {\n const cmd = [...(container.command ?? []), ...(container.args ?? [])]\n .filter((c): c is string => typeof c === 'string')\n .join(' ');\n for (const ref of extractFileRefs(cmd)) {\n const resolved = tryFile(path.resolve(root, ref));\n if (resolved) {\n callers.push({\n file: toPosix(resolved),\n manifest: manifestRel,\n kind: 'k8s',\n detail: `k8s ${kind} container runs ${ref}`,\n });\n }\n }\n }\n }\n return callers;\n}\n\n/** Walk the object tree for `containers:` arrays — covers CronJob/Job/Deployment/Pod nesting. */\nfunction containersOf(obj: unknown): Container[] {\n const out: Container[] = [];\n const walk = (value: unknown): void => {\n if (Array.isArray(value)) {\n for (const v of value) walk(v);\n } else if (value && typeof value === 'object') {\n const rec = value as Record<string, unknown>;\n if (Array.isArray(rec['containers'])) {\n for (const c of rec['containers']) {\n if (c && typeof c === 'object') out.push(c as Container);\n }\n }\n for (const v of Object.values(rec)) walk(v);\n }\n };\n walk(obj);\n return out;\n}\n","/**\n * Build/deploy configs that reference source files: Dockerfile CMD/ENTRYPOINT,\n * serverless.yml function handlers, webpack entry points.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { extractFileRefs } from './fileRefs.js';\nimport { tryFile } from '../graph/resolver.js';\nimport { toPosix } from '../util/paths.js';\nimport type { ManifestCaller } from './types.js';\n\nexport function parseDockerfile(root: string, manifestRel: string): ManifestCaller[] {\n const callers: ManifestCaller[] = [];\n const text = fs.readFileSync(path.join(root, manifestRel), 'utf8');\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*(CMD|ENTRYPOINT)\\s+(.*)$/i.exec(line);\n if (!m) continue;\n // JSON-array exec form → join to a shell-like string for the extractor.\n let command = m[2]!.trim();\n if (command.startsWith('[')) {\n try {\n const arr = JSON.parse(command) as unknown[];\n command = arr.filter((a): a is string => typeof a === 'string').join(' ');\n } catch {\n // malformed exec form; fall through with raw text\n }\n }\n for (const ref of extractFileRefs(command)) {\n const resolved = tryFile(path.resolve(root, ref));\n if (resolved) {\n callers.push({\n file: toPosix(resolved),\n manifest: manifestRel,\n kind: 'dockerfile',\n detail: `Dockerfile ${m[1]!.toUpperCase()} runs ${ref}`,\n });\n }\n }\n }\n return callers;\n}\n\ninterface ServerlessConfig {\n functions?: Record<string, { handler?: unknown }>;\n}\n\nexport function parseServerless(\n root: string,\n manifestRel: string,\n warnings: string[],\n): ManifestCaller[] {\n const callers: ManifestCaller[] = [];\n let doc: ServerlessConfig;\n try {\n doc = parseYaml(fs.readFileSync(path.join(root, manifestRel), 'utf8')) as ServerlessConfig;\n } catch {\n warnings.push(`Could not parse ${manifestRel}; its handlers are unknown.`);\n return callers;\n }\n for (const [fnName, fn] of Object.entries(doc?.functions ?? {})) {\n if (typeof fn?.handler !== 'string') continue;\n // Handler format: path/to/file.exportName — strip the export segment.\n const fileBase = fn.handler.slice(0, fn.handler.lastIndexOf('.'));\n const resolved = tryFile(path.resolve(root, fileBase));\n if (resolved) {\n callers.push({\n file: toPosix(resolved),\n manifest: manifestRel,\n kind: 'serverless',\n detail: `serverless function '${fnName}' handler`,\n });\n }\n }\n return callers;\n}\n\n/**\n * Webpack configs are arbitrary JS — evaluating them is out of scope, so we\n * extract quoted strings from the `entry` property region only. Best-effort by\n * design; a missed entry surfaces as a (visible) unreachable-file finding the\n * user can suppress with --entry.\n */\nexport function parseWebpackConfig(root: string, manifestRel: string): ManifestCaller[] {\n const callers: ManifestCaller[] = [];\n const text = fs.readFileSync(path.join(root, manifestRel), 'utf8');\n const entryMatch = /\\bentry\\s*:\\s*(\\{[^}]*\\}|\\[[^\\]]*\\]|['\"][^'\"]+['\"])/s.exec(text);\n if (!entryMatch) return callers;\n for (const str of entryMatch[1]!.matchAll(/['\"]([^'\"]+)['\"]/g)) {\n const resolved = tryFile(path.resolve(root, str[1]!));\n if (resolved) {\n callers.push({\n file: toPosix(resolved),\n manifest: manifestRel,\n kind: 'webpack',\n detail: `webpack entry`,\n });\n }\n }\n return callers;\n}\n","/**\n * The signal registry — the ONLY place confidence weights live.\n * Detectors and evidence providers reference signals by id; tuning the\n * scoring model means editing this table, nothing else.\n */\nimport type {\n Evidence,\n EvidenceDirection,\n EvidenceSource,\n FindingCategory,\n SourceLocation,\n} from './finding.js';\n\nexport interface SignalSpec {\n id: string;\n source: EvidenceSource;\n direction: EvidenceDirection;\n /** Signed: kill positive, spare negative. */\n weight: number;\n description: string;\n}\n\nfunction kill(id: string, weight: number, description: string): SignalSpec {\n return { id, source: 'static', direction: 'kill', weight, description };\n}\nfunction spare(id: string, weight: number, description: string): SignalSpec {\n return { id, source: 'static', direction: 'spare', weight: -Math.abs(weight), description };\n}\n\nconst SIGNAL_LIST: SignalSpec[] = [\n // Base signals — one per category; they carry the category's base score so\n // the JSON output is fully self-describing (score is just Σ evidence.weight).\n kill('static:unreachable-file', 60, 'File is not reachable from any entry point'),\n kill('static:unreferenced-export', 65, 'Exported symbol is never imported anywhere in the repo'),\n kill('static:unused-dependency', 70, 'Declared dependency is never imported'),\n kill('static:route-registered', 35, 'Route is registered; static analysis cannot observe calls'),\n\n // Kill signals (raise confidence).\n kill('static:deprecated-jsdoc', 15, 'Marked @deprecated'),\n kill('static:removal-comment', 10, 'A nearby comment asks for removal'),\n kill('static:test-only-reference', 10, 'Only reachable from test files'),\n kill('static:no-client-path-match', 10, 'No string literal in the repo matches the route path'),\n kill('static:controller-not-in-module', 45, 'Controller is not registered in any @Module'),\n kill(\n 'static:route-file-unreachable',\n 45,\n 'The file registering this route is itself unreachable, so the route is never mounted',\n ),\n\n // Spare signals (hidden callers — lower confidence, never silently drop).\n spare(\n 'static:dynamic-import-in-dir',\n 25,\n 'A dynamic import/require may load files in this directory',\n ),\n spare(\n 'static:dynamic-import-exact-dir',\n 40,\n 'A dynamic import/require targets exactly this directory',\n ),\n spare('static:string-dispatch', 20, 'Symbol appears in a string-keyed dispatch table'),\n spare('static:script-reference', 60, 'Referenced by a package.json script'),\n spare('static:config-reference', 60, 'Referenced by a build/deploy config'),\n spare('static:manifest-reference', 60, 'Referenced by a caller manifest (cron/CI/k8s)'),\n spare('static:job-registration', 50, 'File registers scheduled jobs or queue workers'),\n spare(\n 'static:namespace-import-ambiguity',\n 15,\n 'Imported via namespace whose usage could not be fully traced',\n ),\n spare('static:cjs-dynamic-pattern', 20, 'File assigns computed CommonJS exports'),\n spare(\n 'static:client-path-match',\n 30,\n 'A string literal elsewhere in the repo matches the route path',\n ),\n spare('static:dynamic-route-prefix', 15, 'Route prefix could not be resolved statically'),\n spare(\n 'static:types-package-pairing',\n 60,\n '@types package pairs with a runtime package that is in use',\n ),\n spare(\n 'static:public-api-reexport',\n 30,\n 'Re-exported by a package entry point; external consumers are invisible to static analysis',\n ),\n\n // Reserved for the paid evidence layer — registered now so the scorer and\n // JSON contract already understand them.\n {\n id: 'prod:zero-requests-90d',\n source: 'production',\n direction: 'kill',\n weight: 35,\n description: 'No production requests observed in 90 days',\n },\n {\n id: 'prod:request-seen',\n source: 'production',\n direction: 'spare',\n weight: -100,\n description: 'Production traffic observed',\n },\n];\n\nexport const SIGNALS: ReadonlyMap<string, SignalSpec> = new Map(SIGNAL_LIST.map((s) => [s.id, s]));\n\n/** Base signal per category — the first evidence entry every finding carries. */\nexport const BASE_SIGNALS: Record<FindingCategory, string> = {\n 'unreachable-file': 'static:unreachable-file',\n 'unused-export': 'static:unreferenced-export',\n 'unused-dependency': 'static:unused-dependency',\n 'dead-route': 'static:route-registered',\n};\n\n/**\n * Static-only findings are hard-capped: without runtime evidence we refuse to\n * claim near-certainty. Routes cap lower because registration alone proves\n * very little. This cap is a product decision (the upsell) — do not remove.\n */\nexport const STATIC_CAPS: Record<FindingCategory, number> = {\n 'dead-route': 70,\n 'unused-export': 85,\n 'unused-dependency': 85,\n 'unreachable-file': 85,\n};\n\nexport const STATIC_CAP_REASON = 'no runtime evidence — connect telemetry to confirm';\n\n/** Build an Evidence entry from the registry. Throws on unknown ids to catch typos in tests. */\nexport function evidenceFor(signalId: string, detail: string, location?: SourceLocation): Evidence {\n const spec = SIGNALS.get(signalId);\n if (!spec) {\n throw new Error(`Unknown signal id: ${signalId}`);\n }\n return {\n signal: spec.id,\n source: spec.source,\n direction: spec.direction,\n weight: spec.weight,\n detail,\n ...(location ? { location } : {}),\n };\n}\n","/**\n * The core data model. This is the SaaS seam: the paid product appends\n * production/tombstone Evidence entries to these same objects, so breaking\n * changes here require a schemaVersion bump and very good reasons.\n */\n\nexport type FindingCategory =\n | 'dead-route'\n | 'unused-export'\n | 'unused-dependency'\n | 'unreachable-file';\n\n/** 'production' and 'tombstone' are reserved for the paid evidence layer. */\nexport type EvidenceSource = 'static' | 'production' | 'tombstone';\n\n/** kill = supports deadness (raises confidence); spare = hints at a hidden caller (lowers it). */\nexport type EvidenceDirection = 'kill' | 'spare';\n\nexport interface SourceLocation {\n /** Repo-relative, posix-normalized. */\n file: string;\n /** 1-based. */\n line: number;\n column?: number;\n}\n\nexport interface Evidence {\n /** Namespaced signal id from the registry, e.g. 'static:dynamic-import-in-dir'. */\n signal: string;\n source: EvidenceSource;\n direction: EvidenceDirection;\n /** Signed contribution: kill positive, spare negative. Score = clamp(0, cap, Σ weights). */\n weight: number;\n /** Human sentence explaining what was observed. */\n detail: string;\n /** Where the evidence was observed (not necessarily the finding target). */\n location?: SourceLocation;\n}\n\nexport type ConfidenceLevel = 'high' | 'medium' | 'low';\n\nexport interface ConfidenceScore {\n /** 0–100, already clamped to any active cap. */\n score: number;\n level: ConfidenceLevel;\n /** Present when the static-only cap actually bound the score — the upsell marker. */\n capped?: { at: number; reason: string };\n}\n\nexport type RouteFramework = 'express' | 'fastify' | 'nest' | 'next';\n\nexport type FindingTarget =\n | { kind: 'route'; method: string; path: string; framework: RouteFramework }\n | { kind: 'export'; symbol: string; file: string }\n | { kind: 'dependency'; name: string; depType: 'dependencies' | 'devDependencies' }\n | { kind: 'file'; file: string };\n\nexport interface Finding {\n /**\n * Stable identity across scans (tombstone tracking). Derived from category +\n * canonical target + workspace, deliberately NOT from the source location —\n * line drift between scans must not change identity.\n */\n id: string;\n category: FindingCategory;\n target: FindingTarget;\n location: SourceLocation;\n /** Owning workspace package name, or '.' for the repo root package. */\n workspace: string;\n evidence: Evidence[];\n confidence: ConfidenceScore;\n}\n\nexport interface CategoryStat {\n total: number;\n flagged: number;\n}\n\nexport interface ScanStats {\n filesScanned: number;\n durationMs: number;\n routes: CategoryStat;\n exports: CategoryStat;\n dependencies: CategoryStat;\n files: CategoryStat;\n}\n\nexport interface ScanResult {\n /** Contract version for the --json output and SaaS ingestion. */\n schemaVersion: 1;\n tool: { name: string; version: string };\n scannedAt: string;\n /** Absolute posix path of the scanned root. */\n root: string;\n workspaces: string[];\n findings: Finding[];\n stats: ScanStats;\n /** Degraded-analysis notes (bad tsconfig, unparseable files/manifests, …). */\n warnings: string[];\n}\n\n/** Canonical string for a target, used for stable finding ids. */\nexport function targetKey(target: FindingTarget): string {\n switch (target.kind) {\n case 'route':\n return `route:${target.framework}:${target.method} ${target.path}`;\n case 'export':\n return `export:${target.file}#${target.symbol}`;\n case 'dependency':\n return `dependency:${target.depType}:${target.name}`;\n case 'file':\n return `file:${target.file}`;\n }\n}\n\nexport function describeTarget(target: FindingTarget): string {\n switch (target.kind) {\n case 'route':\n return `${target.method} ${target.path}`;\n case 'export':\n return `export '${target.symbol}' in ${target.file}`;\n case 'dependency':\n return `${target.name} (${target.depType})`;\n case 'file':\n return target.file;\n }\n}\n","import { createHash } from 'node:crypto';\n\n/** Short stable hash used for finding ids (tombstone identity across scans). */\nexport function stableId(...parts: string[]): string {\n return createHash('sha256').update(parts.join('|')).digest('hex').slice(0, 12);\n}\n","import type { Finding, FindingCategory, FindingTarget, SourceLocation } from '../model/finding.js';\nimport { targetKey } from '../model/finding.js';\nimport { BASE_SIGNALS, evidenceFor } from '../model/signals.js';\nimport { stableId } from '../util/hash.js';\nimport type { ModuleGraph } from '../graph/moduleGraph.js';\nimport type { EntryPoint } from '../workspace/entrypoints.js';\nimport type { ScanUnit } from '../workspace/workspaces.js';\nimport type { ManifestCaller } from '../manifest/types.js';\n\nexport interface Reachability {\n /** Reachable from every entry point, tests included. */\n all: ReadonlySet<string>;\n /** Reachable excluding test-tagged entries. */\n prod: ReadonlySet<string>;\n}\n\nexport interface ResolvedScanOptions {\n categories: ReadonlySet<FindingCategory>;\n /** Force-enabled route frameworks (--framework), bypassing detect(). */\n frameworks: ReadonlySet<string>;\n}\n\nexport interface ScanContext {\n /** Absolute posix scan root. */\n root: string;\n units: ScanUnit[];\n /** The unit this detector invocation analyzes. */\n unit: ScanUnit;\n graph: ModuleGraph;\n /** All entry points across units (reachability is global). */\n entryPoints: EntryPoint[];\n /** Entry points belonging to the current unit. */\n unitEntryPoints: EntryPoint[];\n manifestCallers: ManifestCaller[];\n reach: Reachability;\n options: ResolvedScanOptions;\n warnings: string[];\n /** Absolute posix → repo-relative posix. */\n rel(file: string): string;\n /** Files of the module graph owned by the current unit. */\n unitFiles(): string[];\n}\n\nexport interface DetectorResult {\n findings: Finding[];\n /** Detector-known population counts feeding the shock-stat denominators. */\n counted?: { routes?: number };\n}\n\nexport interface Detector {\n name: string;\n /** Dependency-signature gate, e.g. `'express' in deps`. */\n detect(unit: ScanUnit): boolean;\n extract(ctx: ScanContext): DetectorResult;\n}\n\n/**\n * Construct a finding with its category base evidence. Confidence is computed\n * by the pipeline after evidence providers run — placeholder until then.\n */\nexport function makeFinding(\n category: FindingCategory,\n target: FindingTarget,\n location: SourceLocation,\n workspace: string,\n baseDetail: string,\n): Finding {\n return {\n id: stableId(targetKey(target), workspace),\n category,\n target,\n location,\n workspace,\n evidence: [evidenceFor(BASE_SIGNALS[category], baseDetail)],\n confidence: { score: 0, level: 'low' },\n };\n}\n","import { evidenceFor } from '../model/signals.js';\nimport type { Detector, ScanContext, DetectorResult } from './types.js';\nimport { makeFinding } from './types.js';\n\nexport const unreachableFiles: Detector = {\n name: 'unreachable-files',\n detect: () => true,\n\n extract(ctx: ScanContext): DetectorResult {\n const findings = [];\n const entryFiles = new Set(ctx.entryPoints.map((e) => e.file));\n const entryCount = ctx.entryPoints.filter((e) => e.tag !== 'test').length;\n\n for (const file of ctx.unitFiles()) {\n if (entryFiles.has(file)) continue;\n const rel = ctx.rel(file);\n\n if (!ctx.reach.all.has(file)) {\n findings.push(\n makeFinding(\n 'unreachable-file',\n { kind: 'file', file: rel },\n { file: rel, line: 1 },\n ctx.unit.name,\n `Not imported (directly or transitively) by any of ${entryCount} entry points`,\n ),\n );\n } else if (!ctx.reach.prod.has(file)) {\n // Alive only because tests import it — dead in production terms.\n const finding = makeFinding(\n 'unreachable-file',\n { kind: 'file', file: rel },\n { file: rel, line: 1 },\n ctx.unit.name,\n 'Only reachable through test files; no production entry point imports it',\n );\n finding.evidence.push(\n evidenceFor('static:test-only-reference', 'Reachable exclusively via test entry points'),\n );\n findings.push(finding);\n }\n }\n\n return { findings };\n },\n};\n","import { evidenceFor } from '../model/signals.js';\nimport { isTestFile } from '../workspace/entrypoints.js';\nimport type { Detector, ScanContext, DetectorResult } from './types.js';\nimport { makeFinding } from './types.js';\n\nexport const unusedExports: Detector = {\n name: 'unused-exports',\n detect: () => true,\n\n extract(ctx: ScanContext): DetectorResult {\n const findings = [];\n const entryFiles = new Set(ctx.entryPoints.map((e) => e.file));\n const publicEntryFiles = new Set(\n ctx.entryPoints.filter((e) => e.tag !== 'test').map((e) => e.file),\n );\n\n for (const file of ctx.unitFiles()) {\n // Entry files' exports are public API; unreachable files are already\n // flagged whole — re-flagging each export would be noise.\n if (entryFiles.has(file)) continue;\n if (!ctx.reach.all.has(file)) continue;\n const rel = ctx.rel(file);\n if (isTestFile(rel)) continue;\n\n const pf = ctx.graph.files.get(file)!;\n const seenNames = new Set<string>();\n for (const exp of pf.exports) {\n if (seenNames.has(exp.name)) continue;\n seenNames.add(exp.name);\n if (ctx.graph.isExportUsed(file, exp.name)) continue;\n\n const finding = makeFinding(\n 'unused-export',\n { kind: 'export', symbol: exp.name, file: rel },\n { file: rel, line: exp.line },\n ctx.unit.name,\n exp.kind === 'type'\n ? `Type export '${exp.name}' is never imported`\n : `'${exp.name}' is exported but never imported anywhere in the repo`,\n );\n if (exp.deprecated) {\n finding.evidence.push(\n evidenceFor('static:deprecated-jsdoc', `'${exp.name}' is marked @deprecated`),\n );\n }\n // Re-exported through a package entry barrel → it's public API, and\n // external consumers are invisible here. Keep the finding, lower it.\n if (ctx.graph.isReexportedThrough(file, exp.name, publicEntryFiles)) {\n finding.evidence.push(\n evidenceFor(\n 'static:public-api-reexport',\n `'${exp.name}' is part of the package's public API via an entry-point re-export`,\n ),\n );\n }\n if (pf.hasCjsDynamicExport) {\n // module.exports[computed] means this module's export surface is not\n // fully knowable — honesty requires lowering confidence, not hiding it.\n finding.evidence.push(\n evidenceFor(\n 'static:cjs-dynamic-pattern',\n 'File assigns computed CommonJS exports; the export set is not fully static',\n ),\n );\n }\n findings.push(finding);\n }\n }\n\n return { findings };\n },\n};\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { isUnder } from '../util/paths.js';\nimport { evidenceFor } from '../model/signals.js';\nimport { packageNameOf } from '../graph/resolver.js';\nimport type { Detector, ScanContext, DetectorResult } from './types.js';\nimport { makeFinding } from './types.js';\n\nexport const unusedDeps: Detector = {\n name: 'unused-dependencies',\n detect: (unit) =>\n Object.keys(unit.packageJson.dependencies ?? {}).length > 0 ||\n Object.keys(unit.packageJson.devDependencies ?? {}).length > 0,\n\n extract(ctx: ScanContext): DetectorResult {\n const findings = [];\n const used = usedPackages(ctx);\n const pkgJsonRel = ctx.rel(`${ctx.unit.dir}/package.json`);\n const lineIndex = packageJsonLines(ctx.unit.dir);\n\n for (const depType of ['dependencies', 'devDependencies'] as const) {\n for (const name of Object.keys(ctx.unit.packageJson[depType] ?? {})) {\n if (used.has(name)) continue;\n\n const finding = makeFinding(\n 'unused-dependency',\n { kind: 'dependency', name, depType },\n { file: pkgJsonRel, line: lineIndex.get(name) ?? 1 },\n ctx.unit.name,\n `'${name}' is declared in ${depType} but never imported`,\n );\n\n // @types/* paired with a used runtime package (or with TS itself for\n // @types/node) is almost certainly in use by the compiler — surfaced\n // as spare evidence rather than silently excluded.\n if (name.startsWith('@types/')) {\n const runtime = runtimePackageFor(name);\n if (runtime === 'node' || used.has(runtime)) {\n finding.evidence.push(\n evidenceFor(\n 'static:types-package-pairing',\n `Type definitions for '${runtime}', which is in use`,\n ),\n );\n }\n }\n findings.push(finding);\n }\n }\n\n return { findings };\n },\n};\n\n/** Every npm package imported by files owned by this unit. */\nfunction usedPackages(ctx: ScanContext): Set<string> {\n const used = new Set<string>();\n for (const file of ctx.graph.files.keys()) {\n if (!isUnder(ctx.unit.dir, file)) continue;\n const pf = ctx.graph.files.get(file)!;\n for (const imp of pf.imports) {\n if (imp.resolvedPackage) {\n used.add(imp.resolvedPackage);\n } else if (!imp.specifier.startsWith('.') && !imp.specifier.startsWith('node:')) {\n // A bare specifier names a dependency even when resolution routed it\n // to in-repo sources (workspace packages resolve to sibling files).\n used.add(packageNameOf(imp.specifier));\n }\n }\n }\n return used;\n}\n\n/** '@types/scope__name' → '@scope/name'; '@types/foo' → 'foo'. */\nfunction runtimePackageFor(typesPackage: string): string {\n const base = typesPackage.slice('@types/'.length);\n return base.includes('__') ? `@${base.replace('__', '/')}` : base;\n}\n\n/** Map dependency name → line number in package.json, for clickable locations. */\nfunction packageJsonLines(unitDir: string): Map<string, number> {\n const lines = new Map<string, number>();\n try {\n const text = fs.readFileSync(path.join(unitDir, 'package.json'), 'utf8');\n text.split(/\\r?\\n/).forEach((line, i) => {\n const m = /^\\s*\"((?:@[\\w.-]+\\/)?[\\w.-]+)\"\\s*:/.exec(line);\n if (m && !lines.has(m[1]!)) lines.set(m[1]!, i + 1);\n });\n } catch {\n // location degrades to line 1 — not worth a warning\n }\n return lines;\n}\n","/**\n Express + Fastify route detection (one detector — same call-shape family).\n \n A registration is a method call (get/post/…) on a \"route receiver\" with a\n string-literal path and at least one handler-ish argument. Receivers are\n identifiers traced to express()/Router()/fastify() initializers, plus the\n conventional names (app/router/server/api/fastify) — the handler-argument\n requirement is what keeps axios-style clients (api.get('/x') with no\n callback) from being misread as routes.\n */\nimport ts from 'typescript';\nimport type { Finding } from '../../model/finding.js';\nimport { evidenceFor } from '../../model/signals.js';\nimport type { ParsedFile } from '../../graph/parser.js';\nimport { isTestFile } from '../../workspace/entrypoints.js';\nimport type { Detector, ScanContext, DetectorResult } from '../types.js';\nimport { makeFinding } from '../types.js';\n\nconst HTTP_METHODS = new Set(['get', 'post', 'put', 'patch', 'delete', 'all', 'head', 'options']);\nconst CONVENTIONAL_RECEIVERS = new Set(['app', 'router', 'server', 'api', 'fastify']);\nconst RECEIVER_FACTORIES = new Set(['express', 'fastify', 'Fastify', 'Router']);\n\n/**\n Minimum count of URL-ish string literals outside route files before the\n absence of a match is treated as kill evidence. Below this the repo simply\n doesn't reference paths in strings (API-only service) and absence proves\n nothing — claiming otherwise would make the shock stat dishonest.\n */\nconst CLIENT_LITERAL_THRESHOLD = 3;\n\ninterface RouteReg {\n method: string;\n path: string;\n receiver: string;\n line: number;\n file: string; // absolute posix\n}\n\ninterface Mount {\n prefix: string; // '' when mounted without a path, '<dynamic>' when unresolvable\n localName: string;\n file: string;\n}\n\nexport const expressRoutes: Detector = {\n name: 'express-routes',\n detect: (unit) => {\n const deps = { ...unit.packageJson.dependencies, ...unit.packageJson.devDependencies };\n return Boolean(deps['express'] || deps['fastify']);\n },\n\n extract(ctx: ScanContext): DetectorResult {\n const registrations: RouteReg[] = [];\n const mounts: Mount[] = [];\n\n for (const file of ctx.unitFiles()) {\n if (isTestFile(ctx.rel(file))) continue;\n const pf = ctx.graph.files.get(file)!;\n collectFromFile(pf, registrations, mounts);\n }\n\n // Mount prefixes: same-file (receiver name) and cross-file (imported router).\n const prefixByFileReceiver = new Map<string, string>();\n const prefixByFile = new Map<string, string>();\n for (const mount of mounts) {\n const pf = ctx.graph.files.get(mount.file)!;\n const imported = pf.imports.find(\n (i) =>\n i.resolvedFile &&\n (i.names.some((n) => n.local === mount.localName) ||\n i.namespaceLocal === mount.localName),\n );\n if (imported?.resolvedFile) {\n if (!prefixByFile.has(imported.resolvedFile)) {\n prefixByFile.set(imported.resolvedFile, mount.prefix);\n }\n } else if (!prefixByFileReceiver.has(`${mount.file}#${mount.localName}`)) {\n prefixByFileReceiver.set(`${mount.file}#${mount.localName}`, mount.prefix);\n }\n }\n\n // Client path-literal index: URL-ish strings outside route-defining files.\n const routeFiles = new Set(registrations.map((r) => r.file));\n const clientLiterals: { value: string; file: string }[] = [];\n for (const [file, pf] of ctx.graph.files) {\n if (routeFiles.has(file)) continue;\n for (const lit of pf.pathLiterals) clientLiterals.push({ value: lit.value, file });\n }\n const literalsMeaningful = clientLiterals.length >= CLIENT_LITERAL_THRESHOLD;\n\n const findings: Finding[] = [];\n const seen = new Set<string>();\n const framework = frameworkOf(ctx);\n\n for (const reg of registrations) {\n const prefix =\n prefixByFileReceiver.get(`${reg.file}#${reg.receiver}`) ?? prefixByFile.get(reg.file) ?? '';\n const fullPath = joinRoutePath(prefix, reg.path);\n const method = reg.method.toUpperCase();\n const key = `${method} ${fullPath} ${reg.file}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n const rel = ctx.rel(reg.file);\n const finding = makeFinding(\n 'dead-route',\n { kind: 'route', method, path: fullPath, framework },\n { file: rel, line: reg.line },\n ctx.unit.name,\n `${method} ${fullPath} is registered here; static analysis cannot observe whether it is called`,\n );\n\n if (prefix === '<dynamic>') {\n finding.evidence.push(\n evidenceFor(\n 'static:dynamic-route-prefix',\n 'Mounted under a prefix that is not a string literal',\n ),\n );\n }\n\n if (!ctx.reach.all.has(reg.file)) {\n // The registering file never runs — the route provably is never mounted.\n finding.evidence.push(\n evidenceFor(\n 'static:route-file-unreachable',\n `${rel} is not reachable from any entry point`,\n ),\n );\n } else if (literalsMeaningful && !fullPath.startsWith('<dynamic>')) {\n const match = findPathMatch(fullPath, clientLiterals);\n if (match) {\n finding.evidence.push(\n evidenceFor(\n 'static:client-path-match',\n `'${match.value}' in ${ctx.rel(match.file)} matches this route`,\n ),\n );\n } else {\n finding.evidence.push(\n evidenceFor(\n 'static:no-client-path-match',\n `None of ${clientLiterals.length} URL-like strings in the repo match this route`,\n ),\n );\n }\n }\n\n findings.push(finding);\n }\n\n return { findings, counted: { routes: seen.size } };\n },\n};\n\nfunction frameworkOf(ctx: ScanContext): 'express' | 'fastify' {\n const deps = { ...ctx.unit.packageJson.dependencies, ...ctx.unit.packageJson.devDependencies };\n return deps['fastify'] && !deps['express'] ? 'fastify' : 'express';\n}\n\nfunction collectFromFile(pf: ParsedFile, registrations: RouteReg[], mounts: Mount[]): void {\n // Pass 1: receivers created in this file (const app = express(), const r = Router(), …).\n const receivers = new Set<string>(CONVENTIONAL_RECEIVERS);\n const seed = (node: ts.Node): void => {\n if (\n ts.isVariableDeclaration(node) &&\n ts.isIdentifier(node.name) &&\n node.initializer &&\n ts.isCallExpression(node.initializer)\n ) {\n const callee = node.initializer.expression;\n const isFactory =\n (ts.isIdentifier(callee) && RECEIVER_FACTORIES.has(callee.text)) ||\n (ts.isPropertyAccessExpression(callee) && callee.name.text === 'Router');\n if (isFactory) receivers.add(node.name.text);\n }\n ts.forEachChild(node, seed);\n };\n ts.forEachChild(pf.ast, seed);\n\n const lineOf = (node: ts.Node): number =>\n pf.ast.getLineAndCharacterOfPosition(node.getStart(pf.ast)).line + 1;\n\n const visit = (node: ts.Node): void => {\n if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {\n const methodName = node.expression.name.text;\n const base = node.expression.expression;\n\n // app.get('/path', handler) — also matches X.route('/p').get(handler)\n // because the base of `.get` is then the route(...) call expression.\n if (HTTP_METHODS.has(methodName)) {\n const viaRoute = routeCallPath(base);\n if (viaRoute) {\n if (viaRoute.receiver && receivers.has(viaRoute.receiver)) {\n registrations.push({\n method: methodName,\n path: viaRoute.path,\n receiver: viaRoute.receiver,\n line: lineOf(node),\n file: pf.file,\n });\n }\n } else if (ts.isIdentifier(base) && receivers.has(base.text)) {\n const arg0 = node.arguments[0];\n if (\n arg0 &&\n (ts.isStringLiteral(arg0) || ts.isNoSubstitutionTemplateLiteral(arg0)) &&\n node.arguments.length >= 2 &&\n node.arguments.slice(1).some(isHandlerish)\n ) {\n registrations.push({\n method: methodName,\n path: arg0.text,\n receiver: base.text,\n line: lineOf(node),\n file: pf.file,\n });\n }\n }\n }\n\n // fastify.route({ method: 'GET', url: '/path', handler })\n if (methodName === 'route' && ts.isIdentifier(base) && receivers.has(base.text)) {\n const arg0 = node.arguments[0];\n if (arg0 && ts.isObjectLiteralExpression(arg0)) {\n const get = (prop: string): string | undefined => {\n for (const p of arg0.properties) {\n if (\n ts.isPropertyAssignment(p) &&\n ts.isIdentifier(p.name) &&\n p.name.text === prop &&\n (ts.isStringLiteral(p.initializer) ||\n ts.isNoSubstitutionTemplateLiteral(p.initializer))\n ) {\n return p.initializer.text;\n }\n }\n return undefined;\n };\n const url = get('url') ?? get('path');\n const method = get('method');\n if (url && method) {\n registrations.push({\n method: method.toLowerCase(),\n path: url,\n receiver: base.text,\n line: lineOf(node),\n file: pf.file,\n });\n }\n }\n }\n\n // app.use('/prefix', router) | app.use(router) | fastify.register(plugin, { prefix })\n if (\n (methodName === 'use' || methodName === 'register') &&\n ts.isIdentifier(base) &&\n receivers.has(base.text) &&\n node.arguments.length >= 1\n ) {\n collectMount(node, methodName, pf.file, mounts);\n }\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(pf.ast, visit);\n}\n\n/** X.route('/p') base of a chained .get(...) — returns the receiver + path. */\nfunction routeCallPath(base: ts.Expression): { receiver?: string; path: string } | undefined {\n if (\n ts.isCallExpression(base) &&\n ts.isPropertyAccessExpression(base.expression) &&\n base.expression.name.text === 'route' &&\n base.arguments.length >= 1\n ) {\n const arg = base.arguments[0]!;\n if (ts.isStringLiteral(arg) || ts.isNoSubstitutionTemplateLiteral(arg)) {\n const receiverExpr = base.expression.expression;\n return {\n path: arg.text,\n ...(ts.isIdentifier(receiverExpr) ? { receiver: receiverExpr.text } : {}),\n };\n }\n }\n return undefined;\n}\n\nfunction collectMount(\n node: ts.CallExpression,\n methodName: string,\n file: string,\n mounts: Mount[],\n): void {\n const args = node.arguments;\n if (methodName === 'register') {\n // fastify.register(plugin, { prefix: '/p' })\n if (args[0] && ts.isIdentifier(args[0])) {\n let prefix = '';\n const opts = args[1];\n if (opts && ts.isObjectLiteralExpression(opts)) {\n for (const p of opts.properties) {\n if (ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === 'prefix') {\n prefix = ts.isStringLiteral(p.initializer) ? p.initializer.text : '<dynamic>';\n }\n }\n }\n mounts.push({ prefix, localName: args[0].text, file });\n }\n return;\n }\n // app.use(...)\n const first = args[0]!;\n if (ts.isStringLiteral(first) || ts.isNoSubstitutionTemplateLiteral(first)) {\n for (const arg of args.slice(1)) {\n if (ts.isIdentifier(arg)) mounts.push({ prefix: first.text, localName: arg.text, file });\n }\n } else if (ts.isIdentifier(first)) {\n mounts.push({ prefix: '', localName: first.text, file });\n } else if (args.length >= 2) {\n for (const arg of args.slice(1)) {\n if (ts.isIdentifier(arg)) mounts.push({ prefix: '<dynamic>', localName: arg.text, file });\n }\n }\n}\n\n/** Handler-ish: anything that could be middleware/handler — excludes plain data literals. */\nfunction isHandlerish(arg: ts.Expression): boolean {\n return !(\n ts.isObjectLiteralExpression(arg) ||\n ts.isStringLiteral(arg) ||\n ts.isNoSubstitutionTemplateLiteral(arg) ||\n ts.isNumericLiteral(arg) ||\n arg.kind === ts.SyntaxKind.TrueKeyword ||\n arg.kind === ts.SyntaxKind.FalseKeyword\n );\n}\n\nfunction joinRoutePath(prefix: string, p: string): string {\n if (!prefix) return p || '/';\n const joined = `${prefix}/${p}`.replace(/\\/{2,}/g, '/');\n return joined.length > 1 ? joined.replace(/\\/$/, '') : joined;\n}\n\n/**\n * Does any URL-ish literal match this route? Param segments (:id) match any\n * literal that shares the static prefix.\n */\nfunction findPathMatch(\n routePath: string,\n literals: { value: string; file: string }[],\n): { value: string; file: string } | undefined {\n const paramIdx = routePath.search(/[:*]/);\n if (paramIdx === -1) {\n return literals.find((l) => l.value === routePath || l.value.startsWith(routePath + '?'));\n }\n const prefix = routePath.slice(0, paramIdx);\n return literals.find((l) => l.value.startsWith(prefix) && l.value.length > prefix.length);\n}\n","/**\n * NestJS route detection.\n *\n * Nest is the one framework where static analysis can *prove* a route is dead:\n * a `@Controller()` class only mounts its routes if it is listed in some\n * `@Module({ controllers: [...] })`. A controller that no module registers is\n * never instantiated and its routes never exist at runtime — that is a fact\n * about how Nest boots, not a heuristic, which is why the\n * `static:controller-not-in-module` signal carries a heavy +45 weight.\n *\n * Routes belonging to a *registered* controller emit base evidence only and are\n * pruned by the pipeline as inventory (same as Express) — registration alone\n * doesn't prove a route is called.\n */\nimport ts from 'typescript';\nimport type { Finding, RouteFramework } from '../../model/finding.js';\nimport { evidenceFor } from '../../model/signals.js';\nimport type { ParsedFile } from '../../graph/parser.js';\nimport { isTestFile } from '../../workspace/entrypoints.js';\nimport type { Detector, ScanContext, DetectorResult } from '../types.js';\nimport { makeFinding } from '../types.js';\n\nconst FRAMEWORK: RouteFramework = 'nest';\n\n/** Method decorator → HTTP verb. @All maps to ALL (matches Express semantics). */\nconst METHOD_DECORATORS: Record<string, string> = {\n Get: 'GET',\n Post: 'POST',\n Put: 'PUT',\n Patch: 'PATCH',\n Delete: 'DELETE',\n Options: 'OPTIONS',\n Head: 'HEAD',\n All: 'ALL',\n};\n\ninterface ControllerRoute {\n method: string;\n path: string;\n line: number;\n}\n\ninterface ControllerClass {\n name: string;\n prefix: string; // '' | '<dynamic>' | literal\n routes: ControllerRoute[];\n file: string; // absolute posix\n line: number;\n}\n\nexport const nestRoutes: Detector = {\n name: 'nest-routes',\n detect: (unit) => {\n const deps = { ...unit.packageJson.dependencies, ...unit.packageJson.devDependencies };\n return Boolean(deps['@nestjs/core'] || deps['@nestjs/common']);\n },\n\n extract(ctx: ScanContext): DetectorResult {\n const controllers: ControllerClass[] = [];\n // Class name → set of files whose @Module references it in `controllers`.\n const registeredIn = new Map<string, Set<string>>();\n\n for (const file of ctx.unitFiles()) {\n if (isTestFile(ctx.rel(file))) continue;\n const pf = ctx.graph.files.get(file)!;\n collectControllers(pf, controllers);\n collectModuleControllers(pf, registeredIn);\n }\n\n const findings: Finding[] = [];\n const seen = new Set<string>();\n let routeCount = 0;\n\n for (const ctrl of controllers) {\n // A controller counts as registered when *some* module lists it AND that\n // module file can reach the controller's definition through an import\n // edge (or is the same file). This avoids matching an unrelated class of\n // the same name in another package.\n const registered = isRegistered(ctx, ctrl, registeredIn.get(ctrl.name));\n\n for (const route of ctrl.routes) {\n const fullPath = joinRoutePath(ctrl.prefix, route.path);\n routeCount++;\n const key = `${route.method} ${fullPath} ${ctrl.file}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n const rel = ctx.rel(ctrl.file);\n const finding = makeFinding(\n 'dead-route',\n { kind: 'route', method: route.method, path: fullPath, framework: FRAMEWORK },\n { file: rel, line: route.line },\n ctx.unit.name,\n `${route.method} ${fullPath} is declared on @Controller ${ctrl.name}; static analysis cannot observe whether it is called`,\n );\n\n if (!registered) {\n finding.evidence.push(\n evidenceFor(\n 'static:controller-not-in-module',\n `@Controller ${ctrl.name} is not listed in any @Module({ controllers }), so Nest never mounts it`,\n { file: rel, line: ctrl.line },\n ),\n );\n }\n\n if (ctrl.prefix === '<dynamic>') {\n finding.evidence.push(\n evidenceFor(\n 'static:dynamic-route-prefix',\n `@Controller ${ctrl.name} prefix is not a string literal`,\n ),\n );\n }\n\n findings.push(finding);\n }\n }\n\n return { findings, counted: { routes: routeCount } };\n },\n};\n\n/** Whether a module that registers `ctrl.name` can actually see this controller. */\nfunction isRegistered(\n ctx: ScanContext,\n ctrl: ControllerClass,\n moduleFiles: Set<string> | undefined,\n): boolean {\n if (!moduleFiles || moduleFiles.size === 0) return false;\n for (const moduleFile of moduleFiles) {\n if (moduleFile === ctrl.file) return true; // controller + module co-located\n const pf = ctx.graph.files.get(moduleFile);\n if (pf?.imports.some((imp) => imp.resolvedFile === ctrl.file)) return true;\n }\n return false;\n}\n\nfunction collectControllers(pf: ParsedFile, out: ControllerClass[]): void {\n const lineOf = (node: ts.Node): number =>\n pf.ast.getLineAndCharacterOfPosition(node.getStart(pf.ast)).line + 1;\n\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node) && node.name) {\n const decorators = ts.getDecorators?.(node) ?? [];\n const controllerDec = decorators.find((d) => decoratorName(d) === 'Controller');\n if (controllerDec) {\n const prefix = controllerPrefix(controllerDec);\n const routes: ControllerRoute[] = [];\n for (const member of node.members) {\n if (!ts.isMethodDeclaration(member)) continue;\n for (const dec of ts.getDecorators?.(member) ?? []) {\n const verb = METHOD_DECORATORS[decoratorName(dec) ?? ''];\n if (verb) {\n routes.push({\n method: verb,\n path: decoratorStringArg(dec) ?? '',\n line: lineOf(member),\n });\n }\n }\n }\n if (routes.length > 0) {\n out.push({ name: node.name.text, prefix, routes, file: pf.file, line: lineOf(node) });\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(pf.ast, visit);\n}\n\n/** Record every class name listed in a `@Module({ controllers: [...] })`. */\nfunction collectModuleControllers(pf: ParsedFile, out: Map<string, Set<string>>): void {\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const moduleDec = (ts.getDecorators?.(node) ?? []).find((d) => decoratorName(d) === 'Module');\n if (moduleDec && ts.isCallExpression(moduleDec.expression)) {\n const arg = moduleDec.expression.arguments[0];\n if (arg && ts.isObjectLiteralExpression(arg)) {\n for (const prop of arg.properties) {\n if (\n ts.isPropertyAssignment(prop) &&\n ts.isIdentifier(prop.name) &&\n prop.name.text === 'controllers' &&\n ts.isArrayLiteralExpression(prop.initializer)\n ) {\n for (const el of prop.initializer.elements) {\n if (ts.isIdentifier(el)) {\n let set = out.get(el.text);\n if (!set) out.set(el.text, (set = new Set()));\n set.add(pf.file);\n }\n }\n }\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(pf.ast, visit);\n}\n\nfunction decoratorName(dec: ts.Decorator): string | undefined {\n const expr = ts.isCallExpression(dec.expression) ? dec.expression.expression : dec.expression;\n return ts.isIdentifier(expr) ? expr.text : undefined;\n}\n\n/** First argument of a decorator if it's a string literal. */\nfunction decoratorStringArg(dec: ts.Decorator): string | undefined {\n if (!ts.isCallExpression(dec.expression)) return undefined;\n const arg = dec.expression.arguments[0];\n if (arg && (ts.isStringLiteral(arg) || ts.isNoSubstitutionTemplateLiteral(arg))) return arg.text;\n return undefined;\n}\n\n/** @Controller('cats') | @Controller({ path: 'cats' }) | @Controller() | @Controller */\nfunction controllerPrefix(dec: ts.Decorator): string {\n if (!ts.isCallExpression(dec.expression)) return ''; // bare @Controller\n const arg = dec.expression.arguments[0];\n if (!arg) return '';\n if (ts.isStringLiteral(arg) || ts.isNoSubstitutionTemplateLiteral(arg)) return arg.text;\n if (ts.isObjectLiteralExpression(arg)) {\n for (const prop of arg.properties) {\n if (\n ts.isPropertyAssignment(prop) &&\n ts.isIdentifier(prop.name) &&\n prop.name.text === 'path'\n ) {\n if (\n ts.isStringLiteral(prop.initializer) ||\n ts.isNoSubstitutionTemplateLiteral(prop.initializer)\n ) {\n return prop.initializer.text;\n }\n return '<dynamic>';\n }\n }\n return ''; // object options without a path (e.g. only `version`)\n }\n return '<dynamic>'; // variable / computed prefix\n}\n\nfunction joinRoutePath(prefix: string, p: string): string {\n const a = prefix.replace(/^\\/|\\/$/g, '');\n const b = p.replace(/^\\/|\\/$/g, '');\n const joined = [a, b].filter(Boolean).join('/');\n return '/' + joined;\n}\n","/**\n * Next.js route detection (file-convention based).\n *\n * Next routes have no registration call to inspect — the file's location *is*\n * the route. So static analysis is weaker here than for Nest, and the detector\n * is honest about it: a route is only given kill evidence when no client-side\n * navigation literal (<Link href>, router.push, redirect(), an `href:` value)\n * anywhere in the repo matches it. Below a literal-count threshold, absence\n * proves nothing and no kill evidence is emitted — the same guard the Express\n * detector uses.\n *\n * These files are already entry points (see workspace/entrypoints.ts), so they\n * never appear as unreachable-file findings; this detector only adds the\n * dead-route view.\n */\nimport type { Finding, RouteFramework } from '../../model/finding.js';\nimport { evidenceFor } from '../../model/signals.js';\nimport type { Detector, ScanContext, DetectorResult } from '../types.js';\nimport { makeFinding } from '../types.js';\n\nconst FRAMEWORK: RouteFramework = 'next';\n\n/** Same rationale as the Express detector's threshold — see that file. */\nconst CLIENT_LITERAL_THRESHOLD = 3;\n\n/**\n * Files under pages/ or app/ that are framework lifecycle, not routes:\n * Next special files plus app-router co-located UI files.\n */\nconst NON_ROUTE_BASENAMES = new Set([\n '_app',\n '_document',\n '_error',\n 'layout',\n 'loading',\n 'error',\n 'not-found',\n 'template',\n 'default',\n 'global-error',\n 'instrumentation',\n 'middleware',\n]);\n\ninterface NextRoute {\n routePath: string;\n method: string; // 'GET' for pages, the file's nature for app/route handlers\n file: string; // absolute posix\n}\n\nexport const nextRoutes: Detector = {\n name: 'next-routes',\n detect: (unit) => {\n const deps = { ...unit.packageJson.dependencies, ...unit.packageJson.devDependencies };\n return Boolean(deps['next']);\n },\n\n extract(ctx: ScanContext): DetectorResult {\n const routes: NextRoute[] = [];\n const routeFiles = new Set<string>();\n\n for (const file of ctx.unitFiles()) {\n const rel = relTo(ctx.unit.dir, ctx.rel(file), ctx);\n if (!rel) continue;\n const parsed = routeFromFile(rel);\n if (parsed) {\n routes.push({ ...parsed, file });\n routeFiles.add(file);\n }\n }\n\n // Client navigation literals come from files that are NOT route files\n // themselves (a page linking to itself shouldn't count as a caller).\n const clientLiterals: { value: string; file: string }[] = [];\n for (const [file, pf] of ctx.graph.files) {\n if (routeFiles.has(file)) continue;\n for (const lit of pf.pathLiterals) clientLiterals.push({ value: lit.value, file });\n }\n const literalsMeaningful = clientLiterals.length >= CLIENT_LITERAL_THRESHOLD;\n\n const findings: Finding[] = [];\n const seen = new Set<string>();\n\n for (const route of routes) {\n const key = `${route.method} ${route.routePath}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n const rel = ctx.rel(route.file);\n const finding = makeFinding(\n 'dead-route',\n { kind: 'route', method: route.method, path: route.routePath, framework: FRAMEWORK },\n { file: rel, line: 1 },\n ctx.unit.name,\n `${route.method} ${route.routePath} is a Next.js route file; static analysis cannot observe whether it is visited`,\n );\n\n if (literalsMeaningful && !route.routePath.includes('[')) {\n const match = findPathMatch(route.routePath, clientLiterals);\n if (match) {\n finding.evidence.push(\n evidenceFor(\n 'static:client-path-match',\n `'${match.value}' in ${ctx.rel(match.file)} links to this route`,\n ),\n );\n } else {\n finding.evidence.push(\n evidenceFor(\n 'static:no-client-path-match',\n `No <Link>/router/redirect literal among ${clientLiterals.length} in the repo matches this route`,\n ),\n );\n }\n } else if (route.routePath.includes('[')) {\n // Dynamic segments ([id]) can't be matched against literals reliably.\n finding.evidence.push(\n evidenceFor(\n 'static:dynamic-route-prefix',\n 'Route has dynamic segments; client-link matching is unreliable',\n ),\n );\n }\n\n findings.push(finding);\n }\n\n return { findings, counted: { routes: seen.size } };\n },\n};\n\n/**\n * Map a repo-relative source path to a Next route, or undefined if it isn't a\n * route file. Handles pages/ (Pages Router) and app/ (App Router), with or\n * without a src/ prefix.\n */\nfunction routeFromFile(rel: string): { routePath: string; method: string } | undefined {\n const m = /^(?:src\\/)?(pages|app)\\/(.+)\\.(?:[jt]sx?)$/.exec(rel);\n if (!m) return undefined;\n const router = m[1]!;\n let rest = m[2]!;\n\n const segments = rest.split('/');\n const basename = segments[segments.length - 1]!;\n if (NON_ROUTE_BASENAMES.has(basename)) return undefined;\n\n if (router === 'app') {\n // App Router: only `page` (UI) and `route` (API handler) files are routes.\n if (basename !== 'page' && basename !== 'route') return undefined;\n segments.pop(); // drop the page/route filename; the directory is the path\n const method = basename === 'route' ? 'ALL' : 'GET';\n return { routePath: toRoutePath(segments), method };\n }\n\n // Pages Router: every file is a route; trailing /index collapses.\n if (basename === 'index') segments.pop();\n const isApi = segments[0] === 'api';\n return { routePath: toRoutePath(segments), method: isApi ? 'ALL' : 'GET' };\n}\n\n/** Join path segments into a route, stripping Next route-group dirs `(group)`. */\nfunction toRoutePath(segments: string[]): string {\n const kept = segments.filter((s) => !(s.startsWith('(') && s.endsWith(')')));\n return '/' + kept.join('/');\n}\n\nfunction relTo(unitDir: string, repoRel: string, ctx: ScanContext): string | undefined {\n // ctx.rel gives repo-relative; strip the unit's own prefix so route globs\n // match regardless of how deep the package sits in a monorepo.\n const unitRel = ctx.rel(unitDir);\n if (unitRel === '.' || unitRel === '') return repoRel;\n return repoRel.startsWith(unitRel + '/') ? repoRel.slice(unitRel.length + 1) : undefined;\n}\n\n/** A literal matches when it equals the route or is the route plus a query/hash. */\nfunction findPathMatch(\n routePath: string,\n literals: { value: string; file: string }[],\n): { value: string; file: string } | undefined {\n return literals.find(\n (l) =>\n l.value === routePath ||\n l.value.startsWith(routePath + '?') ||\n l.value.startsWith(routePath + '#') ||\n (routePath !== '/' && l.value.startsWith(routePath + '/')),\n );\n}\n","/**\n * Hidden caller: `require('./handlers/' + name)` style dynamic loading. Any\n * finding living under a dynamically-imported directory might actually be\n * called at runtime — confidence must drop, never silently.\n */\nimport path from 'node:path';\nimport { evidenceFor } from '../model/signals.js';\nimport { dirnamePosix, isUnder, toPosix } from '../util/paths.js';\nimport type { EvidenceProvider, ProviderContext } from './types.js';\nimport { addOnce } from './types.js';\n\ninterface DynamicTarget {\n dir: string; // absolute posix directory the pattern may load from\n sourceFile: string;\n line: number;\n}\n\nexport const dynamicImports: EvidenceProvider = {\n name: 'dynamic-imports',\n\n provide(ctx, findings) {\n const targets: DynamicTarget[] = [];\n for (const [file, pf] of ctx.graph.files) {\n for (const pattern of pf.dynamicPatterns) {\n targets.push({\n dir: dynamicDir(file, pattern.prefix),\n sourceFile: file,\n line: pattern.line,\n });\n }\n }\n if (targets.length === 0) return;\n\n for (const finding of findings) {\n if (finding.category === 'unused-dependency') continue;\n const findingFile = ctx.abs(finding.location.file);\n const findingDir = dirnamePosix(findingFile);\n\n // Apply only the strongest matching pattern.\n const exact = targets.find((t) => t.dir === findingDir);\n const under = exact ?? targets.find((t) => isUnder(t.dir, findingFile));\n if (!under) continue;\n\n addOnce(\n finding,\n evidenceFor(\n exact ? 'static:dynamic-import-exact-dir' : 'static:dynamic-import-in-dir',\n `Dynamic import/require at ${ctx.rel(under.sourceFile)}:${under.line} may load this file at runtime`,\n { file: ctx.rel(under.sourceFile), line: under.line },\n ),\n );\n }\n },\n};\n\n/** Directory a dynamic specifier prefix points at, falling back to the caller's dir. */\nfunction dynamicDir(containingFile: string, prefix: string | undefined): string {\n const baseDir = dirnamePosix(containingFile);\n if (!prefix || !prefix.startsWith('.')) return baseDir;\n const resolved = toPosix(path.resolve(baseDir, prefix));\n // './handlers/' points at the dir itself; './handlers/h-' at a stem inside it.\n return prefix.endsWith('/') ? resolved : dirnamePosix(resolved);\n}\n","import type { Finding } from '../model/finding.js';\nimport type { ModuleGraph } from '../graph/moduleGraph.js';\nimport type { EntryPoint } from '../workspace/entrypoints.js';\nimport type { ScanUnit } from '../workspace/workspaces.js';\nimport type { ManifestCaller } from '../manifest/types.js';\n\nexport interface ProviderContext {\n root: string;\n units: ScanUnit[];\n graph: ModuleGraph;\n manifestCallers: ManifestCaller[];\n entryPoints: EntryPoint[];\n warnings: string[];\n /** Absolute posix → repo-relative posix. */\n rel(file: string): string;\n /** Repo-relative posix → absolute posix. */\n abs(relPath: string): string;\n}\n\n/**\n * Evidence providers append kill/spare evidence to existing findings — they\n * never create or delete findings. The production-evidence layer of the paid\n * product is just another implementation of this interface.\n */\nexport interface EvidenceProvider {\n name: string;\n provide(ctx: ProviderContext, findings: Finding[]): void;\n}\n\n/** Append evidence unless the finding already carries that signal (dedupe). */\nexport function addOnce(finding: Finding, evidence: Finding['evidence'][number]): void {\n if (!finding.evidence.some((e) => e.signal === evidence.signal)) {\n finding.evidence.push(evidence);\n }\n}\n","/**\n * Hidden caller: dispatch tables. An imported symbol sitting in an object\n * literal alongside others is very likely invoked via `table[key]()` — the\n * import edge exists, but if the *export* was flagged through another path\n * (e.g. barrel ambiguity), this lowers its confidence.\n */\nimport ts from 'typescript';\nimport type { Finding } from '../model/finding.js';\nimport { evidenceFor } from '../model/signals.js';\nimport type { EvidenceProvider, ProviderContext } from './types.js';\nimport { addOnce } from './types.js';\n\nexport const stringDispatch: EvidenceProvider = {\n name: 'string-dispatch',\n\n provide(ctx, findings) {\n const bySymbol = indexExportFindings(ctx, findings);\n if (bySymbol.size === 0) return;\n\n for (const [file, pf] of ctx.graph.files) {\n // local identifier → (source file, exported name)\n const importedLocals = new Map<string, { file: string; imported: string }>();\n for (const imp of pf.imports) {\n if (!imp.resolvedFile) continue;\n for (const n of imp.names) {\n importedLocals.set(n.local, { file: imp.resolvedFile, imported: n.imported });\n }\n }\n if (importedLocals.size === 0) continue;\n\n const visit = (node: ts.Node): void => {\n if (ts.isObjectLiteralExpression(node) && node.properties.length >= 2) {\n for (const prop of node.properties) {\n let local: string | undefined;\n if (ts.isShorthandPropertyAssignment(prop)) local = prop.name.text;\n else if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.initializer)) {\n local = prop.initializer.text;\n }\n const ref = local ? importedLocals.get(local) : undefined;\n if (ref) {\n const finding = bySymbol.get(`${ctx.rel(ref.file)}#${ref.imported}`);\n if (finding) {\n addOnce(\n finding,\n evidenceFor(\n 'static:string-dispatch',\n `'${ref.imported}' appears in a dispatch table in ${ctx.rel(file)}`,\n ),\n );\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(pf.ast, visit);\n }\n },\n};\n\nfunction indexExportFindings(ctx: ProviderContext, findings: Finding[]): Map<string, Finding> {\n const index = new Map<string, Finding>();\n for (const f of findings) {\n if (f.category === 'unused-export' && f.target.kind === 'export') {\n index.set(`${f.target.file}#${f.target.symbol}`, f);\n }\n }\n return index;\n}\n","/**\n * Hidden caller: package.json scripts. A dependency that is never imported but\n * whose name (or binary) appears in a script is invoked from the command line —\n * spare evidence, not a silent exclusion, so the user still sees it.\n */\nimport { evidenceFor } from '../model/signals.js';\nimport type { ScanUnit } from '../workspace/workspaces.js';\nimport type { EvidenceProvider } from './types.js';\nimport { addOnce } from './types.js';\n\nexport const packageScripts: EvidenceProvider = {\n name: 'package-scripts',\n\n provide(ctx, findings) {\n for (const finding of findings) {\n if (finding.category !== 'unused-dependency' || finding.target.kind !== 'dependency')\n continue;\n const depName = finding.target.name;\n const unit = ctx.units.find((u) => u.name === finding.workspace) ?? ctx.units[0]!;\n const hit = scriptReferencing(unit, depName) ?? scriptReferencing(ctx.units[0]!, depName);\n if (hit) {\n addOnce(\n finding,\n evidenceFor(\n 'static:script-reference',\n `Referenced by package.json script '${hit.script}': ${truncate(hit.command)}`,\n ),\n );\n }\n }\n },\n};\n\nfunction scriptReferencing(\n unit: ScanUnit,\n depName: string,\n): { script: string; command: string } | undefined {\n // Scoped packages are invoked by their unscoped binary name (`@scope/cli` → `cli`).\n const binName = depName.includes('/') ? depName.split('/').pop()! : depName;\n const re = new RegExp(`(^|[\\\\s\"'=/])${escapeRe(binName)}($|[\\\\s\"'@])`);\n for (const [script, command] of Object.entries(unit.packageJson.scripts ?? {})) {\n if (command.includes(depName) || re.test(command)) return { script, command };\n }\n return undefined;\n}\n\nfunction escapeRe(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction truncate(s: string): string {\n return s.length > 60 ? s.slice(0, 57) + '…' : s;\n}\n","/**\n * Hidden caller: scheduled jobs and queue workers. A file that registers\n * cron jobs or queue processors is invoked by the scheduler/broker, not by\n * imports — findings in it need lowered confidence.\n */\nimport ts from 'typescript';\nimport { evidenceFor } from '../model/signals.js';\nimport { packageNameOf } from '../graph/resolver.js';\nimport type { EvidenceProvider } from './types.js';\nimport { addOnce } from './types.js';\n\nconst JOB_PACKAGES = new Set([\n 'node-cron',\n 'cron',\n 'bull',\n 'bullmq',\n 'agenda',\n 'bree',\n 'node-schedule',\n 'toad-scheduler',\n]);\n\nconst JOB_CALL_NAMES = new Set(['schedule', 'scheduleJob', 'process', 'add', 'every']);\nconst JOB_CTOR_NAMES = new Set(['Queue', 'Worker', 'CronJob', 'Agenda', 'Bree']);\n\nexport const jobRegistration: EvidenceProvider = {\n name: 'job-registration',\n\n provide(ctx, findings) {\n const jobFiles = new Map<string, string>(); // abs file → package responsible\n for (const [file, pf] of ctx.graph.files) {\n const jobPkg = pf.imports\n .map((i) => i.resolvedPackage ?? packageNameOf(i.specifier))\n .find((p) => JOB_PACKAGES.has(p));\n if (jobPkg && registersJobs(pf.ast)) jobFiles.set(file, jobPkg);\n }\n if (jobFiles.size === 0) return;\n\n for (const finding of findings) {\n if (finding.category === 'unused-dependency') continue;\n const pkg = jobFiles.get(ctx.abs(finding.location.file));\n if (pkg) {\n addOnce(\n finding,\n evidenceFor(\n 'static:job-registration',\n `File registers scheduled work via '${pkg}' — it may run without ever being imported`,\n ),\n );\n }\n }\n },\n};\n\nfunction registersJobs(ast: ts.SourceFile): boolean {\n let found = false;\n const visit = (node: ts.Node): void => {\n if (found) return;\n if (\n ts.isCallExpression(node) &&\n ts.isPropertyAccessExpression(node.expression) &&\n JOB_CALL_NAMES.has(node.expression.name.text)\n ) {\n found = true;\n return;\n }\n if (ts.isNewExpression(node)) {\n const callee = node.expression;\n const name = ts.isIdentifier(callee)\n ? callee.text\n : ts.isPropertyAccessExpression(callee)\n ? callee.name.text\n : undefined;\n if (name && JOB_CTOR_NAMES.has(name)) {\n found = true;\n return;\n }\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(ast, visit);\n return found;\n}\n","/**\n * Kill evidence from human intent: @deprecated markers and \"TODO: remove\"\n * style comments near a finding raise confidence — someone already decided\n * this code should go.\n */\nimport { evidenceFor } from '../model/signals.js';\nimport type { EvidenceProvider } from './types.js';\nimport { addOnce } from './types.js';\n\n/** Markers within this many lines of the finding count as referring to it. */\nconst PROXIMITY_LINES = 3;\n\nexport const comments: EvidenceProvider = {\n name: 'comments',\n\n provide(ctx, findings) {\n for (const finding of findings) {\n const pf = ctx.graph.files.get(ctx.abs(finding.location.file));\n if (!pf || pf.commentMarkers.length === 0) continue;\n\n for (const marker of pf.commentMarkers) {\n const near =\n Math.abs(marker.line - finding.location.line) <= PROXIMITY_LINES ||\n // Whole-file findings: a marker anywhere in the first lines of the file.\n (finding.category === 'unreachable-file' && marker.line <= PROXIMITY_LINES + 1);\n if (!near) continue;\n\n addOnce(\n finding,\n evidenceFor(\n marker.type === 'deprecated' ? 'static:deprecated-jsdoc' : 'static:removal-comment',\n `${marker.type === 'deprecated' ? 'Deprecation' : 'Removal'} marker at line ${marker.line}: ${truncate(marker.text)}`,\n { file: finding.location.file, line: marker.line },\n ),\n );\n }\n }\n },\n};\n\nfunction truncate(s: string): string {\n return s.length > 70 ? s.slice(0, 67) + '…' : s;\n}\n","/**\n * Hidden caller: files referenced by caller manifests (crontab, CI workflows,\n * k8s specs, Dockerfiles, …). These files already became entry points; this\n * provider additionally lowers confidence for findings *inside* them (e.g. an\n * \"unused\" export that a serverless handler string actually names).\n */\nimport { evidenceFor } from '../model/signals.js';\nimport type { EvidenceProvider } from './types.js';\nimport { addOnce } from './types.js';\n\nexport const manifestReference: EvidenceProvider = {\n name: 'manifest-reference',\n\n provide(ctx, findings) {\n if (ctx.manifestCallers.length === 0) return;\n const byFile = new Map(ctx.manifestCallers.map((c) => [c.file, c]));\n\n for (const finding of findings) {\n if (finding.category === 'unused-dependency') continue;\n const caller = byFile.get(ctx.abs(finding.location.file));\n if (caller) {\n addOnce(\n finding,\n evidenceFor('static:manifest-reference', `${caller.detail} (${caller.manifest})`),\n );\n }\n }\n },\n};\n","import type {\n ConfidenceLevel,\n ConfidenceScore,\n Evidence,\n FindingCategory,\n} from '../model/finding.js';\nimport { STATIC_CAPS, STATIC_CAP_REASON } from '../model/signals.js';\n\nfunction levelFor(score: number): ConfidenceLevel {\n if (score >= 80) return 'high';\n if (score >= 50) return 'medium';\n return 'low';\n}\n\n/**\n * Deterministic confidence math: sum of signed evidence weights, clamped to\n * [0, cap]. The cap is 100 once any non-static evidence exists — production\n * data literally unlocks higher confidence, which is the business model.\n */\nexport function scoreFinding(category: FindingCategory, evidence: Evidence[]): ConfidenceScore {\n const raw = evidence.reduce((sum, e) => sum + e.weight, 0);\n const allStatic = evidence.every((e) => e.source === 'static');\n const cap = allStatic ? STATIC_CAPS[category] : 100;\n const score = Math.max(0, Math.min(cap, Math.round(raw)));\n const result: ConfidenceScore = { score, level: levelFor(score) };\n if (allStatic && raw > cap) {\n result.capped = { at: cap, reason: STATIC_CAP_REASON };\n }\n return result;\n}\n","import type { ConfidenceLevel, Finding } from '@deadwood/core';\n\nexport interface FailOnSpec {\n level: ConfidenceLevel;\n /** Minimum number of findings at/above `level` required to trip the gate. */\n min: number;\n}\n\nconst LEVEL_RANK: Record<ConfidenceLevel, number> = { low: 0, medium: 1, high: 2 };\n\n/** Parse 'high' | 'medium' | 'low' | 'high:5' style gate specs. */\nexport function parseFailOn(spec: string): FailOnSpec {\n const m = /^(high|medium|low)(?::(\\d+))?$/.exec(spec);\n if (!m) {\n throw new Error(`Invalid --fail-on '${spec}' (expected e.g. 'high', 'medium', 'high:5')`);\n }\n return { level: m[1] as ConfidenceLevel, min: m[2] ? Number(m[2]) : 1 };\n}\n\n/**\n * Returns the number of findings at/above the gate level. The gate evaluates\n * the FULL finding set — display filters (--min-confidence, --category) must\n * never weaken a CI gate.\n */\nexport function evaluateFailOn(\n findings: Finding[],\n spec: FailOnSpec,\n): { count: number; tripped: boolean } {\n const count = findings.filter(\n (f) => LEVEL_RANK[f.confidence.level] >= LEVEL_RANK[spec.level],\n ).length;\n return { count, tripped: count >= spec.min };\n}\n","import type { ScanResult } from '@deadwood/core';\n\n/**\n * The machine-readable contract. ScanResult.schemaVersion governs this shape —\n * never reshape the payload here; change the core model and bump the version.\n */\nexport function renderJson(result: ScanResult): string {\n return JSON.stringify(result, null, 2) + '\\n';\n}\n","/**\n * Markdown report — designed to paste into a PR comment or Slack message.\n */\nimport type { FindingCategory, ScanResult } from '@deadwood/core';\nimport { describeTarget } from '@deadwood/core';\n\nconst CATEGORY_TITLES: Record<FindingCategory, string> = {\n 'dead-route': 'Routes that appear dead',\n 'unused-export': 'Exports that appear unused',\n 'unused-dependency': 'Dependencies that appear unused',\n 'unreachable-file': 'Files that appear unreachable',\n};\n\nexport function renderMd(result: ScanResult): string {\n const lines: string[] = [];\n const { stats } = result;\n\n lines.push(`## ☠ deadwood report`);\n lines.push('');\n if (stats.routes.total > 0) {\n const pct = Math.round((stats.routes.flagged / stats.routes.total) * 100);\n lines.push(\n `**${pct}% of routes appear dead** (${stats.routes.flagged} of ${stats.routes.total})`,\n );\n }\n const summary: string[] = [];\n if (stats.exports.total > 0) summary.push(`${stats.exports.flagged} unused exports`);\n if (stats.dependencies.total > 0)\n summary.push(`${stats.dependencies.flagged} unused dependencies`);\n if (stats.files.total > 0) summary.push(`${stats.files.flagged} unreachable files`);\n if (summary.length > 0)\n lines.push(`${summary.join(' · ')} — ${stats.filesScanned} files scanned`);\n lines.push('');\n\n for (const category of Object.keys(CATEGORY_TITLES) as FindingCategory[]) {\n const group = result.findings.filter((f) => f.category === category);\n if (group.length === 0) continue;\n lines.push(`### ${CATEGORY_TITLES[category]} (${group.length})`);\n lines.push('');\n lines.push('| Confidence | Target | Location | Top evidence |');\n lines.push('|---|---|---|---|');\n for (const f of group) {\n const top = [...f.evidence].sort((a, b) => Math.abs(b.weight) - Math.abs(a.weight))[0];\n lines.push(\n `| ${f.confidence.score} ${f.confidence.level} | ${escapeMd(describeTarget(f.target))} | \\`${f.location.file}:${f.location.line}\\` | ${escapeMd(top?.detail ?? '')} |`,\n );\n }\n lines.push('');\n }\n\n if (result.findings.some((f) => f.confidence.capped)) {\n lines.push(\n `> ⚠ Confidence is capped for static-only findings — no runtime evidence. Connect production telemetry to confirm.`,\n );\n lines.push('');\n }\n for (const warning of result.warnings) {\n lines.push(`> ⚠ ${escapeMd(warning)}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\nfunction escapeMd(s: string): string {\n return s.replace(/\\|/g, '\\\\|');\n}\n","/**\n * The terminal shock report. This output is the product's marketing — keep it\n * sharp, honest (\"appears dead\", never \"is dead\"), and always explain the cap.\n */\nimport pc from 'picocolors';\nimport type {\n CategoryStat,\n ConfidenceLevel,\n Finding,\n FindingCategory,\n ScanResult,\n} from '@deadwood/core';\nimport { describeTarget } from '@deadwood/core';\n\ntype Colors = ReturnType<typeof pc.createColors>;\n\nconst CATEGORY_TITLES: Record<FindingCategory, string> = {\n 'dead-route': 'ROUTES THAT APPEAR DEAD',\n 'unused-export': 'EXPORTS THAT APPEAR UNUSED',\n 'unused-dependency': 'DEPENDENCIES THAT APPEAR UNUSED',\n 'unreachable-file': 'FILES THAT APPEAR UNREACHABLE',\n};\n\nconst RULE_WIDTH = 72;\n\nexport function renderPretty(result: ScanResult, useColor: boolean): string {\n const c = pc.createColors(useColor);\n const lines: string[] = [];\n const { stats } = result;\n\n // ── header ────────────────────────────────────────────────────────────\n lines.push('');\n lines.push(` ${c.bold('☠ deadwood')} ${c.dim(`v${result.tool.version}`)}`);\n const meta = [\n `${stats.filesScanned} files scanned`,\n formatDuration(stats.durationMs),\n result.workspaces.length > 1 ? `${result.workspaces.length} workspaces` : undefined,\n ].filter(Boolean);\n lines.push(` ${c.dim(meta.join(' · '))}`);\n lines.push(` ${c.dim('─'.repeat(RULE_WIDTH))}`);\n lines.push('');\n\n // ── shock lines: routes first (the headline) ─────────────────────────\n pushShock(lines, c, stats.routes, 'of your routes appear dead', true);\n pushShock(lines, c, stats.exports, 'exports appear unused');\n pushShock(lines, c, stats.dependencies, 'dependencies appear unused');\n pushShock(lines, c, stats.files, 'files appear unreachable');\n\n if (result.findings.length === 0) {\n lines.push(\n ` ${c.green('✓')} No dead code findings. Either pristine — or hiding from static analysis.`,\n );\n }\n\n // ── findings grouped by category (engine pre-sorts by confidence) ────\n for (const category of Object.keys(CATEGORY_TITLES) as FindingCategory[]) {\n const group = result.findings.filter((f) => f.category === category);\n if (group.length === 0) continue;\n\n const actionable = group.filter((f) => f.confidence.score >= 50).length;\n const counts =\n actionable === group.length\n ? `${group.length}`\n : `${group.length} · ${actionable} actionable`;\n\n lines.push('');\n lines.push(sectionRule(c, CATEGORY_TITLES[category], counts));\n lines.push('');\n\n for (const finding of group) {\n const lv = finding.confidence.level;\n lines.push(\n ` ${dot(c, lv)} ${scoreLabel(c, finding.confidence.score, lv)} ${c.dim('│')} ${c.bold(\n describeTarget(finding.target),\n )}`,\n );\n lines.push(\n ` ${c.dim('│')} ${c.dim(`${finding.location.file}:${finding.location.line}`)}`,\n );\n const top = topEvidence(finding);\n for (const ev of top) {\n const mark = ev.direction === 'kill' ? c.red('▪') : c.yellow('▫');\n lines.push(` ${c.dim('│')} ${mark} ${c.dim(ev.detail)}`);\n }\n const more = finding.evidence.length - top.length;\n if (more > 0) {\n lines.push(\n ` ${c.dim('│')} ${c.dim(`… ${more} more signal${more > 1 ? 's' : ''} (see --json)`)}`,\n );\n }\n lines.push('');\n }\n }\n\n // ── footer ─────────────────────────────────────────────────────────────\n lines.push(` ${c.dim('─'.repeat(RULE_WIDTH))}`);\n const anyStaticOnly = result.findings.some((f) => f.evidence.every((e) => e.source === 'static'));\n if (anyStaticOnly) {\n lines.push(\n ` ${c.yellow('⚠')} Confidence is capped for static-only findings ${c.dim('(routes 70, others 85)')} —`,\n );\n lines.push(` no runtime evidence. Connect production telemetry to confirm.`);\n }\n if (result.findings.some((f) => f.confidence.score < 50)) {\n lines.push(\n ` ${c.dim('ℹ')} ${c.dim('actionable = medium confidence or higher; headline counts only these')}`,\n );\n }\n for (const warning of result.warnings) {\n lines.push(` ${c.yellow('⚠')} ${c.dim(warning)}`);\n }\n lines.push('');\n lines.push(\n ` ${c.dim('→ --min-confidence medium · --json for machines · --fail-on high for CI')}`,\n );\n lines.push('');\n return lines.join('\\n');\n}\n\nfunction pushShock(\n lines: string[],\n c: Colors,\n stat: CategoryStat,\n label: string,\n withPercent = false,\n): void {\n if (stat.total === 0) return;\n const skull = stat.flagged > 0 ? c.red('☠') : c.green('✓');\n if (withPercent) {\n const pct = Math.round((stat.flagged / stat.total) * 100);\n lines.push(\n ` ${skull} ${c.bold(`${pct}%`)} ${label} ${c.dim(`(${stat.flagged} of ${stat.total})`)}`,\n );\n } else {\n lines.push(` ${skull} ${c.bold(String(stat.flagged))} ${c.dim('of')} ${stat.total} ${label}`);\n }\n}\n\n/** `── TITLE ───────────────────── 21 · 16 actionable` */\nfunction sectionRule(c: Colors, title: string, counts: string): string {\n const fill = Math.max(2, RULE_WIDTH - title.length - counts.length - 8);\n return ` ${c.dim('──')} ${c.bold(title)} ${c.dim('─'.repeat(fill))} ${c.dim(counts)}`;\n}\n\nfunction dot(c: Colors, level: ConfidenceLevel): string {\n if (level === 'high') return c.red('●');\n if (level === 'medium') return c.yellow('●');\n return c.dim('○');\n}\n\n/** Fixed-width `65 medium` label so every finding row lines up. */\nfunction scoreLabel(c: Colors, score: number, level: ConfidenceLevel): string {\n const text = `${String(score).padStart(3)} ${level.padEnd(6)}`;\n if (level === 'high') return c.red(c.bold(text));\n if (level === 'medium') return c.yellow(text);\n return c.dim(text);\n}\n\n/** Show the strongest two signals — full detail lives in --json. */\nfunction topEvidence(finding: Finding): Finding['evidence'] {\n return [...finding.evidence].sort((a, b) => Math.abs(b.weight) - Math.abs(a.weight)).slice(0, 2);\n}\n\nfunction formatDuration(ms: number): string {\n return ms < 1000 ? `${ms}ms` : `${(ms / 1000).toFixed(1)}s`;\n}\n"],"mappings":";;;AAOA,SAAS,qBAAqB;AAC9B,OAAO,aAAa;AACpB,SAAS,SAAS,cAAc;AAChC,OAAO,SAAS;AAChB,OAAOA,SAAQ;;;ACLf,OAAOC,SAAQ;AACf,OAAOC,YAAU;AACjB,SAAS,QAAAC,aAAY;;;ACFd,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC,YACW,MACT,SACA;AACA,UAAM,OAAO;AAHJ;AAIT,SAAK,OAAO;AAAA,EACd;AAAA,EALW;AAMb;;;ACRA,OAAO,QAAQ;AA6Ef,IAAM,gBAAgB;AACtB,IAAM,aAAa;AAEnB,SAAS,cAAc,MAA6B;AAClD,MAAI,KAAK,SAAS,MAAM,EAAG,QAAO,GAAG,WAAW;AAChD,MAAI,KAAK,SAAS,MAAM,EAAG,QAAO,GAAG,WAAW;AAChD,MAAI,kBAAkB,KAAK,IAAI,EAAG,QAAO,GAAG,WAAW;AACvD,SAAO,GAAG,WAAW;AACvB;AAEO,SAAS,UAAU,WAAmB,MAA0B;AACrE,QAAM,MAAM,GAAG;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAG,aAAa;AAAA,IAChB;AAAA,IACA,cAAc,SAAS;AAAA,EACzB;AACA,QAAM,SAAqB;AAAA,IACzB,MAAM;AAAA,IACN;AAAA,IACA,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,iBAAiB,CAAC;AAAA,IAClB,gBAAgB,sBAAsB,IAAI;AAAA,IAC1C,cAAc,CAAC;AAAA,IACf,qBAAqB;AAAA,EACvB;AAEA,QAAM,SAAS,CAAC,SACd,IAAI,8BAA8B,KAAK,SAAS,GAAG,CAAC,EAAE,OAAO;AAE/D,QAAM,qBAAqB,CAAC,SAA2B;AACrD,UAAM,SAAS,GAAG,wBAAwB,MAAM,KAAK,aAAa,CAAC,KAAK,CAAC;AACzE,WAAO,OAAO,KAAK,CAAC,MAAM,cAAc,KAAK,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAAA,EACxE;AAGA,aAAW,QAAQ,IAAI,YAAY;AACjC,QAAI,GAAG,oBAAoB,IAAI,KAAK,GAAG,gBAAgB,KAAK,eAAe,GAAG;AAC5E,YAAM,SAAuB;AAAA,QAC3B,WAAW,KAAK,gBAAgB;AAAA,QAChC,MAAM;AAAA,QACN,OAAO,CAAC;AAAA,QACR,MAAM,OAAO,IAAI;AAAA,MACnB;AACA,YAAM,SAAS,KAAK;AACpB,UAAI,QAAQ;AACV,YAAI,OAAO,KAAM,QAAO,MAAM,KAAK,EAAE,UAAU,WAAW,OAAO,OAAO,KAAK,KAAK,CAAC;AACnF,YAAI,OAAO,eAAe;AACxB,cAAI,GAAG,kBAAkB,OAAO,aAAa,GAAG;AAC9C,mBAAO,iBAAiB,OAAO,cAAc,KAAK;AAAA,UACpD,OAAO;AACL,uBAAW,MAAM,OAAO,cAAc,UAAU;AAC9C,qBAAO,MAAM,KAAK;AAAA,gBAChB,UAAU,GAAG,cAAc,QAAQ,GAAG,KAAK;AAAA,gBAC3C,OAAO,GAAG,KAAK;AAAA,cACjB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,aAAO,QAAQ,KAAK,MAAM;AAC1B;AAAA,IACF;AAEA,QAAI,GAAG,oBAAoB,IAAI,GAAG;AAChC,YAAM,OAAO,KAAK;AAClB,UAAI,QAAQ,GAAG,gBAAgB,IAAI,GAAG;AACpC,YAAI,CAAC,KAAK,cAAc;AACtB,iBAAO,QAAQ,KAAK;AAAA,YAClB,WAAW,KAAK;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,CAAC;AAAA,YACR,MAAM,OAAO,IAAI;AAAA,UACnB,CAAC;AAAA,QACH,WAAW,GAAG,eAAe,KAAK,YAAY,GAAG;AAC/C,gBAAM,aAAa,KAAK,aAAa,SAAS,IAAI,CAAC,QAAQ;AAAA,YACzD,UAAU,GAAG,KAAK;AAAA,YAClB,UAAU,GAAG,cAAc,QAAQ,GAAG,KAAK;AAAA,UAC7C,EAAE;AACF,iBAAO,QAAQ,KAAK;AAAA,YAClB,WAAW,KAAK;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,CAAC;AAAA,YACR;AAAA,YACA,MAAM,OAAO,IAAI;AAAA,UACnB,CAAC;AAED,qBAAW,KAAK,YAAY;AAC1B,mBAAO,QAAQ,KAAK,EAAE,MAAM,EAAE,UAAU,MAAM,SAAS,MAAM,OAAO,IAAI,EAAE,CAAC;AAAA,UAC7E;AAAA,QACF,WAAW,GAAG,kBAAkB,KAAK,YAAY,GAAG;AAElD,iBAAO,QAAQ,KAAK;AAAA,YAClB,WAAW,KAAK;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,CAAC;AAAA,YACR,MAAM,OAAO,IAAI;AAAA,UACnB,CAAC;AACD,iBAAO,QAAQ,KAAK;AAAA,YAClB,MAAM,KAAK,aAAa,KAAK;AAAA,YAC7B,MAAM;AAAA,YACN,MAAM,OAAO,IAAI;AAAA,UACnB,CAAC;AAAA,QACH;AAAA,MACF,WAAW,KAAK,gBAAgB,GAAG,eAAe,KAAK,YAAY,GAAG;AAEpE,mBAAW,MAAM,KAAK,aAAa,UAAU;AAC3C,iBAAO,QAAQ,KAAK;AAAA,YAClB,MAAM,GAAG,KAAK;AAAA,YACd,MAAM;AAAA,YACN,MAAM,OAAO,EAAE;AAAA,YACf,GAAI,mBAAmB,IAAI,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,UACzD,CAAC;AAAA,QACH;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,GAAG,mBAAmB,IAAI,GAAG;AAE/B,aAAO,QAAQ,KAAK,EAAE,MAAM,WAAW,MAAM,SAAS,MAAM,OAAO,IAAI,EAAE,CAAC;AAC1E;AAAA,IACF;AAEA,2BAAuB,MAAM,QAAQ,QAAQ,kBAAkB;AAAA,EACjE;AAGA,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAI,GAAG,iBAAiB,IAAI,GAAG;AAC7B,iBAAW,MAAM,QAAQ,MAAM;AAAA,IACjC,WACE,GAAG,mBAAmB,IAAI,KAC1B,KAAK,cAAc,SAAS,GAAG,WAAW,aAC1C;AACA,gCAA0B,MAAM,QAAQ,MAAM;AAAA,IAChD,WAAW,GAAG,gBAAgB,IAAI,KAAK,GAAG,gCAAgC,IAAI,GAAG;AAC/E,YAAM,IAAI,KAAK;AAIf,UAAI,EAAE,SAAS,OAAO,EAAE,WAAW,GAAG,KAAK,CAAC,KAAK,KAAK,CAAC,GAAG;AACxD,eAAO,aAAa,KAAK,EAAE,OAAO,GAAG,MAAM,OAAO,IAAI,EAAE,CAAC;AAAA,MAC3D;AAAA,IACF;AACA,OAAG,aAAa,MAAM,KAAK;AAAA,EAC7B;AACA,KAAG,aAAa,KAAK,KAAK;AAG1B,QAAM,kBAAkB,oBAAI,IAA4B;AACxD,aAAW,OAAO,OAAO,SAAS;AAChC,QAAI,IAAI,gBAAgB;AACtB,YAAM,QAAwB,EAAE,SAAS,oBAAI,IAAI,GAAG,SAAS,MAAM;AACnE,UAAI,iBAAiB;AACrB,sBAAgB,IAAI,IAAI,gBAAgB,KAAK;AAAA,IAC/C;AAAA,EACF;AACA,MAAI,gBAAgB,OAAO,GAAG;AAC5B,wBAAoB,KAAK,eAAe;AAAA,EAC1C;AAEA,SAAO;AACT;AAEA,SAAS,uBACP,MACA,QACA,QACA,oBACM;AACN,QAAM,OAAO,GAAG,iBAAiB,IAAI,IAAI,GAAG,aAAa,IAAI,IAAI;AACjE,MAAI,CAAC,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,WAAW,aAAa,EAAG;AAChE,QAAM,YAAY,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,WAAW,cAAc;AAC1E,QAAM,aAAa,mBAAmB,IAAI,IAAI,OAAO;AACrD,QAAM,OAAO,CAAC,MAAc,MAAkB,SAC5C,OAAO,QAAQ,KAAK,EAAE,MAAM,MAAM,MAAM,OAAO,IAAI,GAAG,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC,EAAG,CAAC;AAE/F,MAAI,GAAG,sBAAsB,IAAI,KAAK,GAAG,mBAAmB,IAAI,GAAG;AACjE,SAAK,YAAY,YAAa,KAAK,MAAM,QAAQ,WAAY,SAAS,IAAI;AAAA,EAC5E,WAAW,GAAG,oBAAoB,IAAI,GAAG;AACvC,eAAW,QAAQ,KAAK,gBAAgB,cAAc;AACpD,0BAAoB,KAAK,MAAM,CAAC,SAAS,KAAK,MAAM,SAAS,IAAI,CAAC;AAAA,IACpE;AAAA,EACF,WAAW,GAAG,uBAAuB,IAAI,KAAK,GAAG,uBAAuB,IAAI,GAAG;AAC7E,SAAK,KAAK,KAAK,MAAM,QAAQ,IAAI;AAAA,EACnC,WAAW,GAAG,kBAAkB,IAAI,KAAK,GAAG,oBAAoB,IAAI,GAAG;AACrE,QAAI,KAAK,QAAQ,GAAG,aAAa,KAAK,IAAI,EAAG,MAAK,KAAK,KAAK,MAAM,SAAS,IAAI;AAAA,EACjF;AACF;AAEA,SAAS,oBAAoB,MAAsB,IAA+B;AAChF,MAAI,GAAG,aAAa,IAAI,GAAG;AACzB,OAAG,KAAK,IAAI;AAAA,EACd,WAAW,GAAG,uBAAuB,IAAI,KAAK,GAAG,sBAAsB,IAAI,GAAG;AAC5E,eAAW,MAAM,KAAK,UAAU;AAC9B,UAAI,GAAG,iBAAiB,EAAE,EAAG,qBAAoB,GAAG,MAAM,EAAE;AAAA,IAC9D;AAAA,EACF;AACF;AAGA,SAAS,gBAAgB,KAAwC;AAC/D,MAAI,GAAG,qBAAqB,GAAG,KAAK,IAAI,KAAK,KAAK,SAAS,EAAG,QAAO,IAAI,KAAK;AAC9E,MACE,GAAG,mBAAmB,GAAG,KACzB,IAAI,cAAc,SAAS,GAAG,WAAW,cACxC,GAAG,gBAAgB,IAAI,IAAI,KAAK,GAAG,gCAAgC,IAAI,IAAI,IAC5E;AACA,WAAO,IAAI,KAAK;AAAA,EAClB;AACA,SAAO;AACT;AAEA,SAAS,WACP,MACA,QACA,QACM;AACN,QAAM,OAAO,OAAO,IAAI;AAGxB,MACE,GAAG,aAAa,KAAK,UAAU,KAC/B,KAAK,WAAW,SAAS,aACzB,KAAK,UAAU,WAAW,GAC1B;AACA,UAAM,MAAM,KAAK,UAAU,CAAC;AAC5B,QAAI,GAAG,gBAAgB,GAAG,KAAK,GAAG,gCAAgC,GAAG,GAAG;AACtE,YAAM,SAAuB,EAAE,WAAW,IAAI,MAAM,MAAM,WAAW,OAAO,CAAC,GAAG,KAAK;AACrF,wBAAkB,MAAM,MAAM;AAC9B,aAAO,QAAQ,KAAK,MAAM;AAAA,IAC5B,OAAO;AACL,YAAM,SAAS,gBAAgB,GAAG;AAClC,aAAO,gBAAgB,KAAK,EAAE,MAAM,WAAW,MAAM,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAAA,IACtF;AACA;AAAA,EACF;AAGA,MAAI,KAAK,WAAW,SAAS,GAAG,WAAW,iBAAiB,KAAK,UAAU,UAAU,GAAG;AACtF,UAAM,MAAM,KAAK,UAAU,CAAC;AAC5B,QAAI,GAAG,gBAAgB,GAAG,KAAK,GAAG,gCAAgC,GAAG,GAAG;AAGtE,aAAO,QAAQ,KAAK,EAAE,WAAW,IAAI,MAAM,MAAM,WAAW,OAAO,CAAC,GAAG,KAAK,CAAC;AAAA,IAC/E,OAAO;AACL,YAAM,SAAS,gBAAgB,GAAG;AAClC,aAAO,gBAAgB,KAAK,EAAE,MAAM,UAAU,MAAM,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAAA,IACrF;AACA;AAAA,EACF;AAGA,MACE,GAAG,2BAA2B,KAAK,UAAU,KAC7C,GAAG,aAAa,KAAK,WAAW,UAAU,KAC1C,KAAK,WAAW,WAAW,SAAS,aACpC,KAAK,WAAW,KAAK,SAAS,aAC9B,KAAK,UAAU,UAAU,GACzB;AACA,UAAM,MAAM,KAAK,UAAU,CAAC;AAC5B,UAAM,SAAS,GAAG,gBAAgB,GAAG,IAAI,IAAI,OAAO,gBAAgB,GAAG;AACvE,WAAO,gBAAgB,KAAK,EAAE,MAAM,WAAW,MAAM,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAAA,EACtF;AACF;AAGA,SAAS,kBAAkB,MAAyB,QAA4B;AAC9E,QAAM,SAAS,KAAK;AACpB,MAAI,UAAU,GAAG,sBAAsB,MAAM,KAAK,OAAO,gBAAgB,MAAM;AAC7E,QAAI,GAAG,aAAa,OAAO,IAAI,GAAG;AAEhC,aAAO,iBAAiB,OAAO,KAAK;AAAA,IACtC,WAAW,GAAG,uBAAuB,OAAO,IAAI,GAAG;AACjD,iBAAW,MAAM,OAAO,KAAK,UAAU;AACrC,YAAI,GAAG,iBAAiB,EAAE,KAAK,GAAG,aAAa,GAAG,IAAI,GAAG;AACvD,gBAAM,WACJ,GAAG,gBAAgB,GAAG,aAAa,GAAG,YAAY,IAC9C,GAAG,aAAa,OAChB,GAAG,KAAK;AACd,iBAAO,MAAM,KAAK,EAAE,UAAU,OAAO,GAAG,KAAK,KAAK,CAAC;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEF;AAEA,SAAS,0BACP,MACA,QACA,QACM;AACN,QAAM,OAAO,KAAK;AAClB,QAAM,OAAO,OAAO,IAAI;AAExB,QAAM,kBAAkB,CAAC,MACvB,GAAG,2BAA2B,CAAC,KAC/B,GAAG,aAAa,EAAE,UAAU,KAC5B,EAAE,WAAW,SAAS,YACtB,EAAE,KAAK,SAAS;AAGlB,MAAI,gBAAgB,IAAI,GAAG;AACzB,QAAI,GAAG,0BAA0B,KAAK,KAAK,GAAG;AAG5C,iBAAW,QAAQ,KAAK,MAAM,YAAY;AACxC,cAAM,OAAO,KAAK;AAClB,YAAI,SAAS,GAAG,aAAa,IAAI,KAAK,GAAG,gBAAgB,IAAI,IAAI;AAC/D,iBAAO,QAAQ,KAAK,EAAE,MAAM,KAAK,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,QAC5D;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,QAAQ,KAAK,EAAE,MAAM,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IAC5D;AACA;AAAA,EACF;AAGA,MAAI,GAAG,2BAA2B,IAAI,GAAG;AACvC,UAAM,OAAO,KAAK;AAClB,UAAM,gBACH,GAAG,aAAa,IAAI,KAAK,KAAK,SAAS,aAAc,gBAAgB,IAAI;AAC5E,QAAI,iBAAiB,KAAK,KAAK,SAAS,cAAc;AACpD,aAAO,QAAQ,KAAK,EAAE,MAAM,KAAK,KAAK,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,IACjE;AACA;AAAA,EACF;AAGA,MAAI,GAAG,0BAA0B,IAAI,GAAG;AACtC,UAAM,OAAO,KAAK;AAClB,QAAK,GAAG,aAAa,IAAI,KAAK,KAAK,SAAS,aAAc,gBAAgB,IAAI,GAAG;AAC/E,aAAO,sBAAsB;AAAA,IAC/B;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,KAAoB,QAA2C;AAC1F,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAI,GAAG,aAAa,IAAI,KAAK,OAAO,IAAI,KAAK,IAAI,GAAG;AAClD,YAAM,QAAQ,OAAO,IAAI,KAAK,IAAI;AAClC,YAAM,SAAS,KAAK;AACpB,YAAM,oBACJ,WACE,GAAG,kBAAkB,MAAM,KAAK,OAAO,SAAS,QAC/C,GAAG,sBAAsB,MAAM,KAAK,OAAO,SAAS,QACpD,GAAG,kBAAkB,MAAM,KAAK,OAAO,SAAS;AACrD,UAAI,CAAC,mBAAmB;AACtB,YAAI,UAAU,GAAG,2BAA2B,MAAM,KAAK,OAAO,eAAe,MAAM;AACjF,gBAAM,QAAQ,IAAI,OAAO,KAAK,IAAI;AAAA,QACpC,OAAO;AAGL,gBAAM,UAAU;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AACA,OAAG,aAAa,MAAM,KAAK;AAAA,EAC7B;AACA,KAAG,aAAa,KAAK,KAAK;AAC5B;AAEA,SAAS,sBAAsB,MAA+B;AAC5D,QAAM,UAA2B,CAAC;AAClC,QAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AAEpB,QAAI,CAAC,mBAAmB,KAAK,IAAI,EAAG;AACpC,QAAI,cAAc,KAAK,IAAI,GAAG;AAC5B,cAAQ,KAAK,EAAE,MAAM,IAAI,GAAG,MAAM,cAAc,MAAM,KAAK,KAAK,EAAE,CAAC;AAAA,IACrE,WAAW,WAAW,KAAK,IAAI,GAAG;AAChC,cAAQ,KAAK,EAAE,MAAM,IAAI,GAAG,MAAM,WAAW,MAAM,KAAK,KAAK,EAAE,CAAC;AAAA,IAClE;AAAA,EACF;AACA,SAAO;AACT;;;ACncO,IAAM,cAAN,MAAkB;AAAA,EACd,QAAQ,oBAAI,IAAwB;AAAA,EACrC,UAAU,oBAAI,IAA4B;AAAA,EAElD,QAAQ,IAAsB;AAC5B,SAAK,MAAM,IAAI,GAAG,MAAM,EAAE;AAAA,EAC5B;AAAA;AAAA,EAGA,KAAK,UAA0B;AAC7B,eAAW,MAAM,KAAK,MAAM,OAAO,GAAG;AACpC,iBAAW,UAAU,GAAG,SAAS;AAC/B,cAAM,MAAM,SAAS,QAAQ,OAAO,WAAW,GAAG,IAAI;AACtD,YAAI,IAAI,QAAQ,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG;AACxC,iBAAO,eAAe,IAAI;AAC1B,cAAI,QAAQ,KAAK,QAAQ,IAAI,IAAI,IAAI;AACrC,cAAI,CAAC,MAAO,MAAK,QAAQ,IAAI,IAAI,MAAO,QAAQ,CAAC,CAAE;AACnD,gBAAM,KAAK,EAAE,UAAU,GAAG,MAAM,OAAO,CAAC;AAAA,QAC1C,WAAW,IAAI,KAAK;AAClB,iBAAO,kBAAkB,IAAI;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY,MAA8B;AACxC,WAAO,KAAK,QAAQ,IAAI,IAAI,KAAK,CAAC;AAAA,EACpC;AAAA;AAAA,EAGA,UAAU,SAAwC;AAChD,UAAM,OAAO,oBAAI,IAAY;AAC7B,UAAM,QAAkB,CAAC;AACzB,eAAW,KAAK,SAAS;AACvB,UAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,GAAG;AACrC,aAAK,IAAI,CAAC;AACV,cAAM,KAAK,CAAC;AAAA,MACd;AAAA,IACF;AACA,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,KAAK,KAAK,MAAM,IAAI,IAAI;AAC9B,iBAAW,UAAU,GAAG,SAAS;AAC/B,cAAM,OAAO,OAAO;AACpB,YAAI,QAAQ,CAAC,KAAK,IAAI,IAAI,GAAG;AAC3B,eAAK,IAAI,IAAI;AACb,gBAAM,KAAK,IAAI;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBACE,MACA,MACA,SACA,UAAU,oBAAI,IAAY,GACjB;AACT,UAAM,MAAM,GAAG,IAAI,IAAI,IAAI;AAC3B,QAAI,QAAQ,IAAI,GAAG,EAAG,QAAO;AAC7B,YAAQ,IAAI,GAAG;AAEf,eAAW,EAAE,UAAU,OAAO,KAAK,KAAK,YAAY,IAAI,GAAG;AACzD,UAAI;AACJ,UAAI,OAAO,SAAS,mBAAmB,SAAS,WAAW;AACzD,sBAAc;AAAA,MAChB,WAAW,OAAO,SAAS,kBAAkB;AAC3C,sBAAc,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,aAAa,IAAI,GAAG;AAAA,MACrE;AACA,UAAI,CAAC,YAAa;AAClB,UAAI,QAAQ,IAAI,QAAQ,EAAG,QAAO;AAClC,UAAI,KAAK,oBAAoB,UAAU,aAAa,SAAS,OAAO,EAAG,QAAO;AAAA,IAChF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,MAAc,MAAc,UAAU,oBAAI,IAAY,GAAY;AAC7E,UAAM,MAAM,GAAG,IAAI,IAAI,IAAI;AAC3B,QAAI,QAAQ,IAAI,GAAG,EAAG,QAAO;AAC7B,YAAQ,IAAI,GAAG;AAEf,eAAW,EAAE,UAAU,OAAO,KAAK,KAAK,YAAY,IAAI,GAAG;AACzD,cAAQ,OAAO,MAAM;AAAA,QACnB,KAAK;AAAA,QACL,KAAK,WAAW;AACd,cAAI,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,IAAI,EAAG,QAAO;AAC1D,gBAAM,KAAK,OAAO;AAClB,cAAI,OAAO,GAAG,WAAW,GAAG,QAAQ,IAAI,IAAI,GAAI,QAAO;AACvD;AAAA,QACF;AAAA,QACA,KAAK;AAEH,iBAAO;AAAA,QACT,KAAK,kBAAkB;AACrB,gBAAM,QAAQ,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,aAAa,IAAI;AAChE,cAAI,SAAS,KAAK,aAAa,UAAU,MAAM,UAAU,OAAO,EAAG,QAAO;AAC1E;AAAA,QACF;AAAA,QACA,KAAK;AAEH,cAAI,SAAS,aAAa,KAAK,aAAa,UAAU,MAAM,OAAO,EAAG,QAAO;AAC7E;AAAA,MACJ;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;AC5HA,OAAO,QAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,sBAAsB;AAC/B,OAAOC,SAAQ;;;ACTf,OAAO,UAAU;AAOV,SAAS,QAAQ,GAAmB;AACzC,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAEO,SAAS,SAAS,GAAmB;AAC1C,SAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAChC;AAEO,SAAS,SAAS,MAAc,IAAoB;AACzD,SAAO,QAAQ,KAAK,SAAS,MAAM,EAAE,CAAC;AACxC;AAEO,SAAS,aAAa,GAAmB;AAC9C,SAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAChC;AAMO,SAAS,QAAQ,KAAa,MAAuB;AAC1D,SAAO,SAAS,OAAO,KAAK,WAAW,IAAI,SAAS,GAAG,IAAI,MAAM,MAAM,GAAG;AAC5E;;;ADjBA,IAAM,WAAW,IAAI,IAAI,cAAc;AAEvC,IAAM,qBAAqB,CAAC,OAAO,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,MAAM;AAexF,IAAM,kBAAsC;AAAA,EAC1C,kBAAkBC,IAAG,qBAAqB;AAAA,EAC1C,QAAQA,IAAG,WAAW;AAAA,EACtB,QAAQA,IAAG,aAAa;AAAA,EACxB,SAAS;AAAA,EACT,mBAAmB;AACrB;AAEO,IAAM,WAAN,MAAe;AAAA,EAOpB,YACmB,SACA,mBACA,cACA,UACjB;AAJiB;AACA;AACA;AACA;AAAA,EAChB;AAAA,EAJgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EATX,eAAe,oBAAI,IAAgC;AAAA;AAAA,EAEnD,gBAAgB,oBAAI,IAAgC;AAAA,EACpD,gBAAgB,oBAAI,IAAY;AAAA,EASxC,QAAQ,WAAmB,gBAAoC;AAC7D,QAAI,UAAU,WAAW,OAAO,EAAG,QAAO,CAAC;AAC3C,QAAI,SAAS,IAAI,SAAS,KAAK,SAAS,IAAI,UAAU,MAAM,GAAG,EAAE,CAAC,CAAE,EAAG,QAAO,CAAC;AAM/E,UAAM,UAAU,KAAK,iBAAiB,SAAS;AAC/C,QAAI,SAAS,QAAQ,KAAK,aAAa,IAAI,QAAQ,IAAI,EAAG,QAAO;AAEjE,UAAM,UAAU,KAAK,WAAW,aAAa,cAAc,CAAC;AAC5D,UAAM,IAAIA,IAAG,kBAAkB,WAAW,gBAAgB,SAASA,IAAG,GAAG;AACzE,UAAM,WAAW,EAAE;AACnB,QAAI,UAAU;AACZ,YAAM,OAAO,QAAQ,SAAS,gBAAgB;AAC9C,UAAI,CAAC,SAAS,2BAA2B,CAAC,KAAK,SAAS,gBAAgB,GAAG;AACzE,YAAI,KAAK,aAAa,IAAI,IAAI,EAAG,QAAO,EAAE,KAAK;AAI/C,cAAMC,MAAK,KAAK,iBAAiB,SAAS;AAC1C,YAAIA,KAAI,QAAQ,KAAK,aAAa,IAAIA,IAAG,IAAI,EAAG,QAAOA;AACvD,YAAI,UAAU,WAAW,GAAG,GAAG;AAC7B,gBAAM,SAAS,QAAQC,MAAK,QAAQA,MAAK,QAAQ,cAAc,GAAG,SAAS,CAAC;AAC5E,cAAI,UAAU,KAAK,aAAa,IAAI,QAAQ,MAAM,CAAC,EAAG,QAAO,EAAE,MAAM,QAAQ,MAAM,EAAE;AACrF,iBAAO,CAAC;AAAA,QACV;AACA,eAAO,EAAE,KAAK,cAAc,SAAS,EAAE;AAAA,MACzC;AACA,aAAO,EAAE,KAAK,SAAS,WAAW,QAAQ,cAAc,SAAS,EAAE;AAAA,IACrE;AAGA,UAAM,KAAK,KAAK,iBAAiB,SAAS;AAC1C,QAAI,GAAI,QAAO;AAEf,QAAI,UAAU,WAAW,GAAG,KAAK,UAAU,WAAW,GAAG,GAAG;AAC1D,YAAM,SAAS,QAAQA,MAAK,QAAQA,MAAK,QAAQ,cAAc,GAAG,SAAS,CAAC;AAC5E,UAAI,OAAQ,QAAO,EAAE,MAAM,QAAQ,MAAM,EAAE;AAC3C,aAAO,CAAC;AAAA,IACV;AAIA,WAAO,EAAE,KAAK,cAAc,SAAS,EAAE;AAAA,EACzC;AAAA,EAEQ,iBAAiB,WAA2C;AAClE,eAAW,MAAM,KAAK,mBAAmB;AACvC,UAAI,cAAc,GAAG,MAAM;AACzB,eAAO,GAAG,YAAY,EAAE,MAAM,GAAG,UAAU,IAAI,EAAE,KAAK,GAAG,KAAK;AAAA,MAChE;AACA,UAAI,UAAU,WAAW,GAAG,OAAO,GAAG,GAAG;AACvC,cAAM,MAAM,UAAU,MAAM,GAAG,KAAK,SAAS,CAAC;AAC9C,cAAM,MAAM,QAAQA,MAAK,KAAK,GAAG,KAAK,GAAG,CAAC,KAAK,QAAQA,MAAK,KAAK,GAAG,KAAK,OAAO,GAAG,CAAC;AACpF,eAAO,MAAM,EAAE,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,KAAK,GAAG,KAAK;AAAA,MACvD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,UAAsC;AACvD,UAAM,SAAS,KAAK,aAAa,IAAI,QAAQ;AAC7C,QAAI,OAAQ,QAAO;AAEnB,QAAI,UAAU;AACd,QAAI,MAAM;AACV,WAAO,MAAM;AACX,YAAM,YAAY,MAAM;AACxB,UAAI,GAAG,WAAW,SAAS,GAAG;AAC5B,kBAAU,KAAK,YAAY,SAAS;AACpC;AAAA,MACF;AACA,UAAI,QAAQ,KAAK,WAAW,CAAC,IAAI,WAAW,KAAK,OAAO,EAAG;AAC3D,YAAM,SAAS,aAAa,GAAG;AAC/B,UAAI,WAAW,IAAK;AACpB,YAAM;AAAA,IACR;AACA,SAAK,aAAa,IAAI,UAAU,OAAO;AACvC,WAAO;AAAA,EACT;AAAA,EAEQ,YAAY,cAA0C;AAC5D,UAAM,SAAS,KAAK,cAAc,IAAI,YAAY;AAClD,QAAI,OAAQ,QAAO;AAEnB,QAAI,UAAU;AACd,UAAM,OAAOF,IAAG,eAAe,cAAcA,IAAG,IAAI,QAAQ;AAC5D,QAAI,KAAK,OAAO;AACd,WAAK,WAAW,YAAY;AAAA,IAC9B,OAAO;AACL,YAAM,SAASA,IAAG,2BAA2B,KAAK,QAAQA,IAAG,KAAKE,MAAK,QAAQ,YAAY,CAAC;AAG5F,UACE,OAAO,OAAO,KAAK,CAAC,MAAM,EAAE,aAAaF,IAAG,mBAAmB,SAAS,EAAE,SAAS,IAAI,GACvF;AACA,aAAK,WAAW,YAAY;AAAA,MAC9B;AACA,gBAAU;AAAA,QACR,GAAG,OAAO;AAAA,QACV,SAAS;AAAA,QACT,mBAAmB;AAAA;AAAA,QAEnB,kBACE,CAAC,OAAO,QAAQ,oBAChB,OAAO,QAAQ,qBAAqBA,IAAG,qBAAqB,UACxDA,IAAG,qBAAqB,UACxB,OAAO,QAAQ;AAAA,MACvB;AAAA,IACF;AACA,SAAK,cAAc,IAAI,cAAc,OAAO;AAC5C,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,cAA4B;AAC7C,QAAI,KAAK,cAAc,IAAI,YAAY,EAAG;AAC1C,SAAK,cAAc,IAAI,YAAY;AACnC,SAAK,SAAS;AAAA,MACZ,mBAAmB,QAAQE,MAAK,SAAS,KAAK,SAAS,YAAY,CAAC,CAAC;AAAA,IACvE;AAAA,EACF;AACF;AAEO,SAAS,cAAc,WAA2B;AACvD,QAAM,QAAQ,UAAU,MAAM,GAAG;AACjC,SAAO,UAAU,WAAW,GAAG,KAAK,MAAM,UAAU,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC;AAC7F;AAGO,SAAS,QAAQ,GAA+B;AACrD,MAAI,GAAG,WAAW,CAAC,KAAK,GAAG,SAAS,CAAC,EAAE,OAAO,EAAG,QAAO;AACxD,aAAW,OAAO,oBAAoB;AACpC,QAAI,GAAG,WAAW,IAAI,GAAG,EAAG,QAAO,IAAI;AAAA,EACzC;AACA,aAAW,OAAO,oBAAoB;AACpC,UAAM,MAAMA,MAAK,KAAK,GAAG,UAAU,GAAG;AACtC,QAAI,GAAG,WAAW,GAAG,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;;;AEhMA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,YAAY;AACrB,SAAS,SAAS,iBAAiB;AA0BnC,eAAsB,mBACpB,MACoD;AACpD,QAAM,WAAqB,CAAC;AAC5B,QAAM,QAAoB,CAAC;AAE3B,QAAM,UAAU,gBAAgBC,MAAK,KAAK,MAAM,cAAc,GAAG,QAAQ;AACzE,QAAM,KAAK,EAAE,MAAM,SAAS,QAAQ,KAAK,KAAK,MAAM,aAAa,WAAW,CAAC,EAAE,CAAC;AAChF,MAAI,CAAC,SAAS;AACZ,aAAS,KAAK,mEAAmE;AAAA,EACnF;AAEA,QAAM,QAAQ,eAAe,MAAM,OAAO;AAC1C,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,WAAW,MAAM;AAAA,MACrB,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,QAAQ,OAAO,EAAE,CAAC,eAAe;AAAA,MACvD,EAAE,KAAK,MAAM,QAAQ,CAAC,oBAAoB,GAAG,UAAU,KAAK;AAAA,IAC9D;AACA,eAAW,WAAW,SAAS,KAAK,GAAG;AACrC,YAAMC,OAAM,gBAAgB,SAAS,QAAQ;AAC7C,UAAI,CAACA,KAAK;AACV,YAAM,MAAM,QAAQD,MAAK,QAAQ,OAAO,CAAC;AACzC,YAAM,KAAK,EAAE,MAAMC,KAAI,QAAQ,QAAQD,MAAK,SAAS,MAAM,GAAG,CAAC,GAAG,KAAK,aAAaC,KAAI,CAAC;AAAA,IAC3F;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS;AAC3B;AAEA,SAAS,eAAe,MAAc,SAAgD;AACpF,QAAM,SAASD,MAAK,KAAK,MAAM,qBAAqB;AACpD,MAAIE,IAAG,WAAW,MAAM,GAAG;AACzB,QAAI;AACF,YAAM,SAAS,UAAUA,IAAG,aAAa,QAAQ,MAAM,CAAC;AACxD,UAAI,MAAM,QAAQ,QAAQ,QAAQ,EAAG,QAAO,OAAO,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC;AAAA,IAC9F,QAAQ;AAAA,IAER;AAAA,EACF;AACA,QAAM,KAAK,SAAS;AACpB,MAAI,MAAM,QAAQ,EAAE,EAAG,QAAO;AAC9B,MAAI,MAAM,MAAM,QAAQ,GAAG,QAAQ,EAAG,QAAO,GAAG;AAChD,SAAO,CAAC;AACV;AAEA,SAAS,gBAAgB,MAAc,UAAiD;AACtF,MAAI,CAACA,IAAG,WAAW,IAAI,EAAG,QAAO;AACjC,MAAI;AACF,WAAO,KAAK,MAAMA,IAAG,aAAa,MAAM,MAAM,CAAC;AAAA,EACjD,QAAQ;AACN,aAAS,KAAK,mBAAmB,QAAQ,IAAI,CAAC,8BAA8B;AAC5E,WAAO;AAAA,EACT;AACF;AAGO,SAAS,YAAY,OAAmB,MAAwB;AACrE,MAAI,OAAO,MAAM,CAAC;AAClB,aAAW,KAAK,OAAO;AACrB,SAAK,SAAS,EAAE,OAAO,KAAK,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,SAAS,KAAK,IAAI,QAAQ;AACtF,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,EAAE,SAAS,KAAK,OAAO,KAAK,WAAW,KAAK,MAAM,GAAG,GAAI,QAAO,MAAM,CAAC;AAC3E,SAAO;AACT;;;AC1FA,OAAOC,WAAU;;;ACDjB,IAAM,YACJ;AAEK,SAAS,gBAAgB,MAAwB;AACtD,QAAM,OAAiB,CAAC;AACxB,aAAW,SAAS,KAAK,SAAS,SAAS,GAAG;AAC5C,SAAK,KAAK,MAAM,CAAC,CAAE;AAAA,EACrB;AACA,SAAO;AACT;;;ADoBA,IAAM,aAAa,CAAC,QAAQ,SAAS,OAAO,OAAO,UAAU,OAAO;AAEpE,IAAM,eAAe;AAEd,SAAS,WAAW,SAA0B;AACnD,SAAO,aAAa,KAAK,OAAO;AAClC;AAEA,IAAM,iBAAiB;AAEhB,SAAS,oBACd,MACA,cACA,UACc;AACd,QAAM,UAAwB,CAAC;AAC/B,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAMC,OAAM,KAAK;AAEjB,QAAM,MAAM,CAAC,MAAc,QAAqB,QAAiB,QAAiB;AAChF,QAAI,CAAC,KAAK,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,GAAG;AAC7C,WAAK,IAAI,IAAI;AACb,cAAQ,KAAK,EAAE,MAAM,QAAQ,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC,GAAI,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAAA,IACvF;AAAA,EACF;AAEA,QAAM,SAAS,CAAC,KAAa,QAAqB,WAAoB;AACpE,UAAM,WAAW,gBAAgB,KAAK,KAAK,KAAK,YAAY;AAC5D,QAAI,UAAU;AACZ,UAAI,UAAU,QAAQ,MAAM;AAAA,IAC9B,WAAW,CAAC,QAAQ,UAAU,OAAO,SAAS,EAAE,SAAS,MAAM,GAAG;AAChE,eAAS;AAAA,QACP,UAAU,GAAG,QAAQ,KAAK,IAAI;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAOA,KAAI,SAAS,SAAU,QAAOA,KAAI,MAAM,MAAM;AACzD,MAAI,OAAOA,KAAI,WAAW,SAAU,QAAOA,KAAI,QAAQ,QAAQ;AAC/D,MAAI,OAAOA,KAAI,YAAY,SAAU,QAAOA,KAAI,SAAS,SAAS;AAClE,MAAI,OAAOA,KAAI,QAAQ,SAAU,QAAOA,KAAI,KAAK,KAAK;AAAA,WAC7CA,KAAI,OAAO,OAAOA,KAAI,QAAQ,UAAU;AAC/C,eAAW,UAAU,OAAO,OAAOA,KAAI,GAAG,EAAG,QAAO,QAAQ,KAAK;AAAA,EACnE;AACA,aAAW,UAAU,eAAeA,KAAI,OAAO,EAAG,QAAO,QAAQ,SAAS;AAG1E,aAAW,CAAC,YAAY,OAAO,KAAK,OAAO,QAAQA,KAAI,WAAW,CAAC,CAAC,GAAG;AACrE,eAAW,OAAO,gBAAgB,OAAO,GAAG;AAC1C,aAAO,KAAK,UAAU,wBAAwB,UAAU,GAAG;AAAA,IAC7D;AAAA,EACF;AAGA,QAAM,OAAO,EAAE,GAAGA,KAAI,cAAc,GAAGA,KAAI,gBAAgB;AAC3D,MAAI,KAAK,MAAM,GAAG;AAChB,eAAW,QAAQ,cAAc;AAC/B,YAAM,MAAM,MAAM,KAAK,KAAK,IAAI;AAChC,UAAI,OAAO,qCAAqC,KAAK,GAAG;AACtD,YAAI,MAAM,aAAa,0BAA0B;AACnD,UAAI,OAAO,8BAA8B,KAAK,GAAG;AAC/C,YAAI,MAAM,aAAa,oBAAoB;AAAA,IAC/C;AAAA,EACF;AACA,MAAI,KAAK,cAAc,GAAG;AACxB,UAAM,OAAO,QAAQC,MAAK,KAAK,KAAK,KAAK,UAAU,CAAC;AACpD,QAAI,KAAM,KAAI,QAAQ,IAAI,GAAG,aAAa,kBAAkB;AAAA,EAC9D;AAGA,aAAW,QAAQ,cAAc;AAC/B,UAAM,MAAM,MAAM,KAAK,KAAK,IAAI;AAChC,QAAI,OAAO,CAAC,IAAI,SAAS,GAAG,KAAK,eAAe,KAAK,GAAG,GAAG;AACzD,UAAI,MAAM,UAAU,yBAAyB;AAAA,IAC/C;AAAA,EACF;AAIA,aAAW,QAAQ,cAAc;AAC/B,UAAM,MAAM,MAAM,KAAK,KAAK,IAAI;AAChC,QAAI,OAAO,WAAW,GAAG,EAAG,KAAI,MAAM,QAAQ,QAAW,MAAM;AAAA,EACjE;AAEA,SAAO;AACT;AAUO,SAAS,gBACd,SACA,KACA,cACoB;AACpB,QAAM,SAAS,CAAC,MAA8C;AAC5D,QAAI,CAAC,EAAG,QAAO;AACf,UAAM,QAAQ,QAAQ,CAAC;AACvB,WAAO,CAAC,gBAAgB,aAAa,IAAI,KAAK,IAAI,QAAQ;AAAA,EAC5D;AAEA,QAAM,QAAQ,IAAI,QAAQ,SAAS,EAAE;AACrC,QAAM,SAAS,OAAO,QAAQA,MAAK,KAAK,SAAS,KAAK,CAAC,CAAC;AACxD,MAAI,OAAQ,QAAO;AAEnB,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAM,QAAQ,MAAM,CAAC;AACrB,MAAI,WAAW,SAAS,KAAK,GAAG;AAC9B,UAAM,OAAO,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AACpC,UAAM,WAAW,KAAK,QAAQ,yBAAyB,EAAE;AACzD,eAAW,QAAQ,CAAC,OAAO,QAAQ,IAAI,QAAQ,GAAG;AAChD,YAAM,MAAM,OAAO,QAAQA,MAAK,KAAK,SAAS,IAAI,CAAC,CAAC;AACpD,UAAI,IAAK,QAAO;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,eAAe,KAAwB;AAC9C,QAAM,MAAgB,CAAC;AACvB,QAAM,OAAO,CAAC,UAAyB;AACrC,QAAI,OAAO,UAAU,UAAU;AAC7B,UAAI,CAAC,MAAM,SAAS,OAAO,EAAG,KAAI,KAAK,KAAK;AAAA,IAC9C,WAAW,SAAS,OAAO,UAAU,UAAU;AAC7C,iBAAW,KAAK,OAAO,OAAO,KAAK,EAAG,MAAK,CAAC;AAAA,IAC9C;AAAA,EACF;AACA,OAAK,GAAG;AACR,SAAO;AACT;AAEA,SAAS,MAAM,KAAa,MAAkC;AAC5D,SAAO,KAAK,WAAW,MAAM,GAAG,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI;AACnE;;;AEzKA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAMV,SAAS,cAAc,SAA0B;AACtD,SAAO,yCAAyC,KAAK,OAAO;AAC9D;AAEO,SAAS,aAAa,MAAc,aAAuC;AAChF,QAAM,UAA4B,CAAC;AACnC,QAAM,OAAOC,IAAG,aAAaC,MAAK,KAAK,MAAM,WAAW,GAAG,MAAM;AACjE,aAAW,WAAW,KAAK,MAAM,OAAO,GAAG;AACzC,UAAM,OAAO,QAAQ,KAAK;AAC1B,QAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,EAAG;AACnC,UAAM,SAAS,KAAK,MAAM,KAAK;AAE/B,UAAM,WAAW,KAAK,WAAW,GAAG,IAAI,OAAO,CAAC,IAAK,OAAO,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG;AAChF,eAAW,OAAO,gBAAgB,IAAI,GAAG;AACvC,YAAM,WAAW,QAAQA,MAAK,QAAQ,MAAM,GAAG,CAAC;AAChD,UAAI,UAAU;AACZ,gBAAQ,KAAK;AAAA,UACX,MAAM,QAAQ,QAAQ;AAAA,UACtB,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,SAAS,QAAQ,UAAU,GAAG;AAAA,QACxC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACjCA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,SAASC,kBAAiB;AAiB5B,SAAS,oBACd,MACA,aACA,UACkB;AAClB,QAAM,UAA4B,CAAC;AACnC,MAAI;AACJ,MAAI;AACF,UAAMC,WAAUC,IAAG,aAAaC,MAAK,KAAK,MAAM,WAAW,GAAG,MAAM,CAAC;AAAA,EACvE,QAAQ;AACN,aAAS,KAAK,4BAA4B,WAAW,4BAA4B;AACjF,WAAO;AAAA,EACT;AACA,aAAW,CAAC,SAAS,GAAG,KAAK,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,GAAG;AAC5D,eAAW,QAAQ,KAAK,SAAS,CAAC,GAAG;AACnC,UAAI,OAAO,MAAM,QAAQ,SAAU;AACnC,iBAAW,OAAO,gBAAgB,KAAK,GAAG,GAAG;AAC3C,cAAM,WAAW,QAAQA,MAAK,QAAQ,MAAM,GAAG,CAAC;AAChD,YAAI,UAAU;AACZ,kBAAQ,KAAK;AAAA,YACX,MAAM,QAAQ,QAAQ;AAAA,YACtB,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,uBAAuB,OAAO,UAAU,GAAG;AAAA,UACrD,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACjDA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,yBAAyB;AAW3B,SAAS,iBACd,MACA,aACA,UACkB;AAClB,QAAM,UAA4B,CAAC;AACnC,MAAI;AACJ,MAAI;AACF,WAAO,kBAAkBC,IAAG,aAAaC,MAAK,KAAK,MAAM,WAAW,GAAG,MAAM,CAAC;AAAA,EAChF,QAAQ;AACN,aAAS,KAAK,wBAAwB,WAAW,4BAA4B;AAC7E,WAAO;AAAA,EACT;AACA,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,KAAK,OAAO;AACxB,QAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,CAAC,IAAI,YAAY,KAAK,CAAC,IAAI,MAAM,EAAG;AAC3E,UAAM,OAAO,OAAO,IAAI,MAAM,CAAC;AAC/B,eAAW,aAAa,aAAa,GAAG,GAAG;AACzC,YAAM,MAAM,CAAC,GAAI,UAAU,WAAW,CAAC,GAAI,GAAI,UAAU,QAAQ,CAAC,CAAE,EACjE,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,EAChD,KAAK,GAAG;AACX,iBAAW,OAAO,gBAAgB,GAAG,GAAG;AACtC,cAAM,WAAW,QAAQA,MAAK,QAAQ,MAAM,GAAG,CAAC;AAChD,YAAI,UAAU;AACZ,kBAAQ,KAAK;AAAA,YACX,MAAM,QAAQ,QAAQ;AAAA,YACtB,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,OAAO,IAAI,mBAAmB,GAAG;AAAA,UAC3C,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,aAAa,KAA2B;AAC/C,QAAM,MAAmB,CAAC;AAC1B,QAAM,OAAO,CAAC,UAAyB;AACrC,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,KAAK,MAAO,MAAK,CAAC;AAAA,IAC/B,WAAW,SAAS,OAAO,UAAU,UAAU;AAC7C,YAAM,MAAM;AACZ,UAAI,MAAM,QAAQ,IAAI,YAAY,CAAC,GAAG;AACpC,mBAAW,KAAK,IAAI,YAAY,GAAG;AACjC,cAAI,KAAK,OAAO,MAAM,SAAU,KAAI,KAAK,CAAc;AAAA,QACzD;AAAA,MACF;AACA,iBAAW,KAAK,OAAO,OAAO,GAAG,EAAG,MAAK,CAAC;AAAA,IAC5C;AAAA,EACF;AACA,OAAK,GAAG;AACR,SAAO;AACT;;;ACpEA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,SAASC,kBAAiB;AAM5B,SAAS,gBAAgB,MAAc,aAAuC;AACnF,QAAM,UAA4B,CAAC;AACnC,QAAM,OAAOC,IAAG,aAAaC,MAAK,KAAK,MAAM,WAAW,GAAG,MAAM;AACjE,aAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACtC,UAAM,IAAI,gCAAgC,KAAK,IAAI;AACnD,QAAI,CAAC,EAAG;AAER,QAAI,UAAU,EAAE,CAAC,EAAG,KAAK;AACzB,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,OAAO;AAC9B,kBAAU,IAAI,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,EAAE,KAAK,GAAG;AAAA,MAC1E,QAAQ;AAAA,MAER;AAAA,IACF;AACA,eAAW,OAAO,gBAAgB,OAAO,GAAG;AAC1C,YAAM,WAAW,QAAQA,MAAK,QAAQ,MAAM,GAAG,CAAC;AAChD,UAAI,UAAU;AACZ,gBAAQ,KAAK;AAAA,UACX,MAAM,QAAQ,QAAQ;AAAA,UACtB,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,cAAc,EAAE,CAAC,EAAG,YAAY,CAAC,SAAS,GAAG;AAAA,QACvD,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,gBACd,MACA,aACA,UACkB;AAClB,QAAM,UAA4B,CAAC;AACnC,MAAI;AACJ,MAAI;AACF,UAAMC,WAAUF,IAAG,aAAaC,MAAK,KAAK,MAAM,WAAW,GAAG,MAAM,CAAC;AAAA,EACvE,QAAQ;AACN,aAAS,KAAK,mBAAmB,WAAW,6BAA6B;AACzE,WAAO;AAAA,EACT;AACA,aAAW,CAAC,QAAQ,EAAE,KAAK,OAAO,QAAQ,KAAK,aAAa,CAAC,CAAC,GAAG;AAC/D,QAAI,OAAO,IAAI,YAAY,SAAU;AAErC,UAAM,WAAW,GAAG,QAAQ,MAAM,GAAG,GAAG,QAAQ,YAAY,GAAG,CAAC;AAChE,UAAM,WAAW,QAAQA,MAAK,QAAQ,MAAM,QAAQ,CAAC;AACrD,QAAI,UAAU;AACZ,cAAQ,KAAK;AAAA,QACX,MAAM,QAAQ,QAAQ;AAAA,QACtB,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,wBAAwB,MAAM;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,mBAAmB,MAAc,aAAuC;AACtF,QAAM,UAA4B,CAAC;AACnC,QAAM,OAAOD,IAAG,aAAaC,MAAK,KAAK,MAAM,WAAW,GAAG,MAAM;AACjE,QAAM,aAAa,uDAAuD,KAAK,IAAI;AACnF,MAAI,CAAC,WAAY,QAAO;AACxB,aAAW,OAAO,WAAW,CAAC,EAAG,SAAS,mBAAmB,GAAG;AAC9D,UAAM,WAAW,QAAQA,MAAK,QAAQ,MAAM,IAAI,CAAC,CAAE,CAAC;AACpD,QAAI,UAAU;AACZ,cAAQ,KAAK;AAAA,QACX,MAAM,QAAQ,QAAQ;AAAA,QACtB,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;;;AC9EA,SAAS,KAAK,IAAY,QAAgB,aAAiC;AACzE,SAAO,EAAE,IAAI,QAAQ,UAAU,WAAW,QAAQ,QAAQ,YAAY;AACxE;AACA,SAAS,MAAM,IAAY,QAAgB,aAAiC;AAC1E,SAAO,EAAE,IAAI,QAAQ,UAAU,WAAW,SAAS,QAAQ,CAAC,KAAK,IAAI,MAAM,GAAG,YAAY;AAC5F;AAEA,IAAM,cAA4B;AAAA;AAAA;AAAA,EAGhC,KAAK,2BAA2B,IAAI,4CAA4C;AAAA,EAChF,KAAK,8BAA8B,IAAI,wDAAwD;AAAA,EAC/F,KAAK,4BAA4B,IAAI,uCAAuC;AAAA,EAC5E,KAAK,2BAA2B,IAAI,2DAA2D;AAAA;AAAA,EAG/F,KAAK,2BAA2B,IAAI,oBAAoB;AAAA,EACxD,KAAK,0BAA0B,IAAI,mCAAmC;AAAA,EACtE,KAAK,8BAA8B,IAAI,gCAAgC;AAAA,EACvE,KAAK,+BAA+B,IAAI,sDAAsD;AAAA,EAC9F,KAAK,mCAAmC,IAAI,6CAA6C;AAAA,EACzF;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA;AAAA,EAGA;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,MAAM,0BAA0B,IAAI,iDAAiD;AAAA,EACrF,MAAM,2BAA2B,IAAI,qCAAqC;AAAA,EAC1E,MAAM,2BAA2B,IAAI,qCAAqC;AAAA,EAC1E,MAAM,6BAA6B,IAAI,+CAA+C;AAAA,EACtF,MAAM,2BAA2B,IAAI,gDAAgD;AAAA,EACrF;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,MAAM,8BAA8B,IAAI,wCAAwC;AAAA,EAChF;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,MAAM,+BAA+B,IAAI,+CAA+C;AAAA,EACxF;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA;AAAA;AAAA,EAIA;AAAA,IACE,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AACF;AAEO,IAAM,UAA2C,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAG1F,IAAM,eAAgD;AAAA,EAC3D,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,cAAc;AAChB;AAOO,IAAM,cAA+C;AAAA,EAC1D,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,oBAAoB;AACtB;AAEO,IAAM,oBAAoB;AAG1B,SAAS,YAAY,UAAkB,QAAgB,UAAqC;AACjG,QAAM,OAAO,QAAQ,IAAI,QAAQ;AACjC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,sBAAsB,QAAQ,EAAE;AAAA,EAClD;AACA,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,QAAQ,KAAK;AAAA,IACb,WAAW,KAAK;AAAA,IAChB,QAAQ,KAAK;AAAA,IACb;AAAA,IACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,EACjC;AACF;;;AC1CO,SAAS,UAAU,QAA+B;AACvD,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,SAAS,OAAO,SAAS,IAAI,OAAO,MAAM,IAAI,OAAO,IAAI;AAAA,IAClE,KAAK;AACH,aAAO,UAAU,OAAO,IAAI,IAAI,OAAO,MAAM;AAAA,IAC/C,KAAK;AACH,aAAO,cAAc,OAAO,OAAO,IAAI,OAAO,IAAI;AAAA,IACpD,KAAK;AACH,aAAO,QAAQ,OAAO,IAAI;AAAA,EAC9B;AACF;AAEO,SAAS,eAAe,QAA+B;AAC5D,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,GAAG,OAAO,MAAM,IAAI,OAAO,IAAI;AAAA,IACxC,KAAK;AACH,aAAO,WAAW,OAAO,MAAM,QAAQ,OAAO,IAAI;AAAA,IACpD,KAAK;AACH,aAAO,GAAG,OAAO,IAAI,KAAK,OAAO,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,OAAO;AAAA,EAClB;AACF;;;AC9HA,SAAS,kBAAkB;AAGpB,SAAS,YAAY,OAAyB;AACnD,SAAO,WAAW,QAAQ,EAAE,OAAO,MAAM,KAAK,GAAG,CAAC,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC/E;;;ACuDO,SAAS,YACd,UACA,QACA,UACA,WACA,YACS;AACT,SAAO;AAAA,IACL,IAAI,SAAS,UAAU,MAAM,GAAG,SAAS;AAAA,IACzC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,CAAC,YAAY,aAAa,QAAQ,GAAG,UAAU,CAAC;AAAA,IAC1D,YAAY,EAAE,OAAO,GAAG,OAAO,MAAM;AAAA,EACvC;AACF;;;ACxEO,IAAM,mBAA6B;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ,MAAM;AAAA,EAEd,QAAQ,KAAkC;AACxC,UAAM,WAAW,CAAC;AAClB,UAAM,aAAa,IAAI,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC7D,UAAM,aAAa,IAAI,YAAY,OAAO,CAAC,MAAM,EAAE,QAAQ,MAAM,EAAE;AAEnE,eAAW,QAAQ,IAAI,UAAU,GAAG;AAClC,UAAI,WAAW,IAAI,IAAI,EAAG;AAC1B,YAAM,MAAM,IAAI,IAAI,IAAI;AAExB,UAAI,CAAC,IAAI,MAAM,IAAI,IAAI,IAAI,GAAG;AAC5B,iBAAS;AAAA,UACP;AAAA,YACE;AAAA,YACA,EAAE,MAAM,QAAQ,MAAM,IAAI;AAAA,YAC1B,EAAE,MAAM,KAAK,MAAM,EAAE;AAAA,YACrB,IAAI,KAAK;AAAA,YACT,qDAAqD,UAAU;AAAA,UACjE;AAAA,QACF;AAAA,MACF,WAAW,CAAC,IAAI,MAAM,KAAK,IAAI,IAAI,GAAG;AAEpC,cAAM,UAAU;AAAA,UACd;AAAA,UACA,EAAE,MAAM,QAAQ,MAAM,IAAI;AAAA,UAC1B,EAAE,MAAM,KAAK,MAAM,EAAE;AAAA,UACrB,IAAI,KAAK;AAAA,UACT;AAAA,QACF;AACA,gBAAQ,SAAS;AAAA,UACf,YAAY,8BAA8B,6CAA6C;AAAA,QACzF;AACA,iBAAS,KAAK,OAAO;AAAA,MACvB;AAAA,IACF;AAEA,WAAO,EAAE,SAAS;AAAA,EACpB;AACF;;;ACxCO,IAAM,gBAA0B;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ,MAAM;AAAA,EAEd,QAAQ,KAAkC;AACxC,UAAM,WAAW,CAAC;AAClB,UAAM,aAAa,IAAI,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC7D,UAAM,mBAAmB,IAAI;AAAA,MAC3B,IAAI,YAAY,OAAO,CAAC,MAAM,EAAE,QAAQ,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IACnE;AAEA,eAAW,QAAQ,IAAI,UAAU,GAAG;AAGlC,UAAI,WAAW,IAAI,IAAI,EAAG;AAC1B,UAAI,CAAC,IAAI,MAAM,IAAI,IAAI,IAAI,EAAG;AAC9B,YAAM,MAAM,IAAI,IAAI,IAAI;AACxB,UAAI,WAAW,GAAG,EAAG;AAErB,YAAM,KAAK,IAAI,MAAM,MAAM,IAAI,IAAI;AACnC,YAAM,YAAY,oBAAI,IAAY;AAClC,iBAAW,OAAO,GAAG,SAAS;AAC5B,YAAI,UAAU,IAAI,IAAI,IAAI,EAAG;AAC7B,kBAAU,IAAI,IAAI,IAAI;AACtB,YAAI,IAAI,MAAM,aAAa,MAAM,IAAI,IAAI,EAAG;AAE5C,cAAM,UAAU;AAAA,UACd;AAAA,UACA,EAAE,MAAM,UAAU,QAAQ,IAAI,MAAM,MAAM,IAAI;AAAA,UAC9C,EAAE,MAAM,KAAK,MAAM,IAAI,KAAK;AAAA,UAC5B,IAAI,KAAK;AAAA,UACT,IAAI,SAAS,SACT,gBAAgB,IAAI,IAAI,wBACxB,IAAI,IAAI,IAAI;AAAA,QAClB;AACA,YAAI,IAAI,YAAY;AAClB,kBAAQ,SAAS;AAAA,YACf,YAAY,2BAA2B,IAAI,IAAI,IAAI,yBAAyB;AAAA,UAC9E;AAAA,QACF;AAGA,YAAI,IAAI,MAAM,oBAAoB,MAAM,IAAI,MAAM,gBAAgB,GAAG;AACnE,kBAAQ,SAAS;AAAA,YACf;AAAA,cACE;AAAA,cACA,IAAI,IAAI,IAAI;AAAA,YACd;AAAA,UACF;AAAA,QACF;AACA,YAAI,GAAG,qBAAqB;AAG1B,kBAAQ,SAAS;AAAA,YACf;AAAA,cACE;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA,iBAAS,KAAK,OAAO;AAAA,MACvB;AAAA,IACF;AAEA,WAAO,EAAE,SAAS;AAAA,EACpB;AACF;;;ACvEA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AAOV,IAAM,aAAuB;AAAA,EAClC,MAAM;AAAA,EACN,QAAQ,CAAC,SACP,OAAO,KAAK,KAAK,YAAY,gBAAgB,CAAC,CAAC,EAAE,SAAS,KAC1D,OAAO,KAAK,KAAK,YAAY,mBAAmB,CAAC,CAAC,EAAE,SAAS;AAAA,EAE/D,QAAQ,KAAkC;AACxC,UAAM,WAAW,CAAC;AAClB,UAAM,OAAO,aAAa,GAAG;AAC7B,UAAM,aAAa,IAAI,IAAI,GAAG,IAAI,KAAK,GAAG,eAAe;AACzD,UAAM,YAAY,iBAAiB,IAAI,KAAK,GAAG;AAE/C,eAAW,WAAW,CAAC,gBAAgB,iBAAiB,GAAY;AAClE,iBAAW,QAAQ,OAAO,KAAK,IAAI,KAAK,YAAY,OAAO,KAAK,CAAC,CAAC,GAAG;AACnE,YAAI,KAAK,IAAI,IAAI,EAAG;AAEpB,cAAM,UAAU;AAAA,UACd;AAAA,UACA,EAAE,MAAM,cAAc,MAAM,QAAQ;AAAA,UACpC,EAAE,MAAM,YAAY,MAAM,UAAU,IAAI,IAAI,KAAK,EAAE;AAAA,UACnD,IAAI,KAAK;AAAA,UACT,IAAI,IAAI,oBAAoB,OAAO;AAAA,QACrC;AAKA,YAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,gBAAM,UAAU,kBAAkB,IAAI;AACtC,cAAI,YAAY,UAAU,KAAK,IAAI,OAAO,GAAG;AAC3C,oBAAQ,SAAS;AAAA,cACf;AAAA,gBACE;AAAA,gBACA,yBAAyB,OAAO;AAAA,cAClC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA,iBAAS,KAAK,OAAO;AAAA,MACvB;AAAA,IACF;AAEA,WAAO,EAAE,SAAS;AAAA,EACpB;AACF;AAGA,SAAS,aAAa,KAA+B;AACnD,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,IAAI,MAAM,MAAM,KAAK,GAAG;AACzC,QAAI,CAAC,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAG;AAClC,UAAM,KAAK,IAAI,MAAM,MAAM,IAAI,IAAI;AACnC,eAAW,OAAO,GAAG,SAAS;AAC5B,UAAI,IAAI,iBAAiB;AACvB,aAAK,IAAI,IAAI,eAAe;AAAA,MAC9B,WAAW,CAAC,IAAI,UAAU,WAAW,GAAG,KAAK,CAAC,IAAI,UAAU,WAAW,OAAO,GAAG;AAG/E,aAAK,IAAI,cAAc,IAAI,SAAS,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,kBAAkB,cAA8B;AACvD,QAAM,OAAO,aAAa,MAAM,UAAU,MAAM;AAChD,SAAO,KAAK,SAAS,IAAI,IAAI,IAAI,KAAK,QAAQ,MAAM,GAAG,CAAC,KAAK;AAC/D;AAGA,SAAS,iBAAiB,SAAsC;AAC9D,QAAM,QAAQ,oBAAI,IAAoB;AACtC,MAAI;AACF,UAAM,OAAOC,IAAG,aAAaC,MAAK,KAAK,SAAS,cAAc,GAAG,MAAM;AACvE,SAAK,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,MAAM;AACvC,YAAM,IAAI,qCAAqC,KAAK,IAAI;AACxD,UAAI,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAE,EAAG,OAAM,IAAI,EAAE,CAAC,GAAI,IAAI,CAAC;AAAA,IACpD,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AACA,SAAO;AACT;;;AClFA,OAAOC,SAAQ;AAQf,IAAM,eAAe,oBAAI,IAAI,CAAC,OAAO,QAAQ,OAAO,SAAS,UAAU,OAAO,QAAQ,SAAS,CAAC;AAChG,IAAM,yBAAyB,oBAAI,IAAI,CAAC,OAAO,UAAU,UAAU,OAAO,SAAS,CAAC;AACpF,IAAM,qBAAqB,oBAAI,IAAI,CAAC,WAAW,WAAW,WAAW,QAAQ,CAAC;AAQ9E,IAAM,2BAA2B;AAgB1B,IAAM,gBAA0B;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ,CAAC,SAAS;AAChB,UAAM,OAAO,EAAE,GAAG,KAAK,YAAY,cAAc,GAAG,KAAK,YAAY,gBAAgB;AACrF,WAAO,QAAQ,KAAK,SAAS,KAAK,KAAK,SAAS,CAAC;AAAA,EACnD;AAAA,EAEA,QAAQ,KAAkC;AACxC,UAAM,gBAA4B,CAAC;AACnC,UAAM,SAAkB,CAAC;AAEzB,eAAW,QAAQ,IAAI,UAAU,GAAG;AAClC,UAAI,WAAW,IAAI,IAAI,IAAI,CAAC,EAAG;AAC/B,YAAM,KAAK,IAAI,MAAM,MAAM,IAAI,IAAI;AACnC,sBAAgB,IAAI,eAAe,MAAM;AAAA,IAC3C;AAGA,UAAM,uBAAuB,oBAAI,IAAoB;AACrD,UAAM,eAAe,oBAAI,IAAoB;AAC7C,eAAW,SAAS,QAAQ;AAC1B,YAAM,KAAK,IAAI,MAAM,MAAM,IAAI,MAAM,IAAI;AACzC,YAAM,WAAW,GAAG,QAAQ;AAAA,QAC1B,CAAC,MACC,EAAE,iBACD,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,MAAM,SAAS,KAC9C,EAAE,mBAAmB,MAAM;AAAA,MACjC;AACA,UAAI,UAAU,cAAc;AAC1B,YAAI,CAAC,aAAa,IAAI,SAAS,YAAY,GAAG;AAC5C,uBAAa,IAAI,SAAS,cAAc,MAAM,MAAM;AAAA,QACtD;AAAA,MACF,WAAW,CAAC,qBAAqB,IAAI,GAAG,MAAM,IAAI,IAAI,MAAM,SAAS,EAAE,GAAG;AACxE,6BAAqB,IAAI,GAAG,MAAM,IAAI,IAAI,MAAM,SAAS,IAAI,MAAM,MAAM;AAAA,MAC3E;AAAA,IACF;AAGA,UAAM,aAAa,IAAI,IAAI,cAAc,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3D,UAAM,iBAAoD,CAAC;AAC3D,eAAW,CAAC,MAAM,EAAE,KAAK,IAAI,MAAM,OAAO;AACxC,UAAI,WAAW,IAAI,IAAI,EAAG;AAC1B,iBAAW,OAAO,GAAG,aAAc,gBAAe,KAAK,EAAE,OAAO,IAAI,OAAO,KAAK,CAAC;AAAA,IACnF;AACA,UAAM,qBAAqB,eAAe,UAAU;AAEpD,UAAM,WAAsB,CAAC;AAC7B,UAAM,OAAO,oBAAI,IAAY;AAC7B,UAAM,YAAY,YAAY,GAAG;AAEjC,eAAW,OAAO,eAAe;AAC/B,YAAM,SACJ,qBAAqB,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,QAAQ,EAAE,KAAK,aAAa,IAAI,IAAI,IAAI,KAAK;AAC3F,YAAM,WAAW,cAAc,QAAQ,IAAI,IAAI;AAC/C,YAAM,SAAS,IAAI,OAAO,YAAY;AACtC,YAAM,MAAM,GAAG,MAAM,IAAI,QAAQ,IAAI,IAAI,IAAI;AAC7C,UAAI,KAAK,IAAI,GAAG,EAAG;AACnB,WAAK,IAAI,GAAG;AAEZ,YAAM,MAAM,IAAI,IAAI,IAAI,IAAI;AAC5B,YAAM,UAAU;AAAA,QACd;AAAA,QACA,EAAE,MAAM,SAAS,QAAQ,MAAM,UAAU,UAAU;AAAA,QACnD,EAAE,MAAM,KAAK,MAAM,IAAI,KAAK;AAAA,QAC5B,IAAI,KAAK;AAAA,QACT,GAAG,MAAM,IAAI,QAAQ;AAAA,MACvB;AAEA,UAAI,WAAW,aAAa;AAC1B,gBAAQ,SAAS;AAAA,UACf;AAAA,YACE;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG;AAEhC,gBAAQ,SAAS;AAAA,UACf;AAAA,YACE;AAAA,YACA,GAAG,GAAG;AAAA,UACR;AAAA,QACF;AAAA,MACF,WAAW,sBAAsB,CAAC,SAAS,WAAW,WAAW,GAAG;AAClE,cAAM,QAAQ,cAAc,UAAU,cAAc;AACpD,YAAI,OAAO;AACT,kBAAQ,SAAS;AAAA,YACf;AAAA,cACE;AAAA,cACA,IAAI,MAAM,KAAK,QAAQ,IAAI,IAAI,MAAM,IAAI,CAAC;AAAA,YAC5C;AAAA,UACF;AAAA,QACF,OAAO;AACL,kBAAQ,SAAS;AAAA,YACf;AAAA,cACE;AAAA,cACA,WAAW,eAAe,MAAM;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,eAAS,KAAK,OAAO;AAAA,IACvB;AAEA,WAAO,EAAE,UAAU,SAAS,EAAE,QAAQ,KAAK,KAAK,EAAE;AAAA,EACpD;AACF;AAEA,SAAS,YAAY,KAAyC;AAC5D,QAAM,OAAO,EAAE,GAAG,IAAI,KAAK,YAAY,cAAc,GAAG,IAAI,KAAK,YAAY,gBAAgB;AAC7F,SAAO,KAAK,SAAS,KAAK,CAAC,KAAK,SAAS,IAAI,YAAY;AAC3D;AAEA,SAAS,gBAAgB,IAAgB,eAA2B,QAAuB;AAEzF,QAAM,YAAY,IAAI,IAAY,sBAAsB;AACxD,QAAM,OAAO,CAAC,SAAwB;AACpC,QACEC,IAAG,sBAAsB,IAAI,KAC7BA,IAAG,aAAa,KAAK,IAAI,KACzB,KAAK,eACLA,IAAG,iBAAiB,KAAK,WAAW,GACpC;AACA,YAAM,SAAS,KAAK,YAAY;AAChC,YAAM,YACHA,IAAG,aAAa,MAAM,KAAK,mBAAmB,IAAI,OAAO,IAAI,KAC7DA,IAAG,2BAA2B,MAAM,KAAK,OAAO,KAAK,SAAS;AACjE,UAAI,UAAW,WAAU,IAAI,KAAK,KAAK,IAAI;AAAA,IAC7C;AACA,IAAAA,IAAG,aAAa,MAAM,IAAI;AAAA,EAC5B;AACA,EAAAA,IAAG,aAAa,GAAG,KAAK,IAAI;AAE5B,QAAM,SAAS,CAAC,SACd,GAAG,IAAI,8BAA8B,KAAK,SAAS,GAAG,GAAG,CAAC,EAAE,OAAO;AAErE,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAIA,IAAG,iBAAiB,IAAI,KAAKA,IAAG,2BAA2B,KAAK,UAAU,GAAG;AAC/E,YAAM,aAAa,KAAK,WAAW,KAAK;AACxC,YAAM,OAAO,KAAK,WAAW;AAI7B,UAAI,aAAa,IAAI,UAAU,GAAG;AAChC,cAAM,WAAW,cAAc,IAAI;AACnC,YAAI,UAAU;AACZ,cAAI,SAAS,YAAY,UAAU,IAAI,SAAS,QAAQ,GAAG;AACzD,0BAAc,KAAK;AAAA,cACjB,QAAQ;AAAA,cACR,MAAM,SAAS;AAAA,cACf,UAAU,SAAS;AAAA,cACnB,MAAM,OAAO,IAAI;AAAA,cACjB,MAAM,GAAG;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF,WAAWA,IAAG,aAAa,IAAI,KAAK,UAAU,IAAI,KAAK,IAAI,GAAG;AAC5D,gBAAM,OAAO,KAAK,UAAU,CAAC;AAC7B,cACE,SACCA,IAAG,gBAAgB,IAAI,KAAKA,IAAG,gCAAgC,IAAI,MACpE,KAAK,UAAU,UAAU,KACzB,KAAK,UAAU,MAAM,CAAC,EAAE,KAAK,YAAY,GACzC;AACA,0BAAc,KAAK;AAAA,cACjB,QAAQ;AAAA,cACR,MAAM,KAAK;AAAA,cACX,UAAU,KAAK;AAAA,cACf,MAAM,OAAO,IAAI;AAAA,cACjB,MAAM,GAAG;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAGA,UAAI,eAAe,WAAWA,IAAG,aAAa,IAAI,KAAK,UAAU,IAAI,KAAK,IAAI,GAAG;AAC/E,cAAM,OAAO,KAAK,UAAU,CAAC;AAC7B,YAAI,QAAQA,IAAG,0BAA0B,IAAI,GAAG;AAC9C,gBAAM,MAAM,CAAC,SAAqC;AAChD,uBAAW,KAAK,KAAK,YAAY;AAC/B,kBACEA,IAAG,qBAAqB,CAAC,KACzBA,IAAG,aAAa,EAAE,IAAI,KACtB,EAAE,KAAK,SAAS,SACfA,IAAG,gBAAgB,EAAE,WAAW,KAC/BA,IAAG,gCAAgC,EAAE,WAAW,IAClD;AACA,uBAAO,EAAE,YAAY;AAAA,cACvB;AAAA,YACF;AACA,mBAAO;AAAA,UACT;AACA,gBAAM,MAAM,IAAI,KAAK,KAAK,IAAI,MAAM;AACpC,gBAAM,SAAS,IAAI,QAAQ;AAC3B,cAAI,OAAO,QAAQ;AACjB,0BAAc,KAAK;AAAA,cACjB,QAAQ,OAAO,YAAY;AAAA,cAC3B,MAAM;AAAA,cACN,UAAU,KAAK;AAAA,cACf,MAAM,OAAO,IAAI;AAAA,cACjB,MAAM,GAAG;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAGA,WACG,eAAe,SAAS,eAAe,eACxCA,IAAG,aAAa,IAAI,KACpB,UAAU,IAAI,KAAK,IAAI,KACvB,KAAK,UAAU,UAAU,GACzB;AACA,qBAAa,MAAM,YAAY,GAAG,MAAM,MAAM;AAAA,MAChD;AAAA,IACF;AACA,IAAAA,IAAG,aAAa,MAAM,KAAK;AAAA,EAC7B;AACA,EAAAA,IAAG,aAAa,GAAG,KAAK,KAAK;AAC/B;AAGA,SAAS,cAAc,MAAsE;AAC3F,MACEA,IAAG,iBAAiB,IAAI,KACxBA,IAAG,2BAA2B,KAAK,UAAU,KAC7C,KAAK,WAAW,KAAK,SAAS,WAC9B,KAAK,UAAU,UAAU,GACzB;AACA,UAAM,MAAM,KAAK,UAAU,CAAC;AAC5B,QAAIA,IAAG,gBAAgB,GAAG,KAAKA,IAAG,gCAAgC,GAAG,GAAG;AACtE,YAAM,eAAe,KAAK,WAAW;AACrC,aAAO;AAAA,QACL,MAAM,IAAI;AAAA,QACV,GAAIA,IAAG,aAAa,YAAY,IAAI,EAAE,UAAU,aAAa,KAAK,IAAI,CAAC;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aACP,MACA,YACA,MACA,QACM;AACN,QAAM,OAAO,KAAK;AAClB,MAAI,eAAe,YAAY;AAE7B,QAAI,KAAK,CAAC,KAAKA,IAAG,aAAa,KAAK,CAAC,CAAC,GAAG;AACvC,UAAI,SAAS;AACb,YAAM,OAAO,KAAK,CAAC;AACnB,UAAI,QAAQA,IAAG,0BAA0B,IAAI,GAAG;AAC9C,mBAAW,KAAK,KAAK,YAAY;AAC/B,cAAIA,IAAG,qBAAqB,CAAC,KAAKA,IAAG,aAAa,EAAE,IAAI,KAAK,EAAE,KAAK,SAAS,UAAU;AACrF,qBAASA,IAAG,gBAAgB,EAAE,WAAW,IAAI,EAAE,YAAY,OAAO;AAAA,UACpE;AAAA,QACF;AAAA,MACF;AACA,aAAO,KAAK,EAAE,QAAQ,WAAW,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC;AAAA,IACvD;AACA;AAAA,EACF;AAEA,QAAM,QAAQ,KAAK,CAAC;AACpB,MAAIA,IAAG,gBAAgB,KAAK,KAAKA,IAAG,gCAAgC,KAAK,GAAG;AAC1E,eAAW,OAAO,KAAK,MAAM,CAAC,GAAG;AAC/B,UAAIA,IAAG,aAAa,GAAG,EAAG,QAAO,KAAK,EAAE,QAAQ,MAAM,MAAM,WAAW,IAAI,MAAM,KAAK,CAAC;AAAA,IACzF;AAAA,EACF,WAAWA,IAAG,aAAa,KAAK,GAAG;AACjC,WAAO,KAAK,EAAE,QAAQ,IAAI,WAAW,MAAM,MAAM,KAAK,CAAC;AAAA,EACzD,WAAW,KAAK,UAAU,GAAG;AAC3B,eAAW,OAAO,KAAK,MAAM,CAAC,GAAG;AAC/B,UAAIA,IAAG,aAAa,GAAG,EAAG,QAAO,KAAK,EAAE,QAAQ,aAAa,WAAW,IAAI,MAAM,KAAK,CAAC;AAAA,IAC1F;AAAA,EACF;AACF;AAGA,SAAS,aAAa,KAA6B;AACjD,SAAO,EACLA,IAAG,0BAA0B,GAAG,KAChCA,IAAG,gBAAgB,GAAG,KACtBA,IAAG,gCAAgC,GAAG,KACtCA,IAAG,iBAAiB,GAAG,KACvB,IAAI,SAASA,IAAG,WAAW,eAC3B,IAAI,SAASA,IAAG,WAAW;AAE/B;AAEA,SAAS,cAAc,QAAgB,GAAmB;AACxD,MAAI,CAAC,OAAQ,QAAO,KAAK;AACzB,QAAM,SAAS,GAAG,MAAM,IAAI,CAAC,GAAG,QAAQ,WAAW,GAAG;AACtD,SAAO,OAAO,SAAS,IAAI,OAAO,QAAQ,OAAO,EAAE,IAAI;AACzD;AAMA,SAAS,cACP,WACA,UAC6C;AAC7C,QAAM,WAAW,UAAU,OAAO,MAAM;AACxC,MAAI,aAAa,IAAI;AACnB,WAAO,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,aAAa,EAAE,MAAM,WAAW,YAAY,GAAG,CAAC;AAAA,EAC1F;AACA,QAAM,SAAS,UAAU,MAAM,GAAG,QAAQ;AAC1C,SAAO,SAAS,KAAK,CAAC,MAAM,EAAE,MAAM,WAAW,MAAM,KAAK,EAAE,MAAM,SAAS,OAAO,MAAM;AAC1F;;;ACxVA,OAAOC,SAAQ;AAQf,IAAM,YAA4B;AAGlC,IAAM,oBAA4C;AAAA,EAChD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AACP;AAgBO,IAAM,aAAuB;AAAA,EAClC,MAAM;AAAA,EACN,QAAQ,CAAC,SAAS;AAChB,UAAM,OAAO,EAAE,GAAG,KAAK,YAAY,cAAc,GAAG,KAAK,YAAY,gBAAgB;AACrF,WAAO,QAAQ,KAAK,cAAc,KAAK,KAAK,gBAAgB,CAAC;AAAA,EAC/D;AAAA,EAEA,QAAQ,KAAkC;AACxC,UAAM,cAAiC,CAAC;AAExC,UAAM,eAAe,oBAAI,IAAyB;AAElD,eAAW,QAAQ,IAAI,UAAU,GAAG;AAClC,UAAI,WAAW,IAAI,IAAI,IAAI,CAAC,EAAG;AAC/B,YAAM,KAAK,IAAI,MAAM,MAAM,IAAI,IAAI;AACnC,yBAAmB,IAAI,WAAW;AAClC,+BAAyB,IAAI,YAAY;AAAA,IAC3C;AAEA,UAAM,WAAsB,CAAC;AAC7B,UAAM,OAAO,oBAAI,IAAY;AAC7B,QAAI,aAAa;AAEjB,eAAW,QAAQ,aAAa;AAK9B,YAAM,aAAa,aAAa,KAAK,MAAM,aAAa,IAAI,KAAK,IAAI,CAAC;AAEtE,iBAAW,SAAS,KAAK,QAAQ;AAC/B,cAAM,WAAWC,eAAc,KAAK,QAAQ,MAAM,IAAI;AACtD;AACA,cAAM,MAAM,GAAG,MAAM,MAAM,IAAI,QAAQ,IAAI,KAAK,IAAI;AACpD,YAAI,KAAK,IAAI,GAAG,EAAG;AACnB,aAAK,IAAI,GAAG;AAEZ,cAAM,MAAM,IAAI,IAAI,KAAK,IAAI;AAC7B,cAAM,UAAU;AAAA,UACd;AAAA,UACA,EAAE,MAAM,SAAS,QAAQ,MAAM,QAAQ,MAAM,UAAU,WAAW,UAAU;AAAA,UAC5E,EAAE,MAAM,KAAK,MAAM,MAAM,KAAK;AAAA,UAC9B,IAAI,KAAK;AAAA,UACT,GAAG,MAAM,MAAM,IAAI,QAAQ,+BAA+B,KAAK,IAAI;AAAA,QACrE;AAEA,YAAI,CAAC,YAAY;AACf,kBAAQ,SAAS;AAAA,YACf;AAAA,cACE;AAAA,cACA,eAAe,KAAK,IAAI;AAAA,cACxB,EAAE,MAAM,KAAK,MAAM,KAAK,KAAK;AAAA,YAC/B;AAAA,UACF;AAAA,QACF;AAEA,YAAI,KAAK,WAAW,aAAa;AAC/B,kBAAQ,SAAS;AAAA,YACf;AAAA,cACE;AAAA,cACA,eAAe,KAAK,IAAI;AAAA,YAC1B;AAAA,UACF;AAAA,QACF;AAEA,iBAAS,KAAK,OAAO;AAAA,MACvB;AAAA,IACF;AAEA,WAAO,EAAE,UAAU,SAAS,EAAE,QAAQ,WAAW,EAAE;AAAA,EACrD;AACF;AAGA,SAAS,aACP,KACA,MACA,aACS;AACT,MAAI,CAAC,eAAe,YAAY,SAAS,EAAG,QAAO;AACnD,aAAW,cAAc,aAAa;AACpC,QAAI,eAAe,KAAK,KAAM,QAAO;AACrC,UAAM,KAAK,IAAI,MAAM,MAAM,IAAI,UAAU;AACzC,QAAI,IAAI,QAAQ,KAAK,CAAC,QAAQ,IAAI,iBAAiB,KAAK,IAAI,EAAG,QAAO;AAAA,EACxE;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,IAAgB,KAA8B;AACxE,QAAM,SAAS,CAAC,SACd,GAAG,IAAI,8BAA8B,KAAK,SAAS,GAAG,GAAG,CAAC,EAAE,OAAO;AAErE,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAIC,IAAG,mBAAmB,IAAI,KAAK,KAAK,MAAM;AAC5C,YAAM,aAAaA,IAAG,gBAAgB,IAAI,KAAK,CAAC;AAChD,YAAM,gBAAgB,WAAW,KAAK,CAAC,MAAM,cAAc,CAAC,MAAM,YAAY;AAC9E,UAAI,eAAe;AACjB,cAAM,SAAS,iBAAiB,aAAa;AAC7C,cAAM,SAA4B,CAAC;AACnC,mBAAW,UAAU,KAAK,SAAS;AACjC,cAAI,CAACA,IAAG,oBAAoB,MAAM,EAAG;AACrC,qBAAW,OAAOA,IAAG,gBAAgB,MAAM,KAAK,CAAC,GAAG;AAClD,kBAAM,OAAO,kBAAkB,cAAc,GAAG,KAAK,EAAE;AACvD,gBAAI,MAAM;AACR,qBAAO,KAAK;AAAA,gBACV,QAAQ;AAAA,gBACR,MAAM,mBAAmB,GAAG,KAAK;AAAA,gBACjC,MAAM,OAAO,MAAM;AAAA,cACrB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AACA,YAAI,OAAO,SAAS,GAAG;AACrB,cAAI,KAAK,EAAE,MAAM,KAAK,KAAK,MAAM,QAAQ,QAAQ,MAAM,GAAG,MAAM,MAAM,OAAO,IAAI,EAAE,CAAC;AAAA,QACtF;AAAA,MACF;AAAA,IACF;AACA,IAAAA,IAAG,aAAa,MAAM,KAAK;AAAA,EAC7B;AACA,EAAAA,IAAG,aAAa,GAAG,KAAK,KAAK;AAC/B;AAGA,SAAS,yBAAyB,IAAgB,KAAqC;AACrF,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAIA,IAAG,mBAAmB,IAAI,GAAG;AAC/B,YAAM,aAAaA,IAAG,gBAAgB,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,cAAc,CAAC,MAAM,QAAQ;AAC5F,UAAI,aAAaA,IAAG,iBAAiB,UAAU,UAAU,GAAG;AAC1D,cAAM,MAAM,UAAU,WAAW,UAAU,CAAC;AAC5C,YAAI,OAAOA,IAAG,0BAA0B,GAAG,GAAG;AAC5C,qBAAW,QAAQ,IAAI,YAAY;AACjC,gBACEA,IAAG,qBAAqB,IAAI,KAC5BA,IAAG,aAAa,KAAK,IAAI,KACzB,KAAK,KAAK,SAAS,iBACnBA,IAAG,yBAAyB,KAAK,WAAW,GAC5C;AACA,yBAAW,MAAM,KAAK,YAAY,UAAU;AAC1C,oBAAIA,IAAG,aAAa,EAAE,GAAG;AACvB,sBAAI,MAAM,IAAI,IAAI,GAAG,IAAI;AACzB,sBAAI,CAAC,IAAK,KAAI,IAAI,GAAG,MAAO,MAAM,oBAAI,IAAI,CAAE;AAC5C,sBAAI,IAAI,GAAG,IAAI;AAAA,gBACjB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,IAAAA,IAAG,aAAa,MAAM,KAAK;AAAA,EAC7B;AACA,EAAAA,IAAG,aAAa,GAAG,KAAK,KAAK;AAC/B;AAEA,SAAS,cAAc,KAAuC;AAC5D,QAAM,OAAOA,IAAG,iBAAiB,IAAI,UAAU,IAAI,IAAI,WAAW,aAAa,IAAI;AACnF,SAAOA,IAAG,aAAa,IAAI,IAAI,KAAK,OAAO;AAC7C;AAGA,SAAS,mBAAmB,KAAuC;AACjE,MAAI,CAACA,IAAG,iBAAiB,IAAI,UAAU,EAAG,QAAO;AACjD,QAAM,MAAM,IAAI,WAAW,UAAU,CAAC;AACtC,MAAI,QAAQA,IAAG,gBAAgB,GAAG,KAAKA,IAAG,gCAAgC,GAAG,GAAI,QAAO,IAAI;AAC5F,SAAO;AACT;AAGA,SAAS,iBAAiB,KAA2B;AACnD,MAAI,CAACA,IAAG,iBAAiB,IAAI,UAAU,EAAG,QAAO;AACjD,QAAM,MAAM,IAAI,WAAW,UAAU,CAAC;AACtC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAIA,IAAG,gBAAgB,GAAG,KAAKA,IAAG,gCAAgC,GAAG,EAAG,QAAO,IAAI;AACnF,MAAIA,IAAG,0BAA0B,GAAG,GAAG;AACrC,eAAW,QAAQ,IAAI,YAAY;AACjC,UACEA,IAAG,qBAAqB,IAAI,KAC5BA,IAAG,aAAa,KAAK,IAAI,KACzB,KAAK,KAAK,SAAS,QACnB;AACA,YACEA,IAAG,gBAAgB,KAAK,WAAW,KACnCA,IAAG,gCAAgC,KAAK,WAAW,GACnD;AACA,iBAAO,KAAK,YAAY;AAAA,QAC1B;AACA,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAASD,eAAc,QAAgB,GAAmB;AACxD,QAAM,IAAI,OAAO,QAAQ,YAAY,EAAE;AACvC,QAAM,IAAI,EAAE,QAAQ,YAAY,EAAE;AAClC,QAAM,SAAS,CAAC,GAAG,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAC9C,SAAO,MAAM;AACf;;;ACrOA,IAAME,aAA4B;AAGlC,IAAMC,4BAA2B;AAMjC,IAAM,sBAAsB,oBAAI,IAAI;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQM,IAAM,aAAuB;AAAA,EAClC,MAAM;AAAA,EACN,QAAQ,CAAC,SAAS;AAChB,UAAM,OAAO,EAAE,GAAG,KAAK,YAAY,cAAc,GAAG,KAAK,YAAY,gBAAgB;AACrF,WAAO,QAAQ,KAAK,MAAM,CAAC;AAAA,EAC7B;AAAA,EAEA,QAAQ,KAAkC;AACxC,UAAM,SAAsB,CAAC;AAC7B,UAAM,aAAa,oBAAI,IAAY;AAEnC,eAAW,QAAQ,IAAI,UAAU,GAAG;AAClC,YAAM,MAAMC,OAAM,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,GAAG,GAAG;AAClD,UAAI,CAAC,IAAK;AACV,YAAM,SAAS,cAAc,GAAG;AAChC,UAAI,QAAQ;AACV,eAAO,KAAK,EAAE,GAAG,QAAQ,KAAK,CAAC;AAC/B,mBAAW,IAAI,IAAI;AAAA,MACrB;AAAA,IACF;AAIA,UAAM,iBAAoD,CAAC;AAC3D,eAAW,CAAC,MAAM,EAAE,KAAK,IAAI,MAAM,OAAO;AACxC,UAAI,WAAW,IAAI,IAAI,EAAG;AAC1B,iBAAW,OAAO,GAAG,aAAc,gBAAe,KAAK,EAAE,OAAO,IAAI,OAAO,KAAK,CAAC;AAAA,IACnF;AACA,UAAM,qBAAqB,eAAe,UAAUD;AAEpD,UAAM,WAAsB,CAAC;AAC7B,UAAM,OAAO,oBAAI,IAAY;AAE7B,eAAW,SAAS,QAAQ;AAC1B,YAAM,MAAM,GAAG,MAAM,MAAM,IAAI,MAAM,SAAS;AAC9C,UAAI,KAAK,IAAI,GAAG,EAAG;AACnB,WAAK,IAAI,GAAG;AAEZ,YAAM,MAAM,IAAI,IAAI,MAAM,IAAI;AAC9B,YAAM,UAAU;AAAA,QACd;AAAA,QACA,EAAE,MAAM,SAAS,QAAQ,MAAM,QAAQ,MAAM,MAAM,WAAW,WAAWD,WAAU;AAAA,QACnF,EAAE,MAAM,KAAK,MAAM,EAAE;AAAA,QACrB,IAAI,KAAK;AAAA,QACT,GAAG,MAAM,MAAM,IAAI,MAAM,SAAS;AAAA,MACpC;AAEA,UAAI,sBAAsB,CAAC,MAAM,UAAU,SAAS,GAAG,GAAG;AACxD,cAAM,QAAQG,eAAc,MAAM,WAAW,cAAc;AAC3D,YAAI,OAAO;AACT,kBAAQ,SAAS;AAAA,YACf;AAAA,cACE;AAAA,cACA,IAAI,MAAM,KAAK,QAAQ,IAAI,IAAI,MAAM,IAAI,CAAC;AAAA,YAC5C;AAAA,UACF;AAAA,QACF,OAAO;AACL,kBAAQ,SAAS;AAAA,YACf;AAAA,cACE;AAAA,cACA,2CAA2C,eAAe,MAAM;AAAA,YAClE;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,MAAM,UAAU,SAAS,GAAG,GAAG;AAExC,gBAAQ,SAAS;AAAA,UACf;AAAA,YACE;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,eAAS,KAAK,OAAO;AAAA,IACvB;AAEA,WAAO,EAAE,UAAU,SAAS,EAAE,QAAQ,KAAK,KAAK,EAAE;AAAA,EACpD;AACF;AAOA,SAAS,cAAc,KAAgE;AACrF,QAAM,IAAI,6CAA6C,KAAK,GAAG;AAC/D,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,SAAS,EAAE,CAAC;AAClB,MAAI,OAAO,EAAE,CAAC;AAEd,QAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,QAAM,WAAW,SAAS,SAAS,SAAS,CAAC;AAC7C,MAAI,oBAAoB,IAAI,QAAQ,EAAG,QAAO;AAE9C,MAAI,WAAW,OAAO;AAEpB,QAAI,aAAa,UAAU,aAAa,QAAS,QAAO;AACxD,aAAS,IAAI;AACb,UAAM,SAAS,aAAa,UAAU,QAAQ;AAC9C,WAAO,EAAE,WAAW,YAAY,QAAQ,GAAG,OAAO;AAAA,EACpD;AAGA,MAAI,aAAa,QAAS,UAAS,IAAI;AACvC,QAAM,QAAQ,SAAS,CAAC,MAAM;AAC9B,SAAO,EAAE,WAAW,YAAY,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,MAAM;AAC3E;AAGA,SAAS,YAAY,UAA4B;AAC/C,QAAM,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG,EAAE;AAC3E,SAAO,MAAM,KAAK,KAAK,GAAG;AAC5B;AAEA,SAASD,OAAM,SAAiB,SAAiB,KAAsC;AAGrF,QAAM,UAAU,IAAI,IAAI,OAAO;AAC/B,MAAI,YAAY,OAAO,YAAY,GAAI,QAAO;AAC9C,SAAO,QAAQ,WAAW,UAAU,GAAG,IAAI,QAAQ,MAAM,QAAQ,SAAS,CAAC,IAAI;AACjF;AAGA,SAASC,eACP,WACA,UAC6C;AAC7C,SAAO,SAAS;AAAA,IACd,CAAC,MACC,EAAE,UAAU,aACZ,EAAE,MAAM,WAAW,YAAY,GAAG,KAClC,EAAE,MAAM,WAAW,YAAY,GAAG,KACjC,cAAc,OAAO,EAAE,MAAM,WAAW,YAAY,GAAG;AAAA,EAC5D;AACF;;;ACrLA,OAAOC,YAAU;;;ACyBV,SAAS,QAAQ,SAAkB,UAA6C;AACrF,MAAI,CAAC,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,MAAM,GAAG;AAC/D,YAAQ,SAAS,KAAK,QAAQ;AAAA,EAChC;AACF;;;ADjBO,IAAM,iBAAmC;AAAA,EAC9C,MAAM;AAAA,EAEN,QAAQ,KAAK,UAAU;AACrB,UAAM,UAA2B,CAAC;AAClC,eAAW,CAAC,MAAM,EAAE,KAAK,IAAI,MAAM,OAAO;AACxC,iBAAW,WAAW,GAAG,iBAAiB;AACxC,gBAAQ,KAAK;AAAA,UACX,KAAK,WAAW,MAAM,QAAQ,MAAM;AAAA,UACpC,YAAY;AAAA,UACZ,MAAM,QAAQ;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF;AACA,QAAI,QAAQ,WAAW,EAAG;AAE1B,eAAW,WAAW,UAAU;AAC9B,UAAI,QAAQ,aAAa,oBAAqB;AAC9C,YAAM,cAAc,IAAI,IAAI,QAAQ,SAAS,IAAI;AACjD,YAAM,aAAa,aAAa,WAAW;AAG3C,YAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAQ,UAAU;AACtD,YAAM,QAAQ,SAAS,QAAQ,KAAK,CAAC,MAAM,QAAQ,EAAE,KAAK,WAAW,CAAC;AACtE,UAAI,CAAC,MAAO;AAEZ;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ,oCAAoC;AAAA,UAC5C,6BAA6B,IAAI,IAAI,MAAM,UAAU,CAAC,IAAI,MAAM,IAAI;AAAA,UACpE,EAAE,MAAM,IAAI,IAAI,MAAM,UAAU,GAAG,MAAM,MAAM,KAAK;AAAA,QACtD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,WAAW,gBAAwB,QAAoC;AAC9E,QAAM,UAAU,aAAa,cAAc;AAC3C,MAAI,CAAC,UAAU,CAAC,OAAO,WAAW,GAAG,EAAG,QAAO;AAC/C,QAAM,WAAW,QAAQC,OAAK,QAAQ,SAAS,MAAM,CAAC;AAEtD,SAAO,OAAO,SAAS,GAAG,IAAI,WAAW,aAAa,QAAQ;AAChE;;;AExDA,OAAOC,SAAQ;AAMR,IAAM,iBAAmC;AAAA,EAC9C,MAAM;AAAA,EAEN,QAAQ,KAAK,UAAU;AACrB,UAAM,WAAW,oBAAoB,KAAK,QAAQ;AAClD,QAAI,SAAS,SAAS,EAAG;AAEzB,eAAW,CAAC,MAAM,EAAE,KAAK,IAAI,MAAM,OAAO;AAExC,YAAM,iBAAiB,oBAAI,IAAgD;AAC3E,iBAAW,OAAO,GAAG,SAAS;AAC5B,YAAI,CAAC,IAAI,aAAc;AACvB,mBAAW,KAAK,IAAI,OAAO;AACzB,yBAAe,IAAI,EAAE,OAAO,EAAE,MAAM,IAAI,cAAc,UAAU,EAAE,SAAS,CAAC;AAAA,QAC9E;AAAA,MACF;AACA,UAAI,eAAe,SAAS,EAAG;AAE/B,YAAM,QAAQ,CAAC,SAAwB;AACrC,YAAIC,IAAG,0BAA0B,IAAI,KAAK,KAAK,WAAW,UAAU,GAAG;AACrE,qBAAW,QAAQ,KAAK,YAAY;AAClC,gBAAI;AACJ,gBAAIA,IAAG,8BAA8B,IAAI,EAAG,SAAQ,KAAK,KAAK;AAAA,qBACrDA,IAAG,qBAAqB,IAAI,KAAKA,IAAG,aAAa,KAAK,WAAW,GAAG;AAC3E,sBAAQ,KAAK,YAAY;AAAA,YAC3B;AACA,kBAAM,MAAM,QAAQ,eAAe,IAAI,KAAK,IAAI;AAChD,gBAAI,KAAK;AACP,oBAAM,UAAU,SAAS,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE;AACnE,kBAAI,SAAS;AACX;AAAA,kBACE;AAAA,kBACA;AAAA,oBACE;AAAA,oBACA,IAAI,IAAI,QAAQ,oCAAoC,IAAI,IAAI,IAAI,CAAC;AAAA,kBACnE;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA,QAAAA,IAAG,aAAa,MAAM,KAAK;AAAA,MAC7B;AACA,MAAAA,IAAG,aAAa,GAAG,KAAK,KAAK;AAAA,IAC/B;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,KAAsB,UAA2C;AAC5F,QAAM,QAAQ,oBAAI,IAAqB;AACvC,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,aAAa,mBAAmB,EAAE,OAAO,SAAS,UAAU;AAChE,YAAM,IAAI,GAAG,EAAE,OAAO,IAAI,IAAI,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,IACpD;AAAA,EACF;AACA,SAAO;AACT;;;AC1DO,IAAM,iBAAmC;AAAA,EAC9C,MAAM;AAAA,EAEN,QAAQ,KAAK,UAAU;AACrB,eAAW,WAAW,UAAU;AAC9B,UAAI,QAAQ,aAAa,uBAAuB,QAAQ,OAAO,SAAS;AACtE;AACF,YAAM,UAAU,QAAQ,OAAO;AAC/B,YAAM,OAAO,IAAI,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,SAAS,KAAK,IAAI,MAAM,CAAC;AAC/E,YAAM,MAAM,kBAAkB,MAAM,OAAO,KAAK,kBAAkB,IAAI,MAAM,CAAC,GAAI,OAAO;AACxF,UAAI,KAAK;AACP;AAAA,UACE;AAAA,UACA;AAAA,YACE;AAAA,YACA,sCAAsC,IAAI,MAAM,MAAM,SAAS,IAAI,OAAO,CAAC;AAAA,UAC7E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBACP,MACA,SACiD;AAEjD,QAAM,UAAU,QAAQ,SAAS,GAAG,IAAI,QAAQ,MAAM,GAAG,EAAE,IAAI,IAAK;AACpE,QAAM,KAAK,IAAI,OAAO,gBAAgB,SAAS,OAAO,CAAC,cAAc;AACrE,aAAW,CAAC,QAAQ,OAAO,KAAK,OAAO,QAAQ,KAAK,YAAY,WAAW,CAAC,CAAC,GAAG;AAC9E,QAAI,QAAQ,SAAS,OAAO,KAAK,GAAG,KAAK,OAAO,EAAG,QAAO,EAAE,QAAQ,QAAQ;AAAA,EAC9E;AACA,SAAO;AACT;AAEA,SAAS,SAAS,GAAmB;AACnC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AAEA,SAAS,SAAS,GAAmB;AACnC,SAAO,EAAE,SAAS,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,WAAM;AAChD;;;AC/CA,OAAOC,SAAQ;AAMf,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,iBAAiB,oBAAI,IAAI,CAAC,YAAY,eAAe,WAAW,OAAO,OAAO,CAAC;AACrF,IAAM,iBAAiB,oBAAI,IAAI,CAAC,SAAS,UAAU,WAAW,UAAU,MAAM,CAAC;AAExE,IAAM,kBAAoC;AAAA,EAC/C,MAAM;AAAA,EAEN,QAAQ,KAAK,UAAU;AACrB,UAAM,WAAW,oBAAI,IAAoB;AACzC,eAAW,CAAC,MAAM,EAAE,KAAK,IAAI,MAAM,OAAO;AACxC,YAAM,SAAS,GAAG,QACf,IAAI,CAAC,MAAM,EAAE,mBAAmB,cAAc,EAAE,SAAS,CAAC,EAC1D,KAAK,CAAC,MAAM,aAAa,IAAI,CAAC,CAAC;AAClC,UAAI,UAAU,cAAc,GAAG,GAAG,EAAG,UAAS,IAAI,MAAM,MAAM;AAAA,IAChE;AACA,QAAI,SAAS,SAAS,EAAG;AAEzB,eAAW,WAAW,UAAU;AAC9B,UAAI,QAAQ,aAAa,oBAAqB;AAC9C,YAAMC,OAAM,SAAS,IAAI,IAAI,IAAI,QAAQ,SAAS,IAAI,CAAC;AACvD,UAAIA,MAAK;AACP;AAAA,UACE;AAAA,UACA;AAAA,YACE;AAAA,YACA,sCAAsCA,IAAG;AAAA,UAC3C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,cAAc,KAA6B;AAClD,MAAI,QAAQ;AACZ,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAI,MAAO;AACX,QACEC,IAAG,iBAAiB,IAAI,KACxBA,IAAG,2BAA2B,KAAK,UAAU,KAC7C,eAAe,IAAI,KAAK,WAAW,KAAK,IAAI,GAC5C;AACA,cAAQ;AACR;AAAA,IACF;AACA,QAAIA,IAAG,gBAAgB,IAAI,GAAG;AAC5B,YAAM,SAAS,KAAK;AACpB,YAAM,OAAOA,IAAG,aAAa,MAAM,IAC/B,OAAO,OACPA,IAAG,2BAA2B,MAAM,IAClC,OAAO,KAAK,OACZ;AACN,UAAI,QAAQ,eAAe,IAAI,IAAI,GAAG;AACpC,gBAAQ;AACR;AAAA,MACF;AAAA,IACF;AACA,IAAAA,IAAG,aAAa,MAAM,KAAK;AAAA,EAC7B;AACA,EAAAA,IAAG,aAAa,KAAK,KAAK;AAC1B,SAAO;AACT;;;ACxEA,IAAM,kBAAkB;AAEjB,IAAM,WAA6B;AAAA,EACxC,MAAM;AAAA,EAEN,QAAQ,KAAK,UAAU;AACrB,eAAW,WAAW,UAAU;AAC9B,YAAM,KAAK,IAAI,MAAM,MAAM,IAAI,IAAI,IAAI,QAAQ,SAAS,IAAI,CAAC;AAC7D,UAAI,CAAC,MAAM,GAAG,eAAe,WAAW,EAAG;AAE3C,iBAAW,UAAU,GAAG,gBAAgB;AACtC,cAAM,OACJ,KAAK,IAAI,OAAO,OAAO,QAAQ,SAAS,IAAI,KAAK;AAAA,QAEhD,QAAQ,aAAa,sBAAsB,OAAO,QAAQ,kBAAkB;AAC/E,YAAI,CAAC,KAAM;AAEX;AAAA,UACE;AAAA,UACA;AAAA,YACE,OAAO,SAAS,eAAe,4BAA4B;AAAA,YAC3D,GAAG,OAAO,SAAS,eAAe,gBAAgB,SAAS,mBAAmB,OAAO,IAAI,KAAKC,UAAS,OAAO,IAAI,CAAC;AAAA,YACnH,EAAE,MAAM,QAAQ,SAAS,MAAM,MAAM,OAAO,KAAK;AAAA,UACnD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAASA,UAAS,GAAmB;AACnC,SAAO,EAAE,SAAS,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,WAAM;AAChD;;;AChCO,IAAM,oBAAsC;AAAA,EACjD,MAAM;AAAA,EAEN,QAAQ,KAAK,UAAU;AACrB,QAAI,IAAI,gBAAgB,WAAW,EAAG;AACtC,UAAM,SAAS,IAAI,IAAI,IAAI,gBAAgB,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAElE,eAAW,WAAW,UAAU;AAC9B,UAAI,QAAQ,aAAa,oBAAqB;AAC9C,YAAM,SAAS,OAAO,IAAI,IAAI,IAAI,QAAQ,SAAS,IAAI,CAAC;AACxD,UAAI,QAAQ;AACV;AAAA,UACE;AAAA,UACA,YAAY,6BAA6B,GAAG,OAAO,MAAM,KAAK,OAAO,QAAQ,GAAG;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACpBA,SAAS,SAAS,OAAgC;AAChD,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO;AACT;AAOO,SAAS,aAAa,UAA2B,UAAuC;AAC7F,QAAM,MAAM,SAAS,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AACzD,QAAM,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,QAAQ;AAC7D,QAAM,MAAM,YAAY,YAAY,QAAQ,IAAI;AAChD,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC;AACxD,QAAM,SAA0B,EAAE,OAAO,OAAO,SAAS,KAAK,EAAE;AAChE,MAAI,aAAa,MAAM,KAAK;AAC1B,WAAO,SAAS,EAAE,IAAI,KAAK,QAAQ,kBAAkB;AAAA,EACvD;AACA,SAAO;AACT;;;A9BmCA,IAAM,kBAAkB,CAAC,sCAAsC;AAC/D,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAoC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,YAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOA,IAAM,sBAAgD;AAAA,EACpD,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AACR;AAIA,IAAM,YAAgC;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,eAAsB,KAAK,SAA2C;AACpE,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,OAAO,SAAS,QAAQ,IAAI;AAClC,MAAI,CAACC,IAAG,WAAW,IAAI,KAAK,CAACA,IAAG,SAAS,IAAI,EAAE,YAAY,GAAG;AAC5D,UAAM,IAAI,UAAU,gBAAgB,oBAAoB,QAAQ,IAAI,EAAE;AAAA,EACxE;AAEA,QAAM,WAAqB,CAAC;AAC5B,QAAM,EAAE,OAAO,UAAU,UAAU,WAAW,IAAI,MAAM,mBAAmB,IAAI;AAC/E,WAAS,KAAK,GAAG,UAAU;AAE3B,QAAM,QACJ,QAAQ,cAAc,QAAQ,WAAW,SAAS,IAC9C,SAAS,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK,QAAQ,WAAY,SAAS,EAAE,IAAI,CAAC,IACzE;AAGN,QAAM,QAAQ,MAAMC,MAAK,CAAC,GAAG,iBAAiB,GAAI,QAAQ,WAAW,CAAC,CAAE,GAAG;AAAA,IACzE,KAAK;AAAA,IACL,QAAQ,CAAC,GAAG,iBAAiB,GAAI,QAAQ,WAAW,CAAC,CAAE;AAAA,IACvD,UAAU;AAAA,IACV,KAAK;AAAA,EACP,CAAC;AACD,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,IAAI,UAAU,mBAAmB,qCAAqC,QAAQ,IAAI,EAAE;AAAA,EAC5F;AAEA,QAAM,QAAQ,IAAI,YAAY;AAC9B,aAAW,QAAQ,MAAM,IAAI,OAAO,EAAE,KAAK,GAAG;AAC5C,QAAI;AACF,YAAM,QAAQ,UAAU,MAAMD,IAAG,aAAa,MAAM,MAAM,CAAC,CAAC;AAAA,IAC9D,QAAQ;AACN,eAAS,KAAK,mBAAmB,SAAS,MAAM,IAAI,CAAC,iCAAiC;AAAA,IACxF;AAAA,EACF;AACA,QAAM,eAAe,IAAI,IAAI,MAAM,MAAM,KAAK,CAAC;AAG/C,QAAM,YAA8B,MACjC,OAAO,CAAC,MAAM,EAAE,SAAS,GAAG,EAC5B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE,KAAK,WAAW,eAAe,GAAG,YAAY,EAAE,EAAE;AACxF,QAAM,KAAK,IAAI,SAAS,MAAM,WAAW,cAAc,QAAQ,CAAC;AAGhE,QAAM,kBAAkB,MAAM,uBAAuB,MAAM,cAAc,QAAQ;AAGjF,QAAM,gBAAgB,oBAAI,IAA4B;AACtD,aAAW,QAAQ,OAAO;AACxB,kBAAc,IAAI,MAAM,oBAAoB,MAAM,cAAc,QAAQ,CAAC;AAAA,EAC3E;AACA,QAAM,WAAW,MAAM,CAAC;AACxB,aAAW,UAAU,iBAAiB;AACpC,cAAU,eAAe,YAAY,OAAO,OAAO,IAAI,GAAG;AAAA,MACxD,MAAM,OAAO;AAAA,MACb,QAAQ;AAAA,MACR,QAAQ,OAAO;AAAA,IACjB,CAAC;AAAA,EACH;AACA,aAAW,OAAO,QAAQ,WAAW,CAAC,GAAG;AACvC,UAAM,WAAW,gBAAgB,MAAM,KAAK,YAAY,KAAK,QAAQE,OAAK,QAAQ,MAAM,GAAG,CAAC;AAC5F,QAAI,UAAU;AACZ,gBAAU,eAAe,YAAY,OAAO,QAAQ,QAAQ,CAAC,GAAG;AAAA,QAC9D,MAAM,QAAQ,QAAQ;AAAA,QACtB,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,OAAO;AACL,eAAS,KAAK,YAAY,GAAG,kCAAkC;AAAA,IACjE;AAAA,EACF;AAGA,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,cAAc,IAAI,IAAI;AAClC,QAAI,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,QAAQ,UAAU,EAAE,WAAW,QAAQ,GAAG;AAC/D,YAAM,QAAQ,eAAe,MAAM,YAAY;AAC/C,UAAI;AACF,kBAAU,eAAe,MAAM,EAAE,MAAM,OAAO,QAAQ,QAAQ,QAAQ,aAAa,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,QAAM,iBAAiB,CAAC,GAAG,cAAc,OAAO,CAAC,EAAE,KAAK;AACxD,QAAM,QAAQ;AAAA,IACZ,KAAK,MAAM,UAAU,eAAe,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAAA,IACtD,MAAM,MAAM,UAAU,eAAe,OAAO,CAAC,MAAM,EAAE,QAAQ,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAAA,EACzF;AAGA,QAAM,kBAAuC;AAAA,IAC3C,YAAY,IAAI,IAAI,QAAQ,YAAY,SAAS,QAAQ,aAAa,cAAc;AAAA,IACpF,YAAY,IAAI,IAAI,QAAQ,cAAc,CAAC,CAAC;AAAA,EAC9C;AAEA,QAAM,YAAY,oBAAI,IAAsB;AAC5C,aAAW,QAAQ,aAAc,WAAU,IAAI,MAAM,YAAY,OAAO,IAAI,CAAC;AAE7E,MAAI,WAAsB,CAAC;AAC3B,MAAI,cAAc;AAClB,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAmB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb,iBAAiB,cAAc,IAAI,IAAI,KAAK,CAAC;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA,KAAK,CAAC,SAAS,SAAS,MAAM,IAAI;AAAA,MAClC,WAAW,MAAM,CAAC,GAAG,YAAY,EAAE,OAAO,CAAC,MAAM,UAAU,IAAI,CAAC,MAAM,IAAI;AAAA,IAC5E;AACA,UAAM,kBAAkB,IAAI;AAAA,MAC1B,CAAC,GAAG,gBAAgB,UAAU,EAAE,IAAI,CAAC,MAAM,oBAAoB,CAAC,CAAC,EAAE,OAAO,OAAO;AAAA,IACnF;AACA,eAAW,YAAY,WAAW;AAChC,UAAI,CAAC,gBAAgB,IAAI,QAAQ,KAAK,CAAC,SAAS,OAAO,IAAI,EAAG;AAC9D,YAAM,SAAS,SAAS,QAAQ,GAAG;AACnC,eAAS,KAAK,GAAG,OAAO,QAAQ;AAChC,qBAAe,OAAO,SAAS,UAAU;AAAA,IAC3C;AAAA,EACF;AAGA,QAAM,cAA+B;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA,KAAK,CAAC,SAAS,SAAS,MAAM,IAAI;AAAA,IAClC,KAAK,CAAC,YAAY,GAAG,IAAI,IAAI,OAAO;AAAA,EACtC;AACA,aAAW,YAAY,WAAW;AAChC,aAAS,QAAQ,aAAa,QAAQ;AAAA,EACxC;AAGA,aAAW,WAAW,UAAU;AAC9B,YAAQ,aAAa,aAAa,QAAQ,UAAU,QAAQ,QAAQ;AAAA,EACtE;AAGA,aAAW,SAAS,OAAO,CAAC,MAAM,EAAE,EAAE,aAAa,gBAAgB,EAAE,SAAS,WAAW,EAAE;AAC3F,aAAW,SAAS,OAAO,CAAC,MAAM,gBAAgB,WAAW,IAAI,EAAE,QAAQ,CAAC;AAC5E,QAAM,gBAAgB,IAAI,IAAI,eAAe,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAClE,WAAS;AAAA,IACP,CAAC,GAAG,MACF,cAAc,IAAI,EAAE,QAAQ,IAAK,cAAc,IAAI,EAAE,QAAQ,KAC7D,EAAE,WAAW,QAAQ,EAAE,WAAW,SAClC,EAAE,SAAS,KAAK,cAAc,EAAE,SAAS,IAAI,KAC7C,EAAE,SAAS,OAAO,EAAE,SAAS;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,eAAe;AAAA,IACf,MAAM,EAAE,MAAM,YAAY,SAAS,QAAQ,eAAe,QAAQ;AAAA,IAClE,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA,YAAY,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IACnC;AAAA,IACA,OAAO,aAAa,OAAO,OAAO,UAAU,aAAa,KAAK,IAAI,IAAI,SAAS;AAAA,IAC/E,UAAU,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AAAA,EACjC;AACF;AAEA,SAAS,UAAU,KAAkC,MAAgB,OAAyB;AAC5F,QAAM,OAAO,IAAI,IAAI,IAAI;AACzB,MAAI,CAAC,MAAM;AACT,QAAI,IAAI,MAAM,CAAC,KAAK,CAAC;AAAA,EACvB,WAAW,CAAC,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,IAAI,GAAG;AACnD,SAAK,KAAK,KAAK;AAAA,EACjB;AACF;AAGA,SAAS,eAAe,MAAgB,cAAuD;AAC7F,MAAI,OAAO,KAAK,YAAY,SAAS,UAAU;AAC7C,UAAM,SAAS,gBAAgB,KAAK,KAAK,KAAK,YAAY,MAAM,YAAY;AAC5E,QAAI,OAAQ,QAAO;AAAA,EACrB;AACA,aAAW,aAAa,CAAC,aAAa,SAAS,YAAY,WAAW,OAAO,UAAU,MAAM,GAAG;AAC9F,UAAM,MAAM,QAAQA,OAAK,KAAK,KAAK,KAAK,SAAS,CAAC;AAClD,QAAI,OAAO,aAAa,IAAI,QAAQ,GAAG,CAAC,EAAG,QAAO,QAAQ,GAAG;AAAA,EAC/D;AACA,SAAO;AACT;AAEA,eAAe,uBACb,MACA,cACA,UAC2B;AAC3B,QAAM,UAA4B,CAAC;AACnC,QAAM,gBAAgB,MAAMD;AAAA,IAC1B;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,EAAE,KAAK,MAAM,QAAQ,CAAC,sBAAsB,cAAc,YAAY,GAAG,KAAK,KAAK;AAAA,EACrF;AAEA,aAAW,OAAO,cAAc,IAAI,OAAO,EAAE,KAAK,GAAG;AACnD,QAAI;AACF,UAAI,IAAI,WAAW,oBAAoB,GAAG;AACxC,gBAAQ,KAAK,GAAG,oBAAoB,MAAM,KAAK,QAAQ,CAAC;AAAA,MAC1D,WAAW,gCAAgC,KAAK,GAAG,GAAG;AACpD,gBAAQ,KAAK,GAAG,gBAAgB,MAAM,KAAK,QAAQ,CAAC;AAAA,MACtD,WAAW,gBAAgB,KAAK,GAAG,GAAG;AACpC,gBAAQ,KAAK,GAAG,iBAAiB,MAAM,KAAK,QAAQ,CAAC;AAAA,MACvD,WAAW,mBAAmB,KAAK,GAAG,GAAG;AACvC,gBAAQ,KAAK,GAAG,gBAAgB,MAAM,GAAG,CAAC;AAAA,MAC5C,WAAW,cAAc,GAAG,GAAG;AAC7B,gBAAQ,KAAK,GAAG,aAAa,MAAM,GAAG,CAAC;AAAA,MACzC,WAAW,0BAA0B,KAAK,GAAG,GAAG;AAC9C,gBAAQ,KAAK,GAAG,mBAAmB,MAAM,GAAG,CAAC;AAAA,MAC/C;AAAA,IACF,QAAQ;AACN,eAAS,KAAK,2BAA2B,GAAG,4BAA4B;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO,QAAQ,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE,IAAI,CAAC;AACvD;AAEA,SAAS,aACP,OACA,OACA,UACA,aACA,YACW;AAIX,QAAM,UAAU,CAAC,aACf,SAAS,OAAO,CAAC,MAAM,EAAE,aAAa,YAAY,EAAE,WAAW,SAAS,EAAE,EAAE;AAE9E,MAAI,eAAe;AACnB,aAAW,MAAM,MAAM,MAAM,OAAO,GAAG;AACrC,oBAAgB,IAAI,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE;AAAA,EACzD;AACA,MAAI,YAAY;AAChB,aAAW,KAAK,OAAO;AACrB,iBACE,OAAO,KAAK,EAAE,YAAY,gBAAgB,CAAC,CAAC,EAAE,SAC9C,OAAO,KAAK,EAAE,YAAY,mBAAmB,CAAC,CAAC,EAAE;AAAA,EACrD;AAEA,SAAO;AAAA,IACL,cAAc,MAAM,MAAM;AAAA,IAC1B;AAAA,IACA,QAAQ,EAAE,OAAO,aAAa,SAAS,QAAQ,YAAY,EAAE;AAAA,IAC7D,SAAS,EAAE,OAAO,cAAc,SAAS,QAAQ,eAAe,EAAE;AAAA,IAClE,cAAc,EAAE,OAAO,WAAW,SAAS,QAAQ,mBAAmB,EAAE;AAAA,IACxE,OAAO,EAAE,OAAO,MAAM,MAAM,MAAM,SAAS,QAAQ,kBAAkB,EAAE;AAAA,EACzE;AACF;;;A+BtXA,IAAM,aAA8C,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,EAAE;AAG1E,SAAS,YAAY,MAA0B;AACpD,QAAM,IAAI,iCAAiC,KAAK,IAAI;AACpD,MAAI,CAAC,GAAG;AACN,UAAM,IAAI,MAAM,sBAAsB,IAAI,8CAA8C;AAAA,EAC1F;AACA,SAAO,EAAE,OAAO,EAAE,CAAC,GAAsB,KAAK,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE;AACxE;AAOO,SAAS,eACd,UACA,MACqC;AACrC,QAAM,QAAQ,SAAS;AAAA,IACrB,CAAC,MAAM,WAAW,EAAE,WAAW,KAAK,KAAK,WAAW,KAAK,KAAK;AAAA,EAChE,EAAE;AACF,SAAO,EAAE,OAAO,SAAS,SAAS,KAAK,IAAI;AAC7C;;;AC1BO,SAAS,WAAW,QAA4B;AACrD,SAAO,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI;AAC3C;;;ACFA,IAAM,kBAAmD;AAAA,EACvD,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,oBAAoB;AACtB;AAEO,SAAS,SAAS,QAA4B;AACnD,QAAM,QAAkB,CAAC;AACzB,QAAM,EAAE,MAAM,IAAI;AAElB,QAAM,KAAK,2BAAsB;AACjC,QAAM,KAAK,EAAE;AACb,MAAI,MAAM,OAAO,QAAQ,GAAG;AAC1B,UAAM,MAAM,KAAK,MAAO,MAAM,OAAO,UAAU,MAAM,OAAO,QAAS,GAAG;AACxE,UAAM;AAAA,MACJ,KAAK,GAAG,8BAA8B,MAAM,OAAO,OAAO,OAAO,MAAM,OAAO,KAAK;AAAA,IACrF;AAAA,EACF;AACA,QAAM,UAAoB,CAAC;AAC3B,MAAI,MAAM,QAAQ,QAAQ,EAAG,SAAQ,KAAK,GAAG,MAAM,QAAQ,OAAO,iBAAiB;AACnF,MAAI,MAAM,aAAa,QAAQ;AAC7B,YAAQ,KAAK,GAAG,MAAM,aAAa,OAAO,sBAAsB;AAClE,MAAI,MAAM,MAAM,QAAQ,EAAG,SAAQ,KAAK,GAAG,MAAM,MAAM,OAAO,oBAAoB;AAClF,MAAI,QAAQ,SAAS;AACnB,UAAM,KAAK,GAAG,QAAQ,KAAK,QAAK,CAAC,WAAM,MAAM,YAAY,gBAAgB;AAC3E,QAAM,KAAK,EAAE;AAEb,aAAW,YAAY,OAAO,KAAK,eAAe,GAAwB;AACxE,UAAM,QAAQ,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ;AACnE,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,KAAK,OAAO,gBAAgB,QAAQ,CAAC,KAAK,MAAM,MAAM,GAAG;AAC/D,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,mDAAmD;AAC9D,UAAM,KAAK,mBAAmB;AAC9B,eAAW,KAAK,OAAO;AACrB,YAAM,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;AACrF,YAAM;AAAA,QACJ,KAAK,EAAE,WAAW,KAAK,IAAI,EAAE,WAAW,KAAK,MAAM,SAAS,eAAe,EAAE,MAAM,CAAC,CAAC,QAAQ,EAAE,SAAS,IAAI,IAAI,EAAE,SAAS,IAAI,QAAQ,SAAS,KAAK,UAAU,EAAE,CAAC;AAAA,MACpK;AAAA,IACF;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM,GAAG;AACpD,UAAM;AAAA,MACJ;AAAA,IACF;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AACA,aAAW,WAAW,OAAO,UAAU;AACrC,UAAM,KAAK,YAAO,SAAS,OAAO,CAAC,EAAE;AAAA,EACvC;AACA,SAAO,MAAM,KAAK,IAAI,IAAI;AAC5B;AAEA,SAAS,SAAS,GAAmB;AACnC,SAAO,EAAE,QAAQ,OAAO,KAAK;AAC/B;;;AC5DA,OAAO,QAAQ;AAYf,IAAME,mBAAmD;AAAA,EACvD,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,oBAAoB;AACtB;AAEA,IAAM,aAAa;AAEZ,SAAS,aAAa,QAAoB,UAA2B;AAC1E,QAAM,IAAI,GAAG,aAAa,QAAQ;AAClC,QAAM,QAAkB,CAAC;AACzB,QAAM,EAAE,MAAM,IAAI;AAGlB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,KAAK,EAAE,KAAK,iBAAY,CAAC,IAAI,EAAE,IAAI,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC,EAAE;AAC1E,QAAM,OAAO;AAAA,IACX,GAAG,MAAM,YAAY;AAAA,IACrB,eAAe,MAAM,UAAU;AAAA,IAC/B,OAAO,WAAW,SAAS,IAAI,GAAG,OAAO,WAAW,MAAM,gBAAgB;AAAA,EAC5E,EAAE,OAAO,OAAO;AAChB,QAAM,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,UAAO,CAAC,CAAC,EAAE;AAC3C,QAAM,KAAK,KAAK,EAAE,IAAI,SAAI,OAAO,UAAU,CAAC,CAAC,EAAE;AAC/C,QAAM,KAAK,EAAE;AAGb,YAAU,OAAO,GAAG,MAAM,QAAQ,8BAA8B,IAAI;AACpE,YAAU,OAAO,GAAG,MAAM,SAAS,uBAAuB;AAC1D,YAAU,OAAO,GAAG,MAAM,cAAc,4BAA4B;AACpE,YAAU,OAAO,GAAG,MAAM,OAAO,0BAA0B;AAE3D,MAAI,OAAO,SAAS,WAAW,GAAG;AAChC,UAAM;AAAA,MACJ,KAAK,EAAE,MAAM,QAAG,CAAC;AAAA,IACnB;AAAA,EACF;AAGA,aAAW,YAAY,OAAO,KAAKA,gBAAe,GAAwB;AACxE,UAAM,QAAQ,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ;AACnE,QAAI,MAAM,WAAW,EAAG;AAExB,UAAM,aAAa,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE,EAAE;AACjE,UAAM,SACJ,eAAe,MAAM,SACjB,GAAG,MAAM,MAAM,KACf,GAAG,MAAM,MAAM,SAAM,UAAU;AAErC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,YAAY,GAAGA,iBAAgB,QAAQ,GAAG,MAAM,CAAC;AAC5D,UAAM,KAAK,EAAE;AAEb,eAAW,WAAW,OAAO;AAC3B,YAAM,KAAK,QAAQ,WAAW;AAC9B,YAAM;AAAA,QACJ,KAAK,IAAI,GAAG,EAAE,CAAC,IAAI,WAAW,GAAG,QAAQ,WAAW,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,QAAG,CAAC,IAAI,EAAE;AAAA,UAChF,eAAe,QAAQ,MAAM;AAAA,QAC/B,CAAC;AAAA,MACH;AACA,YAAM;AAAA,QACJ,kBAAkB,EAAE,IAAI,QAAG,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,SAAS,IAAI,IAAI,QAAQ,SAAS,IAAI,EAAE,CAAC;AAAA,MAC5F;AACA,YAAM,MAAM,YAAY,OAAO;AAC/B,iBAAW,MAAM,KAAK;AACpB,cAAM,OAAO,GAAG,cAAc,SAAS,EAAE,IAAI,QAAG,IAAI,EAAE,OAAO,QAAG;AAChE,cAAM,KAAK,kBAAkB,EAAE,IAAI,QAAG,CAAC,IAAI,IAAI,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE;AAAA,MACvE;AACA,YAAM,OAAO,QAAQ,SAAS,SAAS,IAAI;AAC3C,UAAI,OAAO,GAAG;AACZ,cAAM;AAAA,UACJ,kBAAkB,EAAE,IAAI,QAAG,CAAC,IAAI,EAAE,IAAI,UAAK,IAAI,eAAe,OAAO,IAAI,MAAM,EAAE,eAAe,CAAC;AAAA,QACnG;AAAA,MACF;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAGA,QAAM,KAAK,KAAK,EAAE,IAAI,SAAI,OAAO,UAAU,CAAC,CAAC,EAAE;AAC/C,QAAM,gBAAgB,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,QAAQ,CAAC;AAChG,MAAI,eAAe;AACjB,UAAM;AAAA,MACJ,KAAK,EAAE,OAAO,QAAG,CAAC,kDAAkD,EAAE,IAAI,wBAAwB,CAAC;AAAA,IACrG;AACA,UAAM,KAAK,mEAAmE;AAAA,EAChF;AACA,MAAI,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE,GAAG;AACxD,UAAM;AAAA,MACJ,KAAK,EAAE,IAAI,QAAG,CAAC,IAAI,EAAE,IAAI,sEAAsE,CAAC;AAAA,IAClG;AAAA,EACF;AACA,aAAW,WAAW,OAAO,UAAU;AACrC,UAAM,KAAK,KAAK,EAAE,OAAO,QAAG,CAAC,IAAI,EAAE,IAAI,OAAO,CAAC,EAAE;AAAA,EACnD;AACA,QAAM,KAAK,EAAE;AACb,QAAM;AAAA,IACJ,KAAK,EAAE,IAAI,wFAA6E,CAAC;AAAA,EAC3F;AACA,QAAM,KAAK,EAAE;AACb,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,UACP,OACA,GACA,MACA,OACA,cAAc,OACR;AACN,MAAI,KAAK,UAAU,EAAG;AACtB,QAAM,QAAQ,KAAK,UAAU,IAAI,EAAE,IAAI,QAAG,IAAI,EAAE,MAAM,QAAG;AACzD,MAAI,aAAa;AACf,UAAM,MAAM,KAAK,MAAO,KAAK,UAAU,KAAK,QAAS,GAAG;AACxD,UAAM;AAAA,MACJ,KAAK,KAAK,IAAI,EAAE,KAAK,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,EAAE,IAAI,IAAI,KAAK,OAAO,OAAO,KAAK,KAAK,GAAG,CAAC;AAAA,IACzF;AAAA,EACF,OAAO;AACL,UAAM,KAAK,KAAK,KAAK,IAAI,EAAE,KAAK,OAAO,KAAK,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,EAAE;AAAA,EAC/F;AACF;AAGA,SAAS,YAAY,GAAW,OAAe,QAAwB;AACrE,QAAM,OAAO,KAAK,IAAI,GAAG,aAAa,MAAM,SAAS,OAAO,SAAS,CAAC;AACtE,SAAO,KAAK,EAAE,IAAI,cAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,IAAI,EAAE,IAAI,SAAI,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC;AACtF;AAEA,SAAS,IAAI,GAAW,OAAgC;AACtD,MAAI,UAAU,OAAQ,QAAO,EAAE,IAAI,QAAG;AACtC,MAAI,UAAU,SAAU,QAAO,EAAE,OAAO,QAAG;AAC3C,SAAO,EAAE,IAAI,QAAG;AAClB;AAGA,SAAS,WAAW,GAAW,OAAe,OAAgC;AAC5E,QAAM,OAAO,GAAG,OAAO,KAAK,EAAE,SAAS,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC;AAC5D,MAAI,UAAU,OAAQ,QAAO,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;AAC/C,MAAI,UAAU,SAAU,QAAO,EAAE,OAAO,IAAI;AAC5C,SAAO,EAAE,IAAI,IAAI;AACnB;AAGA,SAAS,YAAY,SAAuC;AAC1D,SAAO,CAAC,GAAG,QAAQ,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC;AACjG;AAEA,SAAS,eAAe,IAAoB;AAC1C,SAAO,KAAK,MAAO,GAAG,EAAE,OAAO,IAAI,KAAK,KAAM,QAAQ,CAAC,CAAC;AAC1D;;;AnC5IA,IAAM,MAAM,cAAc,YAAY,GAAG,EAAE,iBAAiB;AAE5D,IAAM,aAAgC;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAMC,cAA8C,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,EAAE;AAEjF,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,UAAU,EACf,YAAY,iFAA4E,EACxF,QAAQ,IAAI,OAAO,EACnB,SAAS,UAAU,qBAAqB,GAAG,EAC3C,OAAO,UAAU,uCAAuC,EACxD,OAAO,QAAQ,uCAAuC,EACtD,OAAO,oBAAoB,8DAA8D,EACzF,OAAO,uBAAuB,qBAAqB,EACnD,OAAO,uBAAuB,qBAAqB,EACnD,UAAU,IAAI,OAAO,4BAA4B,gBAAgB,EAAE,QAAQ,UAAU,CAAC,EACtF,OAAO,yBAAyB,uCAAuC,EACvE;AAAA,EACC,IAAI,OAAO,8BAA8B,iCAAiC,EAAE,QAAQ;AAAA,IAClF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH,EACC,OAAO,qBAAqB,kDAAkD,EAC9E;AAAA,EACC,IAAI,OAAO,4BAA4B,gCAAgC,EACpE,QAAQ,CAAC,OAAO,UAAU,MAAM,CAAC,EACjC,QAAQ,KAAK;AAClB,EACC,OAAO,cAAc,gBAAgB,EACrC,OAAO,OAAOC,QAAc,SAAqB;AAChD,QAAM,IAAIA,QAAM,IAAI;AACtB,CAAC;AAgBH,eAAe,IAAIA,QAAc,MAAiC;AAChE,MAAI,KAAK,QAAQ,KAAK,IAAI;AACxB,YAAQ,OAAO,MAAM,iDAAiD;AACtE,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,cAAc,MAAM;AACxB,QAAI;AACF,aAAO,KAAK,SAAS,YAAY,KAAK,MAAM,IAAI;AAAA,IAClD,SAAS,KAAK;AACZ,cAAQ,OAAO,MAAM,UAAW,IAAc,OAAO;AAAA,CAAI;AACzD,cAAQ,WAAW;AACnB,aAAO;AAAA,IACT;AAAA,EACF,GAAG;AACH,MAAI,eAAe,KAAM;AAEzB,QAAM,gBAAgB,QAAQ,KAAK,QAAQ,KAAK,EAAE;AAClD,QAAM,UAAU,IAAI;AAAA,IAClB,MAAM;AAAA,IACN,QAAQ,QAAQ;AAAA,IAChB,WAAW,CAAC,iBAAiB,QAAQ,OAAO,UAAU;AAAA,EACxD,CAAC;AAED,MAAI;AACF,YAAQ,MAAM;AACd,UAAM,SAAS,MAAM,KAAK;AAAA,MACxB,MAAAA;AAAA,MACA,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,aAAa,IAAI;AAAA,IACnB,CAAC;AACD,YAAQ,KAAK;AAGb,UAAM,OAAO,aAAa,eAAe,OAAO,UAAU,UAAU,IAAI;AACxE,UAAM,YAAY,iBAAiB,QAAQ,KAAK,aAAa;AAE7D,UAAM,WAAW,KAAK,SAASC,IAAG,oBAAoB,QAAQ,OAAO,UAAU;AAC/E,UAAM,SAAS,KAAK,OAChB,WAAW,SAAS,IACpB,KAAK,KACH,SAAS,SAAS,IAClB,aAAa,WAAW,QAAQ;AACtC,YAAQ,OAAO,MAAM,MAAM;AAI3B,QAAI,KAAK,MAAM;AACb,iBAAW,WAAW,OAAO,SAAU,SAAQ,OAAO,MAAM,YAAY,OAAO;AAAA,CAAI;AAAA,IACrF;AAEA,QAAI,MAAM,SAAS;AACjB,cAAQ,OAAO;AAAA,QACb,uBAAuB,KAAK,MAAM,aAAa,KAAK,KAAK,WAAW,KAAK,UAAU,IAAI,KAAK,GAAG,cAAc,WAAY,KAAK;AAAA;AAAA,MAChI;AACA,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,KAAK;AACb,QAAI,eAAe,WAAW;AAC5B,cAAQ,OAAO,MAAM,UAAU,IAAI,IAAI,MAAM,IAAI,OAAO;AAAA,CAAI;AAAA,IAC9D,OAAO;AACL,cAAQ,OAAO;AAAA,QACb,UAAU,eAAe,QAAS,IAAI,SAAS,IAAI,UAAW,OAAO,GAAG,CAAC;AAAA;AAAA,MAC3E;AAAA,IACF;AACA,YAAQ,WAAW;AAAA,EACrB;AACF;AAEA,SAAS,iBAAiB,QAAoB,eAA4C;AACxF,MAAI,kBAAkB,MAAO,QAAO;AACpC,QAAM,MAAMF,YAAW,aAAa;AACpC,QAAM,WAAsB,OAAO,SAAS,OAAO,CAAC,MAAMA,YAAW,EAAE,WAAW,KAAK,KAAK,GAAG;AAC/F,SAAO,EAAE,GAAG,QAAQ,SAAS;AAC/B;AAEA,MAAM,QAAQ,WAAW,QAAQ,IAAI;","names":["pc","fs","path","glob","path","ts","ts","ws","path","fs","path","path","pkg","fs","path","pkg","path","fs","path","fs","path","fs","path","parseYaml","parseYaml","fs","path","fs","path","fs","path","fs","path","parseYaml","fs","path","parseYaml","fs","path","fs","path","ts","ts","ts","joinRoutePath","ts","FRAMEWORK","CLIENT_LITERAL_THRESHOLD","relTo","findPathMatch","path","path","ts","ts","ts","pkg","ts","truncate","fs","glob","path","CATEGORY_TITLES","LEVEL_RANK","path","pc"]}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "deadwood-scan",
3
+ "version": "0.2.0",
4
+ "description": "Find dead code and prove it — scans a JS/TS repo and prints a shock report",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "deadwood": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "dependencies": {
17
+ "commander": "^12.1.0",
18
+ "ora": "^8.1.1",
19
+ "picocolors": "^1.1.1",
20
+ "tinyglobby": "^0.2.10",
21
+ "typescript": "^5.7.2",
22
+ "yaml": "^2.6.1"
23
+ },
24
+ "devDependencies": {
25
+ "@deadwood/core": "0.1.0"
26
+ },
27
+ "scripts": {
28
+ "build": "tsup",
29
+ "typecheck": "tsc --noEmit"
30
+ }
31
+ }