@jatingargiitk/archmap 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -9
- package/action.yml +19 -3
- package/dist/action.js +19 -6
- package/dist/action.js.map +1 -1
- package/dist/chunk-QUFBKU64.js +915 -0
- package/dist/chunk-QUFBKU64.js.map +1 -0
- package/dist/cli.js +21 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parser/tree-sitter-loader.ts","../src/parser/typescript-extractor.ts","../src/parser/python-extractor.ts","../src/resolver/index.ts","../src/graph/index.ts","../src/render/index.ts","../src/lock/index.ts","../src/rules/index.ts"],"sourcesContent":["import { Parser, Language } from 'web-tree-sitter';\n\nlet parserInitialized = false;\n\nexport async function initParser(): Promise<void> {\n if (parserInitialized) return;\n await Parser.init();\n parserInitialized = true;\n}\n\nconst languageCache = new Map<string, Language>();\n\nexport async function loadLanguage(name: 'typescript' | 'python'): Promise<Language> {\n if (languageCache.has(name)) {\n return languageCache.get(name)!;\n }\n\n await initParser();\n \n const wasmPath = await getWasmPath(name);\n const language = await Language.load(wasmPath);\n languageCache.set(name, language);\n \n return language;\n}\n\nasync function getWasmPath(name: string): Promise<string> {\n try {\n const { createRequire } = await import('node:module');\n const require = createRequire(import.meta.url);\n const wasmPath = require.resolve(`tree-sitter-${name}/tree-sitter-${name}.wasm`);\n return wasmPath;\n } catch {\n return `node_modules/tree-sitter-${name}/tree-sitter-${name}.wasm`;\n }\n}\n\nexport async function parseFile(content: string, language: 'typescript' | 'python'): Promise<import('web-tree-sitter').Tree> {\n const lang = await loadLanguage(language);\n const parser = new Parser();\n parser.setLanguage(lang);\n const tree = parser.parse(content);\n if (!tree) {\n throw new Error(`Failed to parse file with language: ${language}`);\n }\n return tree;\n}\n","import type { Node } from 'web-tree-sitter';\nimport type { Import, FileImports, Location } from '../types.js';\nimport { parseFile } from './tree-sitter-loader.js';\n\nexport async function extractTypeScriptImports(filePath: string, content: string): Promise<FileImports> {\n const tree = await parseFile(content, 'typescript');\n const imports: Import[] = [];\n\n visitNode(tree.rootNode, (node) => {\n if (node.type === 'import_statement') {\n const imp = extractImportStatement(node, filePath, content);\n if (imp) imports.push(imp);\n } else if (node.type === 'call_expression') {\n const imp = extractDynamicImport(node, filePath, content);\n if (imp) imports.push(imp);\n }\n });\n\n return { file: filePath, imports };\n}\n\nfunction extractImportStatement(node: Node, file: string, content: string): Import | null {\n const sourceNode = node.childForFieldName('source');\n if (!sourceNode) return null;\n\n const from = extractStringValue(sourceNode, content);\n if (!from) return null;\n\n return {\n from,\n location: getLocation(node, file),\n };\n}\n\nfunction extractDynamicImport(node: Node, file: string, content: string): Import | null {\n const func = node.childForFieldName('function');\n if (!func || func.text !== 'import') return null;\n\n const args = node.childForFieldName('arguments');\n if (!args) return null;\n\n const firstArg = args.children.find((c: Node) => c.type === 'string' || c.type === 'template_string');\n if (!firstArg) return null;\n\n const from = extractStringValue(firstArg, content);\n if (!from) return null;\n\n return {\n from,\n isDynamic: true,\n location: getLocation(node, file),\n };\n}\n\nfunction extractStringValue(node: Node, _content: string): string | null {\n const text = node.text;\n if (text.startsWith('\"') || text.startsWith(\"'\")) {\n return text.slice(1, -1);\n }\n if (text.startsWith('`')) {\n const withoutBackticks = text.slice(1, -1);\n if (!withoutBackticks.includes('${')) {\n return withoutBackticks;\n }\n }\n return null;\n}\n\nfunction getLocation(node: Node, file: string): Location {\n return {\n file,\n line: node.startPosition.row + 1,\n column: node.startPosition.column,\n };\n}\n\nfunction visitNode(node: Node, visitor: (node: Node) => void): void {\n visitor(node);\n for (const child of node.children) {\n visitNode(child, visitor);\n }\n}\n\nexport async function extractJavaScriptImports(filePath: string, content: string): Promise<FileImports> {\n return extractTypeScriptImports(filePath, content);\n}\n","import type { Node } from 'web-tree-sitter';\nimport type { Import, FileImports, Location } from '../types.js';\nimport { parseFile } from './tree-sitter-loader.js';\n\nexport async function extractPythonImports(filePath: string, content: string): Promise<FileImports> {\n const tree = await parseFile(content, 'python');\n const imports: Import[] = [];\n\n visitNode(tree.rootNode, (node) => {\n if (node.type === 'import_statement' || node.type === 'import_from_statement') {\n const imp = extractImport(node, filePath, content);\n if (imp) imports.push(imp);\n }\n });\n\n return { file: filePath, imports };\n}\n\nfunction extractImport(node: Node, file: string, _content: string): Import | null {\n if (node.type === 'import_statement') {\n return extractPlainImport(node, file);\n } else if (node.type === 'import_from_statement') {\n return extractFromImport(node, file);\n }\n return null;\n}\n\nfunction extractPlainImport(node: Node, file: string): Import | null {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return null;\n\n const moduleName = getModuleName(nameNode);\n if (!moduleName) return null;\n\n return {\n from: moduleName,\n location: getLocation(node, file),\n };\n}\n\nfunction extractFromImport(node: Node, file: string): Import | null {\n const moduleNode = node.childForFieldName('module_name');\n if (!moduleNode) return null;\n\n const moduleName = getModuleName(moduleNode);\n if (!moduleName) return null;\n\n return {\n from: moduleName,\n location: getLocation(node, file),\n };\n}\n\nfunction getModuleName(node: Node): string | null {\n if (node.type === 'dotted_name') {\n return node.text;\n } else if (node.type === 'relative_import') {\n return node.text;\n } else if (node.type === 'aliased_import') {\n const nameChild = node.childForFieldName('name');\n if (nameChild) {\n return getModuleName(nameChild);\n }\n }\n return node.text || null;\n}\n\nfunction getLocation(node: Node, file: string): Location {\n return {\n file,\n line: node.startPosition.row + 1,\n column: node.startPosition.column,\n };\n}\n\nfunction visitNode(node: Node, visitor: (node: Node) => void): void {\n visitor(node);\n for (const child of node.children) {\n visitNode(child, visitor);\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { FileImports, ResolvedImport } from '../types.js';\n\nexport interface ResolverConfig {\n rootDir: string;\n tsconfig?: TsConfigPaths;\n workspaces?: string[];\n}\n\nexport interface TsConfigPaths {\n baseUrl?: string;\n paths?: Record<string, string[]>;\n}\n\nexport async function resolveImports(\n fileImports: FileImports[],\n config: ResolverConfig\n): Promise<ResolvedImport[]> {\n const resolved: ResolvedImport[] = [];\n\n for (const { file, imports } of fileImports) {\n for (const imp of imports) {\n const resolvedPath = await resolveImport(imp.from, file, config);\n if (resolvedPath) {\n resolved.push({\n from: file,\n to: resolvedPath,\n location: imp.location,\n });\n }\n }\n }\n\n return resolved;\n}\n\nasync function resolveImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (isExternalModule(importPath)) {\n return null;\n }\n\n const fileExt = path.extname(fromFile);\n const isPython = fileExt === '.py';\n\n if (isPython) {\n return resolvePythonImport(importPath, fromFile, config);\n }\n\n return resolveTypeScriptImport(importPath, fromFile, config);\n}\n\nfunction isExternalModule(importPath: string): boolean {\n return !importPath.startsWith('.') && !importPath.startsWith('/');\n}\n\nasync function resolveTypeScriptImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (importPath.startsWith('.')) {\n return resolveRelativePath(importPath, fromFile, config);\n }\n\n if (config.tsconfig?.paths) {\n const aliasResolved = await resolvePathAlias(importPath, config);\n if (aliasResolved) return aliasResolved;\n }\n\n if (config.workspaces) {\n const workspaceResolved = await resolveWorkspace(importPath, config);\n if (workspaceResolved) return workspaceResolved;\n }\n\n return null;\n}\n\nasync function resolveRelativePath(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n const dir = path.dirname(fromFile);\n let candidatePath = path.join(dir, importPath);\n\n // Handle ESM-style TypeScript imports: map .js/.mjs/.cjs to their TS sources (B3)\n const esmExt = path.extname(candidatePath);\n if (esmExt === '.js' || esmExt === '.mjs' || esmExt === '.cjs') {\n const basePath = candidatePath.slice(0, -esmExt.length);\n \n // Map .js -> .ts/.tsx, .mjs -> .mts, .cjs -> .cts\n const tsExtensions = esmExt === '.mjs' ? ['.mts'] :\n esmExt === '.cjs' ? ['.cts'] :\n ['.ts', '.tsx'];\n \n for (const tsExt of tsExtensions) {\n const tsPath = basePath + tsExt;\n if (await fileExists(path.join(config.rootDir, tsPath))) {\n return tsPath;\n }\n }\n \n // If no TS source found, continue with normal resolution\n candidatePath = basePath;\n }\n\n const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts'];\n \n for (const ext of extensions) {\n const withExt = candidatePath + ext;\n if (await fileExists(path.join(config.rootDir, withExt))) {\n return withExt;\n }\n }\n\n for (const ext of ['index.ts', 'index.tsx', 'index.js', 'index.jsx']) {\n const indexPath = path.join(candidatePath, ext);\n if (await fileExists(path.join(config.rootDir, indexPath))) {\n return indexPath;\n }\n }\n\n return null;\n}\n\nasync function resolvePathAlias(\n importPath: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (!config.tsconfig?.paths) return null;\n\n const { paths, baseUrl = '.' } = config.tsconfig;\n\n for (const [pattern, mappings] of Object.entries(paths)) {\n const regex = patternToRegex(pattern);\n const match = importPath.match(regex);\n\n if (match) {\n for (const mapping of mappings) {\n const resolved = mapping.replace('*', match[1] || '');\n const fullPath = path.join(baseUrl, resolved);\n \n const candidate = await resolveRelativePath(`./${fullPath}`, '', {\n ...config,\n rootDir: config.rootDir,\n });\n \n if (candidate) return candidate;\n\n if (await fileExists(path.join(config.rootDir, fullPath))) {\n return fullPath;\n }\n }\n }\n }\n\n return null;\n}\n\nasync function resolveWorkspace(\n importPath: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (!config.workspaces) return null;\n\n for (const workspace of config.workspaces) {\n const packageJsonPath = path.join(config.rootDir, workspace, 'package.json');\n \n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n \n if (pkg.name === importPath || importPath.startsWith(pkg.name + '/')) {\n const subpath = importPath.slice(pkg.name.length + 1) || '.';\n const mainFile = pkg.main || pkg.module || 'index.js';\n \n if (subpath === '.') {\n return path.join(workspace, mainFile);\n }\n \n const resolved = await resolveRelativePath(`./${subpath}`, workspace, {\n ...config,\n rootDir: config.rootDir,\n });\n \n if (resolved) return resolved;\n }\n } catch {\n // Skip if package.json doesn't exist\n }\n }\n\n return null;\n}\n\nasync function resolvePythonImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (importPath.startsWith('.')) {\n return resolvePythonRelative(importPath, fromFile, config);\n }\n\n const parts = importPath.split('.');\n const possiblePaths = [\n path.join(...parts) + '.py',\n path.join(...parts, '__init__.py'),\n path.join('src', ...parts) + '.py',\n path.join('src', ...parts, '__init__.py'),\n ];\n\n for (const possiblePath of possiblePaths) {\n if (await fileExists(path.join(config.rootDir, possiblePath))) {\n return possiblePath;\n }\n }\n\n return null;\n}\n\nasync function resolvePythonRelative(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n const dir = path.dirname(fromFile);\n let targetDir = dir;\n\n const dots = importPath.match(/^\\.+/)?.[0] || '.';\n const rest = importPath.slice(dots.length);\n\n for (let i = 1; i < dots.length; i++) {\n targetDir = path.dirname(targetDir);\n }\n\n if (rest) {\n const parts = rest.split('.');\n targetDir = path.join(targetDir, ...parts);\n }\n\n const candidatePath = targetDir + '.py';\n if (await fileExists(path.join(config.rootDir, candidatePath))) {\n return candidatePath;\n }\n\n const initPath = path.join(targetDir, '__init__.py');\n if (await fileExists(path.join(config.rootDir, initPath))) {\n return initPath;\n }\n\n return null;\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const withWildcard = escaped.replace(/\\\\\\*/g, '(.*)');\n return new RegExp(`^${withWildcard}$`);\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function loadTsConfig(rootDir: string): Promise<TsConfigPaths | null> {\n const tsconfigPath = path.join(rootDir, 'tsconfig.json');\n \n try {\n const content = await fs.readFile(tsconfigPath, 'utf-8');\n const tsconfig = JSON.parse(content);\n \n return {\n baseUrl: tsconfig.compilerOptions?.baseUrl,\n paths: tsconfig.compilerOptions?.paths,\n };\n } catch {\n return null;\n }\n}\n\nexport async function findWorkspaces(rootDir: string): Promise<string[]> {\n const packageJsonPath = path.join(rootDir, 'package.json');\n \n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n \n if (pkg.workspaces) {\n const patterns = Array.isArray(pkg.workspaces) \n ? pkg.workspaces \n : pkg.workspaces.packages || [];\n \n const workspaces: string[] = [];\n for (const pattern of patterns) {\n if (!pattern.includes('*')) {\n workspaces.push(pattern);\n } else {\n const base = pattern.replace('/*', '');\n try {\n const entries = await fs.readdir(path.join(rootDir, base));\n for (const entry of entries) {\n const fullPath = path.join(base, entry);\n const pkgPath = path.join(rootDir, fullPath, 'package.json');\n if (await fileExists(pkgPath)) {\n workspaces.push(fullPath);\n }\n }\n } catch {\n // Skip if base doesn't exist\n }\n }\n }\n \n return workspaces;\n }\n } catch {\n // No package.json or not a workspace\n }\n \n return [];\n}\n","import * as path from 'node:path';\nimport type { ResolvedImport, Module, ModuleEdge, Graph } from '../types.js';\n\nexport interface ModuleConfig {\n roots?: string[];\n depth?: number;\n}\n\nexport function buildGraph(\n resolvedImports: ResolvedImport[],\n allFiles: string[],\n config: ModuleConfig = {}\n): Graph {\n const { roots = ['src', 'packages/*', 'apps/*'], depth = 1 } = config;\n\n const fileToModule = new Map<string, string>();\n \n for (const file of allFiles) {\n const moduleName = getModuleName(file, roots, depth);\n fileToModule.set(file, moduleName);\n }\n\n const moduleFiles = new Map<string, Set<string>>();\n for (const [file, module] of fileToModule) {\n if (!moduleFiles.has(module)) {\n moduleFiles.set(module, new Set());\n }\n moduleFiles.get(module)!.add(file);\n }\n\n const edgeMap = new Map<string, Map<string, ModuleEdge>>();\n const externalDeps = new Map<string, Set<string>>();\n\n for (const resolved of resolvedImports) {\n const fromModule = fileToModule.get(resolved.from);\n const toModule = fileToModule.get(resolved.to);\n\n if (!fromModule || !toModule || fromModule === toModule) {\n continue;\n }\n\n if (!edgeMap.has(fromModule)) {\n edgeMap.set(fromModule, new Map());\n }\n\n const fromEdges = edgeMap.get(fromModule)!;\n \n if (!fromEdges.has(toModule)) {\n fromEdges.set(toModule, {\n from: fromModule,\n to: toModule,\n weight: 0,\n locations: [],\n });\n }\n\n const edge = fromEdges.get(toModule)!;\n edge.weight++;\n edge.locations.push(resolved.location);\n }\n\n const edges: ModuleEdge[] = [];\n for (const fromEdges of edgeMap.values()) {\n for (const edge of fromEdges.values()) {\n edges.push(edge);\n }\n }\n\n const fanIn = new Map<string, number>();\n const fanOut = new Map<string, number>();\n\n for (const edge of edges) {\n fanOut.set(edge.from, (fanOut.get(edge.from) || 0) + 1);\n fanIn.set(edge.to, (fanIn.get(edge.to) || 0) + 1);\n }\n\n const modules: Module[] = [];\n for (const [moduleName, files] of moduleFiles) {\n modules.push({\n name: moduleName,\n files: Array.from(files).sort(),\n fanIn: fanIn.get(moduleName) || 0,\n fanOut: fanOut.get(moduleName) || 0,\n externalDeps: Array.from(externalDeps.get(moduleName) || []).sort(),\n });\n }\n\n modules.sort((a, b) => a.name.localeCompare(b.name));\n\n const cycles = detectCycles(edges, modules.map(m => m.name));\n\n return {\n modules,\n edges,\n cycles,\n };\n}\n\nfunction getModuleName(file: string, roots: string[], depth: number): string {\n const normalized = file.replace(/\\\\/g, '/');\n \n for (const root of roots) {\n if (root.endsWith('/*')) {\n const base = root.slice(0, -2);\n if (normalized.startsWith(base + '/')) {\n const rest = normalized.slice(base.length + 1);\n const parts = rest.split('/');\n if (parts.length > 0) {\n return path.join(base, parts[0]);\n }\n }\n } else {\n if (normalized.startsWith(root + '/')) {\n const rest = normalized.slice(root.length + 1);\n const parts = rest.split('/');\n if (depth === 0) {\n return root;\n }\n const moduleParts = parts.slice(0, depth);\n return path.join(root, ...moduleParts);\n }\n }\n }\n\n const parts = normalized.split('/');\n if (parts.length > 0) {\n return parts[0];\n }\n\n return normalized;\n}\n\nexport function detectCycles(edges: ModuleEdge[], modules: string[]): string[][] {\n const graph = new Map<string, string[]>();\n \n for (const module of modules) {\n graph.set(module, []);\n }\n\n for (const edge of edges) {\n if (!graph.has(edge.from)) {\n graph.set(edge.from, []);\n }\n graph.get(edge.from)!.push(edge.to);\n }\n\n return tarjan(graph);\n}\n\nfunction tarjan(graph: Map<string, string[]>): string[][] {\n let index = 0;\n const stack: string[] = [];\n const onStack = new Set<string>();\n const indices = new Map<string, number>();\n const lowlinks = new Map<string, number>();\n const sccs: string[][] = [];\n\n function strongConnect(v: string): void {\n indices.set(v, index);\n lowlinks.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n const neighbors = graph.get(v) || [];\n for (const w of neighbors) {\n if (!indices.has(w)) {\n strongConnect(w);\n lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));\n } else if (onStack.has(w)) {\n lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));\n }\n }\n\n if (lowlinks.get(v) === indices.get(v)) {\n const scc: string[] = [];\n let w: string;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n\n if (scc.length > 1) {\n sccs.push(scc.sort());\n }\n }\n }\n\n for (const v of graph.keys()) {\n if (!indices.has(v)) {\n strongConnect(v);\n }\n }\n\n return sccs;\n}\n\nexport function computeLOC(files: Map<string, string>): Map<string, number> {\n const loc = new Map<string, number>();\n\n for (const [file, content] of files) {\n const lines = content.split('\\n').filter(line => {\n const trimmed = line.trim();\n return trimmed.length > 0 && !trimmed.startsWith('//') && !trimmed.startsWith('#');\n });\n loc.set(file, lines.length);\n }\n\n return loc;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Graph, Module, ModuleEdge } from '../types.js';\n\nconst START_MARKER = '<!-- archmap:start -->';\nconst END_MARKER = '<!-- archmap:end -->';\n\nexport function renderMermaid(graph: Graph): string {\n const sections: string[] = [];\n\n sections.push('# Architecture\\n');\n sections.push(START_MARKER);\n sections.push('');\n sections.push('## Module Dependencies\\n');\n sections.push('```mermaid');\n sections.push(renderMermaidGraph(graph));\n sections.push('```\\n');\n\n sections.push('## Modules\\n');\n sections.push(renderModuleTable(graph.modules));\n sections.push('');\n\n if (graph.cycles.length > 0) {\n sections.push('## ⚠️ Cycles Detected\\n');\n sections.push(renderCycles(graph.cycles));\n sections.push('');\n }\n\n sections.push(END_MARKER);\n\n return sections.join('\\n');\n}\n\nfunction renderMermaidGraph(graph: Graph): string {\n const lines: string[] = ['flowchart LR'];\n\n const edgesSorted = [...graph.edges].sort((a, b) => {\n if (a.from !== b.from) return a.from.localeCompare(b.from);\n return a.to.localeCompare(b.to);\n });\n\n for (const edge of edgesSorted) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n const label = edge.weight > 1 ? `|${edge.weight}|` : '';\n const arrow = label ? `-->${label}` : '-->';\n lines.push(` ${fromId}[${edge.from}] ${arrow} ${toId}[${edge.to}]`);\n }\n\n if (edgesSorted.length === 0) {\n for (const module of graph.modules.slice(0, 5)) {\n const id = sanitizeId(module.name);\n lines.push(` ${id}[${module.name}]`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction renderModuleTable(modules: Module[]): string {\n const lines: string[] = [\n '| Module | Files | Fan-In | Fan-Out | External Deps |',\n '|--------|-------|--------|---------|---------------|',\n ];\n\n const sorted = [...modules].sort((a, b) => {\n const fanA = a.fanIn + a.fanOut;\n const fanB = b.fanIn + b.fanOut;\n if (fanB !== fanA) return fanB - fanA;\n return a.name.localeCompare(b.name);\n });\n\n for (const module of sorted) {\n const externalDeps = module.externalDeps.length > 0\n ? module.externalDeps.slice(0, 3).join(', ') +\n (module.externalDeps.length > 3 ? '...' : '')\n : '-';\n\n lines.push(\n `| \\`${module.name}\\` | ${module.files.length} | ${module.fanIn} | ${module.fanOut} | ${externalDeps} |`\n );\n }\n\n return lines.join('\\n');\n}\n\nfunction renderCycles(cycles: string[][]): string {\n const lines: string[] = [];\n\n for (let i = 0; i < cycles.length; i++) {\n const cycle = cycles[i];\n lines.push(`${i + 1}. ${cycle.map(m => `\\`${m}\\``).join(' → ')}`);\n }\n\n return lines.join('\\n');\n}\n\nfunction sanitizeId(name: string): string {\n return name.replace(/[^a-zA-Z0-9_]/g, '_');\n}\n\nexport async function writeArchitectureFile(\n filePath: string,\n graph: Graph\n): Promise<void> {\n let existingContent = '';\n \n try {\n existingContent = await fs.readFile(filePath, 'utf-8');\n } catch {\n // File doesn't exist, that's fine\n }\n\n const newContent = renderMermaid(graph);\n\n let finalContent: string;\n\n if (existingContent) {\n const startIndex = existingContent.indexOf(START_MARKER);\n const endIndex = existingContent.indexOf(END_MARKER);\n\n if (startIndex !== -1 && endIndex !== -1) {\n const before = existingContent.slice(0, startIndex);\n const after = existingContent.slice(endIndex + END_MARKER.length);\n \n const extractedSection = newContent.slice(\n newContent.indexOf(START_MARKER),\n newContent.indexOf(END_MARKER) + END_MARKER.length\n );\n\n finalContent = before + extractedSection + after;\n } else {\n finalContent = newContent + '\\n\\n' + existingContent;\n }\n } else {\n finalContent = newContent;\n }\n\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, finalContent, 'utf-8');\n}\n\nexport function renderDeltaDiagram(\n addedEdges: ModuleEdge[],\n removedEdges: ModuleEdge[],\n touchedModules: Set<string>\n): string {\n const lines: string[] = ['```mermaid', 'flowchart LR'];\n \n for (const module of touchedModules) {\n const id = sanitizeId(module);\n lines.push(` ${id}[${module}]`);\n }\n\n let edgeIndex = 0;\n\n for (const edge of addedEdges) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n lines.push(` ${fromId} ====> ${toId}`);\n lines.push(` linkStyle ${edgeIndex} stroke:#00ff00,stroke-width:3px`);\n edgeIndex++;\n }\n\n for (const edge of removedEdges) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n lines.push(` ${fromId} -.-> ${toId}`);\n lines.push(` linkStyle ${edgeIndex} stroke:#ff0000,stroke-width:2px,stroke-dasharray:5`);\n edgeIndex++;\n }\n\n lines.push('```');\n\n return lines.join('\\n');\n}\n","import * as fs from 'node:fs/promises';\nimport type { Graph, LockFile, GraphDiff, ModuleEdge } from '../types.js';\n\nconst LOCK_VERSION = '1';\n\nexport function graphToLock(graph: Graph): LockFile {\n const modules = graph.modules.map(m => m.name).sort();\n \n const edges = graph.edges\n .map(e => ({\n from: e.from,\n to: e.to,\n weight: e.weight,\n }))\n .sort((a, b) => {\n if (a.from !== b.from) return a.from.localeCompare(b.from);\n return a.to.localeCompare(b.to);\n });\n\n const externalDeps: Record<string, string[]> = {};\n for (const module of graph.modules) {\n if (module.externalDeps.length > 0) {\n externalDeps[module.name] = module.externalDeps.sort();\n }\n }\n\n return {\n version: LOCK_VERSION,\n modules,\n edges,\n externalDeps,\n };\n}\n\nexport async function writeLockFile(filePath: string, lock: LockFile): Promise<void> {\n const content = JSON.stringify(lock, null, 2) + '\\n';\n await fs.writeFile(filePath, content, 'utf-8');\n}\n\nexport async function readLockFile(filePath: string): Promise<LockFile | null> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\nexport function diffLocks(oldLock: LockFile | null, newLock: LockFile, newGraph?: Graph): GraphDiff {\n const oldEdges = oldLock?.edges || [];\n const newEdges = newLock.edges;\n\n const oldEdgeSet = new Set(oldEdges.map(edgeKey));\n const newEdgeSet = new Set(newEdges.map(edgeKey));\n\n // Build a map from edge key to full edge with locations (B6)\n const edgeLocationMap = new Map<string, ModuleEdge>();\n if (newGraph) {\n for (const edge of newGraph.edges) {\n edgeLocationMap.set(edgeKey(edge), edge);\n }\n }\n\n const added: ModuleEdge[] = [];\n const removed: ModuleEdge[] = [];\n\n for (const edge of newEdges) {\n if (!oldEdgeSet.has(edgeKey(edge))) {\n const fullEdge = edgeLocationMap.get(edgeKey(edge));\n added.push({\n from: edge.from,\n to: edge.to,\n weight: edge.weight,\n locations: fullEdge?.locations || [],\n });\n }\n }\n\n for (const edge of oldEdges) {\n if (!newEdgeSet.has(edgeKey(edge))) {\n removed.push({\n from: edge.from,\n to: edge.to,\n weight: edge.weight,\n locations: [],\n });\n }\n }\n\n const newCycles = detectNewCycles(oldLock, newLock);\n\n return {\n added,\n removed,\n newCycles,\n };\n}\n\nfunction edgeKey(edge: { from: string; to: string }): string {\n return `${edge.from}->${edge.to}`;\n}\n\nfunction detectNewCycles(oldLock: LockFile | null, newLock: LockFile): string[][] {\n if (!oldLock) {\n return [];\n }\n\n const oldCycles = findCyclesInLock(oldLock);\n const newCycles = findCyclesInLock(newLock);\n\n const oldCycleSet = new Set(oldCycles.map(cycleKey));\n const result: string[][] = [];\n\n for (const cycle of newCycles) {\n if (!oldCycleSet.has(cycleKey(cycle))) {\n result.push(cycle);\n }\n }\n\n return result;\n}\n\nfunction findCyclesInLock(lock: LockFile): string[][] {\n const graph = new Map<string, string[]>();\n\n for (const module of lock.modules) {\n graph.set(module, []);\n }\n\n for (const edge of lock.edges) {\n if (!graph.has(edge.from)) {\n graph.set(edge.from, []);\n }\n graph.get(edge.from)!.push(edge.to);\n }\n\n return tarjan(graph);\n}\n\nfunction tarjan(graph: Map<string, string[]>): string[][] {\n let index = 0;\n const stack: string[] = [];\n const onStack = new Set<string>();\n const indices = new Map<string, number>();\n const lowlinks = new Map<string, number>();\n const sccs: string[][] = [];\n\n function strongConnect(v: string): void {\n indices.set(v, index);\n lowlinks.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n const neighbors = graph.get(v) || [];\n for (const w of neighbors) {\n if (!indices.has(w)) {\n strongConnect(w);\n lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));\n } else if (onStack.has(w)) {\n lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));\n }\n }\n\n if (lowlinks.get(v) === indices.get(v)) {\n const scc: string[] = [];\n let w: string;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n\n if (scc.length > 1) {\n sccs.push(scc.sort());\n }\n }\n }\n\n for (const v of graph.keys()) {\n if (!indices.has(v)) {\n strongConnect(v);\n }\n }\n\n return sccs;\n}\n\nfunction cycleKey(cycle: string[]): string {\n return cycle.sort().join('->');\n}\n","import type { Config, ModuleEdge, GraphDiff } from '../types.js';\n\nexport interface RuleViolation {\n rule: string;\n edge: ModuleEdge;\n message: string;\n}\n\nexport function checkRules(\n edges: ModuleEdge[],\n config: Config\n): RuleViolation[] {\n const violations: RuleViolation[] = [];\n\n if (!config.rules) {\n return violations;\n }\n\n for (const rule of config.rules) {\n if (rule.deny) {\n const ruleViolations = checkDenyRule(edges, rule.deny);\n violations.push(...ruleViolations);\n }\n }\n\n return violations;\n}\n\nfunction checkDenyRule(\n edges: ModuleEdge[],\n deny: { from: string; to: string }\n): RuleViolation[] {\n const violations: RuleViolation[] = [];\n\n for (const edge of edges) {\n if (matchesPattern(edge.from, deny.from) && matchesPattern(edge.to, deny.to)) {\n violations.push({\n rule: `deny: ${deny.from} → ${deny.to}`,\n edge,\n message: `Module ${edge.from} is not allowed to depend on ${edge.to}`,\n });\n }\n }\n\n return violations;\n}\n\nfunction matchesPattern(modulePath: string, pattern: string): boolean {\n // If pattern ends with /**, it should match the directory itself and anything under it\n // e.g., \"ui/**\" should match \"src/ui\", \"ui\", \"foo/ui\", and \"src/ui/components\"\n if (pattern.endsWith('/**')) {\n const basePattern = pattern.slice(0, -3); // Remove the /**\n const regex = patternToRegex(basePattern);\n \n // Match if the module path ends with the pattern (e.g., \"src/ui\" ends with \"ui\")\n // or contains the pattern as a segment (e.g., \"src/ui/button\" contains \"ui\")\n if (regex.test(modulePath) || regex.test(modulePath + '/')) {\n return true;\n }\n \n // Also check if the module path ends with the base pattern\n const parts = modulePath.split('/');\n for (let i = 0; i < parts.length; i++) {\n const segment = parts.slice(i).join('/');\n if (regex.test(segment) || regex.test(segment + '/')) {\n return true;\n }\n }\n }\n \n // Standard glob matching\n const regex = patternToRegex(pattern);\n return regex.test(modulePath) || regex.test(modulePath + '/');\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n const regexStr = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/\\*\\*/g, '___DOUBLESTAR___')\n .replace(/\\*/g, '[^/]*')\n .replace(/___DOUBLESTAR___/g, '.*');\n\n return new RegExp(`^${regexStr}$`);\n}\n\nexport function shouldFailCheck(\n diff: GraphDiff,\n violations: RuleViolation[],\n config: Config\n): boolean {\n if (config.mode === 'gate') {\n if (diff.added.length > 0 || diff.removed.length > 0) {\n return true;\n }\n }\n\n return violations.length > 0;\n}\n"],"mappings":"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","names":["require","visitNode","getLocation","path","getModuleName","parts","fs","path","fs","tarjan","regex","patternToRegex"]}
|
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
resolveImports,
|
|
13
13
|
writeArchitectureFile,
|
|
14
14
|
writeLockFile
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-QUFBKU64.js";
|
|
16
16
|
|
|
17
17
|
// src/cli/index.ts
|
|
18
18
|
import * as fs from "fs/promises";
|
|
@@ -38,7 +38,23 @@ async function runCLI() {
|
|
|
38
38
|
case "init":
|
|
39
39
|
await initCommand(rootDir);
|
|
40
40
|
break;
|
|
41
|
+
case "help":
|
|
42
|
+
case "--help":
|
|
43
|
+
case "-h":
|
|
44
|
+
console.log(`Usage: archmap [command]
|
|
45
|
+
|
|
46
|
+
Commands:
|
|
47
|
+
render Generate ARCHITECTURE.md and archmap.lock.json
|
|
48
|
+
diff [--base] Show diff against base branch (default: main)
|
|
49
|
+
check Check for unapproved changes
|
|
50
|
+
accept Accept current changes and update lock
|
|
51
|
+
init Initialize archmap in this repository
|
|
52
|
+
`);
|
|
53
|
+
process.exit(0);
|
|
54
|
+
break;
|
|
41
55
|
default:
|
|
56
|
+
console.error(`Unknown command: ${command}
|
|
57
|
+
`);
|
|
42
58
|
console.log(`Usage: archmap [command]
|
|
43
59
|
|
|
44
60
|
Commands:
|
|
@@ -88,7 +104,7 @@ async function diffCommand(rootDir, args) {
|
|
|
88
104
|
const diff = diffLocks(baseLock, currentLock, currentGraph);
|
|
89
105
|
console.log("\nChanges:");
|
|
90
106
|
console.log(` +${diff.added.length} new edges`);
|
|
91
|
-
console.log(`
|
|
107
|
+
console.log(` ${diff.removed.length > 0 ? "-" : ""}${diff.removed.length} removed edges`);
|
|
92
108
|
if (diff.added.length > 0) {
|
|
93
109
|
console.log("\nAdded edges:");
|
|
94
110
|
for (const edge of diff.added) {
|
|
@@ -132,7 +148,7 @@ async function checkCommand(rootDir) {
|
|
|
132
148
|
}
|
|
133
149
|
if (diff.added.length > 0 || diff.removed.length > 0) {
|
|
134
150
|
console.log("\u274C Unapproved changes detected:");
|
|
135
|
-
console.log(` +${diff.added.length} new edges,
|
|
151
|
+
console.log(` +${diff.added.length} new edges, ${diff.removed.length > 0 ? "-" : ""}${diff.removed.length} removed edges`);
|
|
136
152
|
if (diff.added.length > 0) {
|
|
137
153
|
console.log("\nAdded edges:");
|
|
138
154
|
for (const edge of diff.added) {
|
|
@@ -167,8 +183,6 @@ async function initCommand(rootDir) {
|
|
|
167
183
|
|
|
168
184
|
on:
|
|
169
185
|
pull_request:
|
|
170
|
-
push:
|
|
171
|
-
branches: [main]
|
|
172
186
|
|
|
173
187
|
permissions:
|
|
174
188
|
contents: write
|
|
@@ -179,14 +193,9 @@ jobs:
|
|
|
179
193
|
runs-on: ubuntu-latest
|
|
180
194
|
steps:
|
|
181
195
|
- uses: actions/checkout@v4
|
|
182
|
-
|
|
183
|
-
- uses: actions/setup-node@v4
|
|
184
196
|
with:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
- run: npx @jatingargiitk/archmap render
|
|
188
|
-
|
|
189
|
-
- run: npx @jatingargiitk/archmap check || true
|
|
197
|
+
fetch-depth: 0
|
|
198
|
+
- uses: jatingargiitk/archmap@v0
|
|
190
199
|
`;
|
|
191
200
|
await fs.writeFile(workflowPath, workflow, "utf-8");
|
|
192
201
|
await renderCommand(rootDir);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/index.ts","../src/cli.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { extractTypeScriptImports, extractPythonImports } from '../parser/index.js';\nimport { resolveImports, loadTsConfig, findWorkspaces } from '../resolver/index.js';\nimport { buildGraph } from '../graph/index.js';\nimport { writeArchitectureFile } from '../render/index.js';\nimport { graphToLock, writeLockFile, readLockFile, diffLocks } from '../lock/index.js';\nimport { checkRules } from '../rules/index.js';\nimport type { Config } from '../types.js';\n\nexport async function runCLI(): Promise<void> {\n const args = process.argv.slice(2);\n const command = args[0] || 'render';\n\n const rootDir = process.cwd();\n\n switch (command) {\n case 'render':\n await renderCommand(rootDir);\n break;\n case 'diff':\n await diffCommand(rootDir, args);\n break;\n case 'check':\n await checkCommand(rootDir);\n break;\n case 'accept':\n await acceptCommand(rootDir);\n break;\n case 'init':\n await initCommand(rootDir);\n break;\n default:\n console.log(`Usage: archmap [command]\n\nCommands:\n render Generate ARCHITECTURE.md and archmap.lock.json\n diff [--base] Show diff against base branch (default: main)\n check Check for unapproved changes\n accept Accept current changes and update lock\n init Initialize archmap in this repository\n`);\n process.exit(1);\n }\n}\n\nasync function renderCommand(rootDir: string): Promise<void> {\n console.log('🔍 Analyzing architecture...');\n \n const graph = await analyzeRepo(rootDir);\n \n await writeArchitectureFile(\n path.join(rootDir, 'ARCHITECTURE.md'),\n graph\n );\n \n const lock = graphToLock(graph);\n await writeLockFile(path.join(rootDir, 'archmap.lock.json'), lock);\n \n console.log('✅ Generated ARCHITECTURE.md and archmap.lock.json');\n console.log(` ${graph.modules.length} modules, ${graph.edges.length} edges`);\n \n if (graph.cycles.length > 0) {\n console.log(` ⚠️ ${graph.cycles.length} cycle(s) detected`);\n }\n}\n\nasync function diffCommand(rootDir: string, args: string[]): Promise<void> {\n const baseArg = args.indexOf('--base');\n const base = baseArg !== -1 && args[baseArg + 1] ? args[baseArg + 1] : 'main';\n \n console.log(`📊 Computing diff against ${base}...`);\n \n const currentGraph = await analyzeRepo(rootDir);\n const currentLock = graphToLock(currentGraph);\n \n let baseLock = await readLockFile(path.join(rootDir, 'archmap.lock.json'));\n \n if (!baseLock) {\n try {\n const baseLockContent = execSync(\n `git show ${base}:archmap.lock.json`,\n { cwd: rootDir, encoding: 'utf-8' }\n );\n baseLock = JSON.parse(baseLockContent);\n } catch {\n console.log(`⚠️ No lock file found in ${base} branch`);\n baseLock = null;\n }\n }\n \n const diff = diffLocks(baseLock, currentLock, currentGraph);\n \n console.log('\\nChanges:');\n console.log(` +${diff.added.length} new edges`);\n console.log(` -${diff.removed.length} removed edges`);\n \n if (diff.added.length > 0) {\n console.log('\\nAdded edges:');\n for (const edge of diff.added) {\n // Show locations (B6)\n const locationStr = edge.locations.length > 0 \n ? ` (${edge.locations[0].file}:${edge.locations[0].line})`\n : '';\n console.log(` + ${edge.from} → ${edge.to}${locationStr}`);\n }\n }\n \n if (diff.removed.length > 0) {\n console.log('\\nRemoved edges:');\n for (const edge of diff.removed) {\n console.log(` - ${edge.from} → ${edge.to}`);\n }\n }\n \n if (diff.newCycles.length > 0) {\n console.log(`\\n⚠️ ${diff.newCycles.length} new cycle(s) detected:`);\n for (const cycle of diff.newCycles) {\n console.log(` ${cycle.join(' → ')}`);\n }\n }\n}\n\nasync function checkCommand(rootDir: string): Promise<void> {\n console.log('🔍 Checking for unapproved changes...');\n \n const config = await loadConfig(rootDir);\n const currentGraph = await analyzeRepo(rootDir);\n const currentLock = graphToLock(currentGraph);\n \n const committedLock = await readLockFile(path.join(rootDir, 'archmap.lock.json'));\n \n if (!committedLock) {\n console.log('❌ No lock file found. Run `archmap accept` to create one.');\n process.exit(1);\n }\n \n const diff = diffLocks(committedLock, currentLock, currentGraph);\n const violations = checkRules(currentGraph.edges, config);\n \n if (violations.length > 0) {\n console.log('❌ Rule violations detected:');\n for (const violation of violations) {\n console.log(` ${violation.message}`);\n console.log(` Rule: ${violation.rule}`);\n }\n process.exit(1);\n }\n \n // CLI check always fails on unapproved changes, regardless of mode\n if (diff.added.length > 0 || diff.removed.length > 0) {\n console.log('❌ Unapproved changes detected:');\n console.log(` +${diff.added.length} new edges, -${diff.removed.length} removed edges`);\n if (diff.added.length > 0) {\n console.log('\\nAdded edges:');\n for (const edge of diff.added) {\n // Show locations (B6)\n const locationStr = edge.locations.length > 0 \n ? ` (${edge.locations[0].file}:${edge.locations[0].line})`\n : '';\n console.log(` + ${edge.from} → ${edge.to}${locationStr}`);\n }\n }\n console.log('\\nRun `archmap diff` to see details');\n console.log('Run `archmap accept` to approve these changes');\n process.exit(1);\n }\n \n console.log('✅ No unapproved changes');\n}\n\nasync function acceptCommand(rootDir: string): Promise<void> {\n console.log('✅ Accepting current architecture...');\n \n const graph = await analyzeRepo(rootDir);\n \n await writeArchitectureFile(\n path.join(rootDir, 'ARCHITECTURE.md'),\n graph\n );\n \n const lock = graphToLock(graph);\n await writeLockFile(path.join(rootDir, 'archmap.lock.json'), lock);\n \n console.log('✅ Updated ARCHITECTURE.md and archmap.lock.json');\n console.log(' Remember to commit these changes');\n}\n\nasync function initCommand(rootDir: string): Promise<void> {\n console.log('🚀 Initializing archmap...');\n \n const workflowDir = path.join(rootDir, '.github', 'workflows');\n await fs.mkdir(workflowDir, { recursive: true });\n \n const workflowPath = path.join(workflowDir, 'archmap.yml');\n \n const workflow = `name: archmap\n\non:\n pull_request:\n push:\n branches: [main]\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n archmap:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n \n - uses: actions/setup-node@v4\n with:\n node-version: '20'\n \n - run: npx @jatingargiitk/archmap render\n \n - run: npx @jatingargiitk/archmap check || true\n`;\n \n await fs.writeFile(workflowPath, workflow, 'utf-8');\n \n await renderCommand(rootDir);\n \n console.log('✅ archmap initialized!');\n console.log(' Created:');\n console.log(' - .github/workflows/archmap.yml');\n console.log(' - ARCHITECTURE.md');\n console.log(' - archmap.lock.json');\n console.log('\\n Next steps:');\n console.log(' 1. Review the generated files');\n console.log(' 2. Commit them to your repository');\n console.log(' 3. The GitHub Action will run on every PR');\n}\n\nasync function analyzeRepo(rootDir: string): Promise<any> {\n const config = await loadConfig(rootDir);\n \n const files = await findSourceFiles(rootDir, config.ignore || []);\n \n // Filter files to only those in module roots (B4)\n const moduleConfig = config.modules || {};\n const roots = moduleConfig.roots || ['src', 'packages/*', 'apps/*'];\n const filteredFiles = files.filter(file => matchesAnyRoot(file, roots));\n \n const allImports = [];\n const allFiles: string[] = [];\n \n for (const file of filteredFiles) {\n const fullPath = path.join(rootDir, file);\n const content = await fs.readFile(fullPath, 'utf-8');\n \n let imports;\n if (file.endsWith('.ts') || file.endsWith('.tsx') || file.endsWith('.js') || file.endsWith('.jsx')) {\n imports = await extractTypeScriptImports(file, content);\n } else if (file.endsWith('.py')) {\n imports = await extractPythonImports(file, content);\n } else {\n continue;\n }\n \n allImports.push(imports);\n allFiles.push(file);\n }\n \n const tsconfig = await loadTsConfig(rootDir);\n const workspaces = await findWorkspaces(rootDir);\n \n const resolved = await resolveImports(allImports, {\n rootDir,\n tsconfig: tsconfig || undefined,\n workspaces: workspaces.length > 0 ? workspaces : undefined,\n });\n \n const graph = buildGraph(resolved, allFiles, moduleConfig);\n \n return graph;\n}\n\nfunction matchesAnyRoot(file: string, roots: string[]): boolean {\n const normalized = file.replace(/\\\\/g, '/');\n \n for (const root of roots) {\n if (root.endsWith('/*')) {\n const base = root.slice(0, -2);\n if (normalized.startsWith(base + '/')) {\n return true;\n }\n } else {\n if (normalized.startsWith(root + '/') || normalized === root) {\n return true;\n }\n }\n }\n \n return false;\n}\n\nasync function findSourceFiles(rootDir: string, ignore: string[]): Promise<string[]> {\n const files: string[] = [];\n \n // Load .gitignore patterns (B4)\n const gitignorePatterns = await loadGitignore(rootDir);\n \n const ignorePatterns = [\n 'node_modules',\n 'node_modules/**',\n '**/node_modules/**',\n 'dist',\n 'dist/**',\n '**/dist/**',\n 'build',\n 'build/**',\n '**/build/**',\n '.git',\n '.git/**',\n '**/.git/**',\n '**/coverage/**',\n '**/*.test.*',\n '**/*.spec.*',\n '**/__tests__/**',\n // Ignore root-level config files (B4)\n '*.config.*',\n '*.json',\n '*.md',\n '*.yml',\n '*.yaml',\n '.eslintrc.*',\n '.gitignore',\n 'LICENSE',\n ...gitignorePatterns,\n ...ignore,\n ];\n \n async function walk(dir: string): Promise<void> {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n \n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = path.relative(rootDir, fullPath);\n \n if (shouldIgnore(relativePath, ignorePatterns)) {\n continue;\n }\n \n if (entry.isDirectory()) {\n await walk(fullPath);\n } else if (entry.isFile()) {\n if (isSourceFile(entry.name)) {\n files.push(relativePath);\n }\n }\n }\n }\n \n await walk(rootDir);\n return files;\n}\n\nasync function loadGitignore(rootDir: string): Promise<string[]> {\n try {\n const gitignorePath = path.join(rootDir, '.gitignore');\n const content = await fs.readFile(gitignorePath, 'utf-8');\n \n return content\n .split('\\n')\n .map(line => line.trim())\n .filter(line => line && !line.startsWith('#'))\n .map(pattern => {\n // Convert gitignore patterns to glob patterns\n if (pattern.endsWith('/')) {\n return pattern.slice(0, -1) + '/**';\n }\n return pattern;\n });\n } catch {\n return [];\n }\n}\n\nfunction shouldIgnore(filePath: string, patterns: string[]): boolean {\n const normalized = filePath.replace(/\\\\/g, '/');\n \n for (const pattern of patterns) {\n const regex = patternToRegex(pattern);\n if (regex.test(normalized)) {\n return true;\n }\n }\n \n return false;\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n const regexStr = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/\\*\\*/g, '___DOUBLESTAR___')\n .replace(/\\*/g, '[^/]*')\n .replace(/___DOUBLESTAR___/g, '.*');\n \n return new RegExp(`^${regexStr}$`);\n}\n\nfunction isSourceFile(name: string): boolean {\n return /\\.(ts|tsx|js|jsx|py)$/.test(name);\n}\n\nasync function loadConfig(rootDir: string): Promise<Config> {\n const configPath = path.join(rootDir, 'archmap.yml');\n \n try {\n const content = await fs.readFile(configPath, 'utf-8');\n const yaml = await import('js-yaml');\n return yaml.load(content) as Config;\n } catch {\n return {};\n }\n}\n","import { runCLI } from './cli/index.js';\n\nrunCLI().catch((error) => {\n console.error('Error:', error.message);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/index.ts","../src/cli.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { extractTypeScriptImports, extractPythonImports } from '../parser/index.js';\nimport { resolveImports, loadTsConfig, findWorkspaces } from '../resolver/index.js';\nimport { buildGraph } from '../graph/index.js';\nimport { writeArchitectureFile } from '../render/index.js';\nimport { graphToLock, writeLockFile, readLockFile, diffLocks } from '../lock/index.js';\nimport { checkRules } from '../rules/index.js';\nimport type { Config } from '../types.js';\n\nexport async function runCLI(): Promise<void> {\n const args = process.argv.slice(2);\n const command = args[0] || 'render';\n\n const rootDir = process.cwd();\n\n switch (command) {\n case 'render':\n await renderCommand(rootDir);\n break;\n case 'diff':\n await diffCommand(rootDir, args);\n break;\n case 'check':\n await checkCommand(rootDir);\n break;\n case 'accept':\n await acceptCommand(rootDir);\n break;\n case 'init':\n await initCommand(rootDir);\n break;\n case 'help':\n case '--help':\n case '-h':\n console.log(`Usage: archmap [command]\n\nCommands:\n render Generate ARCHITECTURE.md and archmap.lock.json\n diff [--base] Show diff against base branch (default: main)\n check Check for unapproved changes\n accept Accept current changes and update lock\n init Initialize archmap in this repository\n`);\n process.exit(0);\n break;\n default:\n console.error(`Unknown command: ${command}\\n`);\n console.log(`Usage: archmap [command]\n\nCommands:\n render Generate ARCHITECTURE.md and archmap.lock.json\n diff [--base] Show diff against base branch (default: main)\n check Check for unapproved changes\n accept Accept current changes and update lock\n init Initialize archmap in this repository\n`);\n process.exit(1);\n }\n}\n\nasync function renderCommand(rootDir: string): Promise<void> {\n console.log('🔍 Analyzing architecture...');\n \n const graph = await analyzeRepo(rootDir);\n \n await writeArchitectureFile(\n path.join(rootDir, 'ARCHITECTURE.md'),\n graph\n );\n \n const lock = graphToLock(graph);\n await writeLockFile(path.join(rootDir, 'archmap.lock.json'), lock);\n \n console.log('✅ Generated ARCHITECTURE.md and archmap.lock.json');\n console.log(` ${graph.modules.length} modules, ${graph.edges.length} edges`);\n \n if (graph.cycles.length > 0) {\n console.log(` ⚠️ ${graph.cycles.length} cycle(s) detected`);\n }\n}\n\nasync function diffCommand(rootDir: string, args: string[]): Promise<void> {\n const baseArg = args.indexOf('--base');\n const base = baseArg !== -1 && args[baseArg + 1] ? args[baseArg + 1] : 'main';\n \n console.log(`📊 Computing diff against ${base}...`);\n \n const currentGraph = await analyzeRepo(rootDir);\n const currentLock = graphToLock(currentGraph);\n \n let baseLock = await readLockFile(path.join(rootDir, 'archmap.lock.json'));\n \n if (!baseLock) {\n try {\n const baseLockContent = execSync(\n `git show ${base}:archmap.lock.json`,\n { cwd: rootDir, encoding: 'utf-8' }\n );\n baseLock = JSON.parse(baseLockContent);\n } catch {\n console.log(`⚠️ No lock file found in ${base} branch`);\n baseLock = null;\n }\n }\n \n const diff = diffLocks(baseLock, currentLock, currentGraph);\n \n console.log('\\nChanges:');\n console.log(` +${diff.added.length} new edges`);\n console.log(` ${diff.removed.length > 0 ? '-' : ''}${diff.removed.length} removed edges`);\n \n if (diff.added.length > 0) {\n console.log('\\nAdded edges:');\n for (const edge of diff.added) {\n // Show locations (B6)\n const locationStr = edge.locations.length > 0 \n ? ` (${edge.locations[0].file}:${edge.locations[0].line})`\n : '';\n console.log(` + ${edge.from} → ${edge.to}${locationStr}`);\n }\n }\n \n if (diff.removed.length > 0) {\n console.log('\\nRemoved edges:');\n for (const edge of diff.removed) {\n console.log(` - ${edge.from} → ${edge.to}`);\n }\n }\n \n if (diff.newCycles.length > 0) {\n console.log(`\\n⚠️ ${diff.newCycles.length} new cycle(s) detected:`);\n for (const cycle of diff.newCycles) {\n console.log(` ${cycle.join(' → ')}`);\n }\n }\n}\n\nasync function checkCommand(rootDir: string): Promise<void> {\n console.log('🔍 Checking for unapproved changes...');\n \n const config = await loadConfig(rootDir);\n const currentGraph = await analyzeRepo(rootDir);\n const currentLock = graphToLock(currentGraph);\n \n const committedLock = await readLockFile(path.join(rootDir, 'archmap.lock.json'));\n \n if (!committedLock) {\n console.log('❌ No lock file found. Run `archmap accept` to create one.');\n process.exit(1);\n }\n \n const diff = diffLocks(committedLock, currentLock, currentGraph);\n const violations = checkRules(currentGraph.edges, config);\n \n if (violations.length > 0) {\n console.log('❌ Rule violations detected:');\n for (const violation of violations) {\n console.log(` ${violation.message}`);\n console.log(` Rule: ${violation.rule}`);\n }\n process.exit(1);\n }\n \n // CLI check always fails on unapproved changes, regardless of mode\n if (diff.added.length > 0 || diff.removed.length > 0) {\n console.log('❌ Unapproved changes detected:');\n console.log(` +${diff.added.length} new edges, ${diff.removed.length > 0 ? '-' : ''}${diff.removed.length} removed edges`);\n if (diff.added.length > 0) {\n console.log('\\nAdded edges:');\n for (const edge of diff.added) {\n // Show locations (B6)\n const locationStr = edge.locations.length > 0 \n ? ` (${edge.locations[0].file}:${edge.locations[0].line})`\n : '';\n console.log(` + ${edge.from} → ${edge.to}${locationStr}`);\n }\n }\n console.log('\\nRun `archmap diff` to see details');\n console.log('Run `archmap accept` to approve these changes');\n process.exit(1);\n }\n \n console.log('✅ No unapproved changes');\n}\n\nasync function acceptCommand(rootDir: string): Promise<void> {\n console.log('✅ Accepting current architecture...');\n \n const graph = await analyzeRepo(rootDir);\n \n await writeArchitectureFile(\n path.join(rootDir, 'ARCHITECTURE.md'),\n graph\n );\n \n const lock = graphToLock(graph);\n await writeLockFile(path.join(rootDir, 'archmap.lock.json'), lock);\n \n console.log('✅ Updated ARCHITECTURE.md and archmap.lock.json');\n console.log(' Remember to commit these changes');\n}\n\nasync function initCommand(rootDir: string): Promise<void> {\n console.log('🚀 Initializing archmap...');\n \n const workflowDir = path.join(rootDir, '.github', 'workflows');\n await fs.mkdir(workflowDir, { recursive: true });\n \n const workflowPath = path.join(workflowDir, 'archmap.yml');\n \n const workflow = `name: archmap\n\non:\n pull_request:\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n archmap:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n - uses: jatingargiitk/archmap@v0\n`;\n \n await fs.writeFile(workflowPath, workflow, 'utf-8');\n \n await renderCommand(rootDir);\n \n console.log('✅ archmap initialized!');\n console.log(' Created:');\n console.log(' - .github/workflows/archmap.yml');\n console.log(' - ARCHITECTURE.md');\n console.log(' - archmap.lock.json');\n console.log('\\n Next steps:');\n console.log(' 1. Review the generated files');\n console.log(' 2. Commit them to your repository');\n console.log(' 3. The GitHub Action will run on every PR');\n}\n\nasync function analyzeRepo(rootDir: string): Promise<any> {\n const config = await loadConfig(rootDir);\n \n const files = await findSourceFiles(rootDir, config.ignore || []);\n \n // Filter files to only those in module roots (B4)\n const moduleConfig = config.modules || {};\n const roots = moduleConfig.roots || ['src', 'packages/*', 'apps/*'];\n const filteredFiles = files.filter(file => matchesAnyRoot(file, roots));\n \n const allImports = [];\n const allFiles: string[] = [];\n \n for (const file of filteredFiles) {\n const fullPath = path.join(rootDir, file);\n const content = await fs.readFile(fullPath, 'utf-8');\n \n let imports;\n if (file.endsWith('.ts') || file.endsWith('.tsx') || file.endsWith('.js') || file.endsWith('.jsx')) {\n imports = await extractTypeScriptImports(file, content);\n } else if (file.endsWith('.py')) {\n imports = await extractPythonImports(file, content);\n } else {\n continue;\n }\n \n allImports.push(imports);\n allFiles.push(file);\n }\n \n const tsconfig = await loadTsConfig(rootDir);\n const workspaces = await findWorkspaces(rootDir);\n \n const resolved = await resolveImports(allImports, {\n rootDir,\n tsconfig: tsconfig || undefined,\n workspaces: workspaces.length > 0 ? workspaces : undefined,\n });\n \n const graph = buildGraph(resolved, allFiles, moduleConfig);\n \n return graph;\n}\n\nfunction matchesAnyRoot(file: string, roots: string[]): boolean {\n const normalized = file.replace(/\\\\/g, '/');\n \n for (const root of roots) {\n if (root.endsWith('/*')) {\n const base = root.slice(0, -2);\n if (normalized.startsWith(base + '/')) {\n return true;\n }\n } else {\n if (normalized.startsWith(root + '/') || normalized === root) {\n return true;\n }\n }\n }\n \n return false;\n}\n\nasync function findSourceFiles(rootDir: string, ignore: string[]): Promise<string[]> {\n const files: string[] = [];\n \n // Load .gitignore patterns (B4)\n const gitignorePatterns = await loadGitignore(rootDir);\n \n const ignorePatterns = [\n 'node_modules',\n 'node_modules/**',\n '**/node_modules/**',\n 'dist',\n 'dist/**',\n '**/dist/**',\n 'build',\n 'build/**',\n '**/build/**',\n '.git',\n '.git/**',\n '**/.git/**',\n '**/coverage/**',\n '**/*.test.*',\n '**/*.spec.*',\n '**/__tests__/**',\n // Ignore root-level config files (B4)\n '*.config.*',\n '*.json',\n '*.md',\n '*.yml',\n '*.yaml',\n '.eslintrc.*',\n '.gitignore',\n 'LICENSE',\n ...gitignorePatterns,\n ...ignore,\n ];\n \n async function walk(dir: string): Promise<void> {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n \n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = path.relative(rootDir, fullPath);\n \n if (shouldIgnore(relativePath, ignorePatterns)) {\n continue;\n }\n \n if (entry.isDirectory()) {\n await walk(fullPath);\n } else if (entry.isFile()) {\n if (isSourceFile(entry.name)) {\n files.push(relativePath);\n }\n }\n }\n }\n \n await walk(rootDir);\n return files;\n}\n\nasync function loadGitignore(rootDir: string): Promise<string[]> {\n try {\n const gitignorePath = path.join(rootDir, '.gitignore');\n const content = await fs.readFile(gitignorePath, 'utf-8');\n \n return content\n .split('\\n')\n .map(line => line.trim())\n .filter(line => line && !line.startsWith('#'))\n .map(pattern => {\n // Convert gitignore patterns to glob patterns\n if (pattern.endsWith('/')) {\n return pattern.slice(0, -1) + '/**';\n }\n return pattern;\n });\n } catch {\n return [];\n }\n}\n\nfunction shouldIgnore(filePath: string, patterns: string[]): boolean {\n const normalized = filePath.replace(/\\\\/g, '/');\n \n for (const pattern of patterns) {\n const regex = patternToRegex(pattern);\n if (regex.test(normalized)) {\n return true;\n }\n }\n \n return false;\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n const regexStr = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/\\*\\*/g, '___DOUBLESTAR___')\n .replace(/\\*/g, '[^/]*')\n .replace(/___DOUBLESTAR___/g, '.*');\n \n return new RegExp(`^${regexStr}$`);\n}\n\nfunction isSourceFile(name: string): boolean {\n return /\\.(ts|tsx|js|jsx|py)$/.test(name);\n}\n\nasync function loadConfig(rootDir: string): Promise<Config> {\n const configPath = path.join(rootDir, 'archmap.yml');\n \n try {\n const content = await fs.readFile(configPath, 'utf-8');\n const yaml = await import('js-yaml');\n return yaml.load(content) as Config;\n } catch {\n return {};\n }\n}\n","import { runCLI } from './cli/index.js';\n\nrunCLI().catch((error) => {\n console.error('Error:', error.message);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -599,8 +599,9 @@ function renderMermaidGraph(graph) {
|
|
|
599
599
|
for (const edge of edgesSorted) {
|
|
600
600
|
const fromId = sanitizeId(edge.from);
|
|
601
601
|
const toId = sanitizeId(edge.to);
|
|
602
|
-
const label = edge.weight > 1 ?
|
|
603
|
-
|
|
602
|
+
const label = edge.weight > 1 ? `|${edge.weight}|` : "";
|
|
603
|
+
const arrow = label ? `-->${label}` : "-->";
|
|
604
|
+
lines.push(` ${fromId}[${edge.from}] ${arrow} ${toId}[${edge.to}]`);
|
|
604
605
|
}
|
|
605
606
|
if (edgesSorted.length === 0) {
|
|
606
607
|
for (const module of graph.modules.slice(0, 5)) {
|
|
@@ -674,17 +675,20 @@ function renderDeltaDiagram(addedEdges, removedEdges, touchedModules) {
|
|
|
674
675
|
const id = sanitizeId(module);
|
|
675
676
|
lines.push(` ${id}[${module}]`);
|
|
676
677
|
}
|
|
678
|
+
let edgeIndex = 0;
|
|
677
679
|
for (const edge of addedEdges) {
|
|
678
680
|
const fromId = sanitizeId(edge.from);
|
|
679
681
|
const toId = sanitizeId(edge.to);
|
|
680
682
|
lines.push(` ${fromId} ====> ${toId}`);
|
|
681
|
-
lines.push(` linkStyle ${
|
|
683
|
+
lines.push(` linkStyle ${edgeIndex} stroke:#00ff00,stroke-width:3px`);
|
|
684
|
+
edgeIndex++;
|
|
682
685
|
}
|
|
683
686
|
for (const edge of removedEdges) {
|
|
684
687
|
const fromId = sanitizeId(edge.from);
|
|
685
688
|
const toId = sanitizeId(edge.to);
|
|
686
689
|
lines.push(` ${fromId} -.-> ${toId}`);
|
|
687
|
-
lines.push(` linkStyle ${
|
|
690
|
+
lines.push(` linkStyle ${edgeIndex} stroke:#ff0000,stroke-width:2px,stroke-dasharray:5`);
|
|
691
|
+
edgeIndex++;
|
|
688
692
|
}
|
|
689
693
|
lines.push("```");
|
|
690
694
|
return lines.join("\n");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/parser/tree-sitter-loader.ts","../src/parser/typescript-extractor.ts","../src/parser/python-extractor.ts","../src/resolver/index.ts","../src/graph/index.ts","../src/render/index.ts","../src/lock/index.ts","../src/index.ts"],"sourcesContent":["import { Parser, Language } from 'web-tree-sitter';\n\nlet parserInitialized = false;\n\nexport async function initParser(): Promise<void> {\n if (parserInitialized) return;\n await Parser.init();\n parserInitialized = true;\n}\n\nconst languageCache = new Map<string, Language>();\n\nexport async function loadLanguage(name: 'typescript' | 'python'): Promise<Language> {\n if (languageCache.has(name)) {\n return languageCache.get(name)!;\n }\n\n await initParser();\n \n const wasmPath = await getWasmPath(name);\n const language = await Language.load(wasmPath);\n languageCache.set(name, language);\n \n return language;\n}\n\nasync function getWasmPath(name: string): Promise<string> {\n try {\n const { createRequire } = await import('node:module');\n const require = createRequire(import.meta.url);\n const wasmPath = require.resolve(`tree-sitter-${name}/tree-sitter-${name}.wasm`);\n return wasmPath;\n } catch {\n return `node_modules/tree-sitter-${name}/tree-sitter-${name}.wasm`;\n }\n}\n\nexport async function parseFile(content: string, language: 'typescript' | 'python'): Promise<import('web-tree-sitter').Tree> {\n const lang = await loadLanguage(language);\n const parser = new Parser();\n parser.setLanguage(lang);\n const tree = parser.parse(content);\n if (!tree) {\n throw new Error(`Failed to parse file with language: ${language}`);\n }\n return tree;\n}\n","import type { Node } from 'web-tree-sitter';\nimport type { Import, FileImports, Location } from '../types.js';\nimport { parseFile } from './tree-sitter-loader.js';\n\nexport async function extractTypeScriptImports(filePath: string, content: string): Promise<FileImports> {\n const tree = await parseFile(content, 'typescript');\n const imports: Import[] = [];\n\n visitNode(tree.rootNode, (node) => {\n if (node.type === 'import_statement') {\n const imp = extractImportStatement(node, filePath, content);\n if (imp) imports.push(imp);\n } else if (node.type === 'call_expression') {\n const imp = extractDynamicImport(node, filePath, content);\n if (imp) imports.push(imp);\n }\n });\n\n return { file: filePath, imports };\n}\n\nfunction extractImportStatement(node: Node, file: string, content: string): Import | null {\n const sourceNode = node.childForFieldName('source');\n if (!sourceNode) return null;\n\n const from = extractStringValue(sourceNode, content);\n if (!from) return null;\n\n return {\n from,\n location: getLocation(node, file),\n };\n}\n\nfunction extractDynamicImport(node: Node, file: string, content: string): Import | null {\n const func = node.childForFieldName('function');\n if (!func || func.text !== 'import') return null;\n\n const args = node.childForFieldName('arguments');\n if (!args) return null;\n\n const firstArg = args.children.find((c: Node) => c.type === 'string' || c.type === 'template_string');\n if (!firstArg) return null;\n\n const from = extractStringValue(firstArg, content);\n if (!from) return null;\n\n return {\n from,\n isDynamic: true,\n location: getLocation(node, file),\n };\n}\n\nfunction extractStringValue(node: Node, _content: string): string | null {\n const text = node.text;\n if (text.startsWith('\"') || text.startsWith(\"'\")) {\n return text.slice(1, -1);\n }\n if (text.startsWith('`')) {\n const withoutBackticks = text.slice(1, -1);\n if (!withoutBackticks.includes('${')) {\n return withoutBackticks;\n }\n }\n return null;\n}\n\nfunction getLocation(node: Node, file: string): Location {\n return {\n file,\n line: node.startPosition.row + 1,\n column: node.startPosition.column,\n };\n}\n\nfunction visitNode(node: Node, visitor: (node: Node) => void): void {\n visitor(node);\n for (const child of node.children) {\n visitNode(child, visitor);\n }\n}\n\nexport async function extractJavaScriptImports(filePath: string, content: string): Promise<FileImports> {\n return extractTypeScriptImports(filePath, content);\n}\n","import type { Node } from 'web-tree-sitter';\nimport type { Import, FileImports, Location } from '../types.js';\nimport { parseFile } from './tree-sitter-loader.js';\n\nexport async function extractPythonImports(filePath: string, content: string): Promise<FileImports> {\n const tree = await parseFile(content, 'python');\n const imports: Import[] = [];\n\n visitNode(tree.rootNode, (node) => {\n if (node.type === 'import_statement' || node.type === 'import_from_statement') {\n const imp = extractImport(node, filePath, content);\n if (imp) imports.push(imp);\n }\n });\n\n return { file: filePath, imports };\n}\n\nfunction extractImport(node: Node, file: string, _content: string): Import | null {\n if (node.type === 'import_statement') {\n return extractPlainImport(node, file);\n } else if (node.type === 'import_from_statement') {\n return extractFromImport(node, file);\n }\n return null;\n}\n\nfunction extractPlainImport(node: Node, file: string): Import | null {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return null;\n\n const moduleName = getModuleName(nameNode);\n if (!moduleName) return null;\n\n return {\n from: moduleName,\n location: getLocation(node, file),\n };\n}\n\nfunction extractFromImport(node: Node, file: string): Import | null {\n const moduleNode = node.childForFieldName('module_name');\n if (!moduleNode) return null;\n\n const moduleName = getModuleName(moduleNode);\n if (!moduleName) return null;\n\n return {\n from: moduleName,\n location: getLocation(node, file),\n };\n}\n\nfunction getModuleName(node: Node): string | null {\n if (node.type === 'dotted_name') {\n return node.text;\n } else if (node.type === 'relative_import') {\n return node.text;\n } else if (node.type === 'aliased_import') {\n const nameChild = node.childForFieldName('name');\n if (nameChild) {\n return getModuleName(nameChild);\n }\n }\n return node.text || null;\n}\n\nfunction getLocation(node: Node, file: string): Location {\n return {\n file,\n line: node.startPosition.row + 1,\n column: node.startPosition.column,\n };\n}\n\nfunction visitNode(node: Node, visitor: (node: Node) => void): void {\n visitor(node);\n for (const child of node.children) {\n visitNode(child, visitor);\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { FileImports, ResolvedImport } from '../types.js';\n\nexport interface ResolverConfig {\n rootDir: string;\n tsconfig?: TsConfigPaths;\n workspaces?: string[];\n}\n\nexport interface TsConfigPaths {\n baseUrl?: string;\n paths?: Record<string, string[]>;\n}\n\nexport async function resolveImports(\n fileImports: FileImports[],\n config: ResolverConfig\n): Promise<ResolvedImport[]> {\n const resolved: ResolvedImport[] = [];\n\n for (const { file, imports } of fileImports) {\n for (const imp of imports) {\n const resolvedPath = await resolveImport(imp.from, file, config);\n if (resolvedPath) {\n resolved.push({\n from: file,\n to: resolvedPath,\n location: imp.location,\n });\n }\n }\n }\n\n return resolved;\n}\n\nasync function resolveImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (isExternalModule(importPath)) {\n return null;\n }\n\n const fileExt = path.extname(fromFile);\n const isPython = fileExt === '.py';\n\n if (isPython) {\n return resolvePythonImport(importPath, fromFile, config);\n }\n\n return resolveTypeScriptImport(importPath, fromFile, config);\n}\n\nfunction isExternalModule(importPath: string): boolean {\n return !importPath.startsWith('.') && !importPath.startsWith('/');\n}\n\nasync function resolveTypeScriptImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (importPath.startsWith('.')) {\n return resolveRelativePath(importPath, fromFile, config);\n }\n\n if (config.tsconfig?.paths) {\n const aliasResolved = await resolvePathAlias(importPath, config);\n if (aliasResolved) return aliasResolved;\n }\n\n if (config.workspaces) {\n const workspaceResolved = await resolveWorkspace(importPath, config);\n if (workspaceResolved) return workspaceResolved;\n }\n\n return null;\n}\n\nasync function resolveRelativePath(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n const dir = path.dirname(fromFile);\n let candidatePath = path.join(dir, importPath);\n\n // Handle ESM-style TypeScript imports: map .js/.mjs/.cjs to their TS sources (B3)\n const esmExt = path.extname(candidatePath);\n if (esmExt === '.js' || esmExt === '.mjs' || esmExt === '.cjs') {\n const basePath = candidatePath.slice(0, -esmExt.length);\n \n // Map .js -> .ts/.tsx, .mjs -> .mts, .cjs -> .cts\n const tsExtensions = esmExt === '.mjs' ? ['.mts'] :\n esmExt === '.cjs' ? ['.cts'] :\n ['.ts', '.tsx'];\n \n for (const tsExt of tsExtensions) {\n const tsPath = basePath + tsExt;\n if (await fileExists(path.join(config.rootDir, tsPath))) {\n return tsPath;\n }\n }\n \n // If no TS source found, continue with normal resolution\n candidatePath = basePath;\n }\n\n const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts'];\n \n for (const ext of extensions) {\n const withExt = candidatePath + ext;\n if (await fileExists(path.join(config.rootDir, withExt))) {\n return withExt;\n }\n }\n\n for (const ext of ['index.ts', 'index.tsx', 'index.js', 'index.jsx']) {\n const indexPath = path.join(candidatePath, ext);\n if (await fileExists(path.join(config.rootDir, indexPath))) {\n return indexPath;\n }\n }\n\n return null;\n}\n\nasync function resolvePathAlias(\n importPath: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (!config.tsconfig?.paths) return null;\n\n const { paths, baseUrl = '.' } = config.tsconfig;\n\n for (const [pattern, mappings] of Object.entries(paths)) {\n const regex = patternToRegex(pattern);\n const match = importPath.match(regex);\n\n if (match) {\n for (const mapping of mappings) {\n const resolved = mapping.replace('*', match[1] || '');\n const fullPath = path.join(baseUrl, resolved);\n \n const candidate = await resolveRelativePath(`./${fullPath}`, '', {\n ...config,\n rootDir: config.rootDir,\n });\n \n if (candidate) return candidate;\n\n if (await fileExists(path.join(config.rootDir, fullPath))) {\n return fullPath;\n }\n }\n }\n }\n\n return null;\n}\n\nasync function resolveWorkspace(\n importPath: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (!config.workspaces) return null;\n\n for (const workspace of config.workspaces) {\n const packageJsonPath = path.join(config.rootDir, workspace, 'package.json');\n \n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n \n if (pkg.name === importPath || importPath.startsWith(pkg.name + '/')) {\n const subpath = importPath.slice(pkg.name.length + 1) || '.';\n const mainFile = pkg.main || pkg.module || 'index.js';\n \n if (subpath === '.') {\n return path.join(workspace, mainFile);\n }\n \n const resolved = await resolveRelativePath(`./${subpath}`, workspace, {\n ...config,\n rootDir: config.rootDir,\n });\n \n if (resolved) return resolved;\n }\n } catch {\n // Skip if package.json doesn't exist\n }\n }\n\n return null;\n}\n\nasync function resolvePythonImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (importPath.startsWith('.')) {\n return resolvePythonRelative(importPath, fromFile, config);\n }\n\n const parts = importPath.split('.');\n const possiblePaths = [\n path.join(...parts) + '.py',\n path.join(...parts, '__init__.py'),\n path.join('src', ...parts) + '.py',\n path.join('src', ...parts, '__init__.py'),\n ];\n\n for (const possiblePath of possiblePaths) {\n if (await fileExists(path.join(config.rootDir, possiblePath))) {\n return possiblePath;\n }\n }\n\n return null;\n}\n\nasync function resolvePythonRelative(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n const dir = path.dirname(fromFile);\n let targetDir = dir;\n\n const dots = importPath.match(/^\\.+/)?.[0] || '.';\n const rest = importPath.slice(dots.length);\n\n for (let i = 1; i < dots.length; i++) {\n targetDir = path.dirname(targetDir);\n }\n\n if (rest) {\n const parts = rest.split('.');\n targetDir = path.join(targetDir, ...parts);\n }\n\n const candidatePath = targetDir + '.py';\n if (await fileExists(path.join(config.rootDir, candidatePath))) {\n return candidatePath;\n }\n\n const initPath = path.join(targetDir, '__init__.py');\n if (await fileExists(path.join(config.rootDir, initPath))) {\n return initPath;\n }\n\n return null;\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const withWildcard = escaped.replace(/\\\\\\*/g, '(.*)');\n return new RegExp(`^${withWildcard}$`);\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function loadTsConfig(rootDir: string): Promise<TsConfigPaths | null> {\n const tsconfigPath = path.join(rootDir, 'tsconfig.json');\n \n try {\n const content = await fs.readFile(tsconfigPath, 'utf-8');\n const tsconfig = JSON.parse(content);\n \n return {\n baseUrl: tsconfig.compilerOptions?.baseUrl,\n paths: tsconfig.compilerOptions?.paths,\n };\n } catch {\n return null;\n }\n}\n\nexport async function findWorkspaces(rootDir: string): Promise<string[]> {\n const packageJsonPath = path.join(rootDir, 'package.json');\n \n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n \n if (pkg.workspaces) {\n const patterns = Array.isArray(pkg.workspaces) \n ? pkg.workspaces \n : pkg.workspaces.packages || [];\n \n const workspaces: string[] = [];\n for (const pattern of patterns) {\n if (!pattern.includes('*')) {\n workspaces.push(pattern);\n } else {\n const base = pattern.replace('/*', '');\n try {\n const entries = await fs.readdir(path.join(rootDir, base));\n for (const entry of entries) {\n const fullPath = path.join(base, entry);\n const pkgPath = path.join(rootDir, fullPath, 'package.json');\n if (await fileExists(pkgPath)) {\n workspaces.push(fullPath);\n }\n }\n } catch {\n // Skip if base doesn't exist\n }\n }\n }\n \n return workspaces;\n }\n } catch {\n // No package.json or not a workspace\n }\n \n return [];\n}\n","import * as path from 'node:path';\nimport type { ResolvedImport, Module, ModuleEdge, Graph } from '../types.js';\n\nexport interface ModuleConfig {\n roots?: string[];\n depth?: number;\n}\n\nexport function buildGraph(\n resolvedImports: ResolvedImport[],\n allFiles: string[],\n config: ModuleConfig = {}\n): Graph {\n const { roots = ['src', 'packages/*', 'apps/*'], depth = 1 } = config;\n\n const fileToModule = new Map<string, string>();\n \n for (const file of allFiles) {\n const moduleName = getModuleName(file, roots, depth);\n fileToModule.set(file, moduleName);\n }\n\n const moduleFiles = new Map<string, Set<string>>();\n for (const [file, module] of fileToModule) {\n if (!moduleFiles.has(module)) {\n moduleFiles.set(module, new Set());\n }\n moduleFiles.get(module)!.add(file);\n }\n\n const edgeMap = new Map<string, Map<string, ModuleEdge>>();\n const externalDeps = new Map<string, Set<string>>();\n\n for (const resolved of resolvedImports) {\n const fromModule = fileToModule.get(resolved.from);\n const toModule = fileToModule.get(resolved.to);\n\n if (!fromModule || !toModule || fromModule === toModule) {\n continue;\n }\n\n if (!edgeMap.has(fromModule)) {\n edgeMap.set(fromModule, new Map());\n }\n\n const fromEdges = edgeMap.get(fromModule)!;\n \n if (!fromEdges.has(toModule)) {\n fromEdges.set(toModule, {\n from: fromModule,\n to: toModule,\n weight: 0,\n locations: [],\n });\n }\n\n const edge = fromEdges.get(toModule)!;\n edge.weight++;\n edge.locations.push(resolved.location);\n }\n\n const edges: ModuleEdge[] = [];\n for (const fromEdges of edgeMap.values()) {\n for (const edge of fromEdges.values()) {\n edges.push(edge);\n }\n }\n\n const fanIn = new Map<string, number>();\n const fanOut = new Map<string, number>();\n\n for (const edge of edges) {\n fanOut.set(edge.from, (fanOut.get(edge.from) || 0) + 1);\n fanIn.set(edge.to, (fanIn.get(edge.to) || 0) + 1);\n }\n\n const modules: Module[] = [];\n for (const [moduleName, files] of moduleFiles) {\n modules.push({\n name: moduleName,\n files: Array.from(files).sort(),\n fanIn: fanIn.get(moduleName) || 0,\n fanOut: fanOut.get(moduleName) || 0,\n externalDeps: Array.from(externalDeps.get(moduleName) || []).sort(),\n });\n }\n\n modules.sort((a, b) => a.name.localeCompare(b.name));\n\n const cycles = detectCycles(edges, modules.map(m => m.name));\n\n return {\n modules,\n edges,\n cycles,\n };\n}\n\nfunction getModuleName(file: string, roots: string[], depth: number): string {\n const normalized = file.replace(/\\\\/g, '/');\n \n for (const root of roots) {\n if (root.endsWith('/*')) {\n const base = root.slice(0, -2);\n if (normalized.startsWith(base + '/')) {\n const rest = normalized.slice(base.length + 1);\n const parts = rest.split('/');\n if (parts.length > 0) {\n return path.join(base, parts[0]);\n }\n }\n } else {\n if (normalized.startsWith(root + '/')) {\n const rest = normalized.slice(root.length + 1);\n const parts = rest.split('/');\n if (depth === 0) {\n return root;\n }\n const moduleParts = parts.slice(0, depth);\n return path.join(root, ...moduleParts);\n }\n }\n }\n\n const parts = normalized.split('/');\n if (parts.length > 0) {\n return parts[0];\n }\n\n return normalized;\n}\n\nexport function detectCycles(edges: ModuleEdge[], modules: string[]): string[][] {\n const graph = new Map<string, string[]>();\n \n for (const module of modules) {\n graph.set(module, []);\n }\n\n for (const edge of edges) {\n if (!graph.has(edge.from)) {\n graph.set(edge.from, []);\n }\n graph.get(edge.from)!.push(edge.to);\n }\n\n return tarjan(graph);\n}\n\nfunction tarjan(graph: Map<string, string[]>): string[][] {\n let index = 0;\n const stack: string[] = [];\n const onStack = new Set<string>();\n const indices = new Map<string, number>();\n const lowlinks = new Map<string, number>();\n const sccs: string[][] = [];\n\n function strongConnect(v: string): void {\n indices.set(v, index);\n lowlinks.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n const neighbors = graph.get(v) || [];\n for (const w of neighbors) {\n if (!indices.has(w)) {\n strongConnect(w);\n lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));\n } else if (onStack.has(w)) {\n lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));\n }\n }\n\n if (lowlinks.get(v) === indices.get(v)) {\n const scc: string[] = [];\n let w: string;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n\n if (scc.length > 1) {\n sccs.push(scc.sort());\n }\n }\n }\n\n for (const v of graph.keys()) {\n if (!indices.has(v)) {\n strongConnect(v);\n }\n }\n\n return sccs;\n}\n\nexport function computeLOC(files: Map<string, string>): Map<string, number> {\n const loc = new Map<string, number>();\n\n for (const [file, content] of files) {\n const lines = content.split('\\n').filter(line => {\n const trimmed = line.trim();\n return trimmed.length > 0 && !trimmed.startsWith('//') && !trimmed.startsWith('#');\n });\n loc.set(file, lines.length);\n }\n\n return loc;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Graph, Module, ModuleEdge } from '../types.js';\n\nconst START_MARKER = '<!-- archmap:start -->';\nconst END_MARKER = '<!-- archmap:end -->';\n\nexport function renderMermaid(graph: Graph): string {\n const sections: string[] = [];\n\n sections.push('# Architecture\\n');\n sections.push(START_MARKER);\n sections.push('');\n sections.push('## Module Dependencies\\n');\n sections.push('```mermaid');\n sections.push(renderMermaidGraph(graph));\n sections.push('```\\n');\n\n sections.push('## Modules\\n');\n sections.push(renderModuleTable(graph.modules));\n sections.push('');\n\n if (graph.cycles.length > 0) {\n sections.push('## ⚠️ Cycles Detected\\n');\n sections.push(renderCycles(graph.cycles));\n sections.push('');\n }\n\n sections.push(END_MARKER);\n\n return sections.join('\\n');\n}\n\nfunction renderMermaidGraph(graph: Graph): string {\n const lines: string[] = ['flowchart LR'];\n\n const edgesSorted = [...graph.edges].sort((a, b) => {\n if (a.from !== b.from) return a.from.localeCompare(b.from);\n return a.to.localeCompare(b.to);\n });\n\n for (const edge of edgesSorted) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n const label = edge.weight > 1 ? ` |${edge.weight}| ` : ' ';\n lines.push(` ${fromId}[${edge.from}]${label}-->${label}${toId}[${edge.to}]`);\n }\n\n if (edgesSorted.length === 0) {\n for (const module of graph.modules.slice(0, 5)) {\n const id = sanitizeId(module.name);\n lines.push(` ${id}[${module.name}]`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction renderModuleTable(modules: Module[]): string {\n const lines: string[] = [\n '| Module | Files | Fan-In | Fan-Out | External Deps |',\n '|--------|-------|--------|---------|---------------|',\n ];\n\n const sorted = [...modules].sort((a, b) => {\n const fanA = a.fanIn + a.fanOut;\n const fanB = b.fanIn + b.fanOut;\n if (fanB !== fanA) return fanB - fanA;\n return a.name.localeCompare(b.name);\n });\n\n for (const module of sorted) {\n const externalDeps = module.externalDeps.length > 0\n ? module.externalDeps.slice(0, 3).join(', ') +\n (module.externalDeps.length > 3 ? '...' : '')\n : '-';\n\n lines.push(\n `| \\`${module.name}\\` | ${module.files.length} | ${module.fanIn} | ${module.fanOut} | ${externalDeps} |`\n );\n }\n\n return lines.join('\\n');\n}\n\nfunction renderCycles(cycles: string[][]): string {\n const lines: string[] = [];\n\n for (let i = 0; i < cycles.length; i++) {\n const cycle = cycles[i];\n lines.push(`${i + 1}. ${cycle.map(m => `\\`${m}\\``).join(' → ')}`);\n }\n\n return lines.join('\\n');\n}\n\nfunction sanitizeId(name: string): string {\n return name.replace(/[^a-zA-Z0-9_]/g, '_');\n}\n\nexport async function writeArchitectureFile(\n filePath: string,\n graph: Graph\n): Promise<void> {\n let existingContent = '';\n \n try {\n existingContent = await fs.readFile(filePath, 'utf-8');\n } catch {\n // File doesn't exist, that's fine\n }\n\n const newContent = renderMermaid(graph);\n\n let finalContent: string;\n\n if (existingContent) {\n const startIndex = existingContent.indexOf(START_MARKER);\n const endIndex = existingContent.indexOf(END_MARKER);\n\n if (startIndex !== -1 && endIndex !== -1) {\n const before = existingContent.slice(0, startIndex);\n const after = existingContent.slice(endIndex + END_MARKER.length);\n \n const extractedSection = newContent.slice(\n newContent.indexOf(START_MARKER),\n newContent.indexOf(END_MARKER) + END_MARKER.length\n );\n\n finalContent = before + extractedSection + after;\n } else {\n finalContent = newContent + '\\n\\n' + existingContent;\n }\n } else {\n finalContent = newContent;\n }\n\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, finalContent, 'utf-8');\n}\n\nexport function renderDeltaDiagram(\n addedEdges: ModuleEdge[],\n removedEdges: ModuleEdge[],\n touchedModules: Set<string>\n): string {\n const lines: string[] = ['```mermaid', 'flowchart LR'];\n \n for (const module of touchedModules) {\n const id = sanitizeId(module);\n lines.push(` ${id}[${module}]`);\n }\n\n for (const edge of addedEdges) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n lines.push(` ${fromId} ====> ${toId}`);\n lines.push(` linkStyle ${lines.length - 2} stroke:#00ff00,stroke-width:3px`);\n }\n\n for (const edge of removedEdges) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n lines.push(` ${fromId} -.-> ${toId}`);\n lines.push(` linkStyle ${lines.length - 2} stroke:#ff0000,stroke-width:2px,stroke-dasharray:5`);\n }\n\n lines.push('```');\n\n return lines.join('\\n');\n}\n","import * as fs from 'node:fs/promises';\nimport type { Graph, LockFile, GraphDiff, ModuleEdge } from '../types.js';\n\nconst LOCK_VERSION = '1';\n\nexport function graphToLock(graph: Graph): LockFile {\n const modules = graph.modules.map(m => m.name).sort();\n \n const edges = graph.edges\n .map(e => ({\n from: e.from,\n to: e.to,\n weight: e.weight,\n }))\n .sort((a, b) => {\n if (a.from !== b.from) return a.from.localeCompare(b.from);\n return a.to.localeCompare(b.to);\n });\n\n const externalDeps: Record<string, string[]> = {};\n for (const module of graph.modules) {\n if (module.externalDeps.length > 0) {\n externalDeps[module.name] = module.externalDeps.sort();\n }\n }\n\n return {\n version: LOCK_VERSION,\n modules,\n edges,\n externalDeps,\n };\n}\n\nexport async function writeLockFile(filePath: string, lock: LockFile): Promise<void> {\n const content = JSON.stringify(lock, null, 2) + '\\n';\n await fs.writeFile(filePath, content, 'utf-8');\n}\n\nexport async function readLockFile(filePath: string): Promise<LockFile | null> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\nexport function diffLocks(oldLock: LockFile | null, newLock: LockFile, newGraph?: Graph): GraphDiff {\n const oldEdges = oldLock?.edges || [];\n const newEdges = newLock.edges;\n\n const oldEdgeSet = new Set(oldEdges.map(edgeKey));\n const newEdgeSet = new Set(newEdges.map(edgeKey));\n\n // Build a map from edge key to full edge with locations (B6)\n const edgeLocationMap = new Map<string, ModuleEdge>();\n if (newGraph) {\n for (const edge of newGraph.edges) {\n edgeLocationMap.set(edgeKey(edge), edge);\n }\n }\n\n const added: ModuleEdge[] = [];\n const removed: ModuleEdge[] = [];\n\n for (const edge of newEdges) {\n if (!oldEdgeSet.has(edgeKey(edge))) {\n const fullEdge = edgeLocationMap.get(edgeKey(edge));\n added.push({\n from: edge.from,\n to: edge.to,\n weight: edge.weight,\n locations: fullEdge?.locations || [],\n });\n }\n }\n\n for (const edge of oldEdges) {\n if (!newEdgeSet.has(edgeKey(edge))) {\n removed.push({\n from: edge.from,\n to: edge.to,\n weight: edge.weight,\n locations: [],\n });\n }\n }\n\n const newCycles = detectNewCycles(oldLock, newLock);\n\n return {\n added,\n removed,\n newCycles,\n };\n}\n\nfunction edgeKey(edge: { from: string; to: string }): string {\n return `${edge.from}->${edge.to}`;\n}\n\nfunction detectNewCycles(oldLock: LockFile | null, newLock: LockFile): string[][] {\n if (!oldLock) {\n return [];\n }\n\n const oldCycles = findCyclesInLock(oldLock);\n const newCycles = findCyclesInLock(newLock);\n\n const oldCycleSet = new Set(oldCycles.map(cycleKey));\n const result: string[][] = [];\n\n for (const cycle of newCycles) {\n if (!oldCycleSet.has(cycleKey(cycle))) {\n result.push(cycle);\n }\n }\n\n return result;\n}\n\nfunction findCyclesInLock(lock: LockFile): string[][] {\n const graph = new Map<string, string[]>();\n\n for (const module of lock.modules) {\n graph.set(module, []);\n }\n\n for (const edge of lock.edges) {\n if (!graph.has(edge.from)) {\n graph.set(edge.from, []);\n }\n graph.get(edge.from)!.push(edge.to);\n }\n\n return tarjan(graph);\n}\n\nfunction tarjan(graph: Map<string, string[]>): string[][] {\n let index = 0;\n const stack: string[] = [];\n const onStack = new Set<string>();\n const indices = new Map<string, number>();\n const lowlinks = new Map<string, number>();\n const sccs: string[][] = [];\n\n function strongConnect(v: string): void {\n indices.set(v, index);\n lowlinks.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n const neighbors = graph.get(v) || [];\n for (const w of neighbors) {\n if (!indices.has(w)) {\n strongConnect(w);\n lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));\n } else if (onStack.has(w)) {\n lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));\n }\n }\n\n if (lowlinks.get(v) === indices.get(v)) {\n const scc: string[] = [];\n let w: string;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n\n if (scc.length > 1) {\n sccs.push(scc.sort());\n }\n }\n }\n\n for (const v of graph.keys()) {\n if (!indices.has(v)) {\n strongConnect(v);\n }\n }\n\n return sccs;\n}\n\nfunction cycleKey(cycle: string[]): string {\n return cycle.sort().join('->');\n}\n","export const version = '0.1.0';\n\nexport * from './parser/index.js';\nexport * from './resolver/index.js';\nexport * from './graph/index.js';\nexport * from './render/index.js';\nexport * from './lock/index.js';\nexport * from './types.js';\n"],"mappings":"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","names":["require","visitNode","getLocation","path","getModuleName","parts","fs","path","fs","tarjan"]}
|
|
1
|
+
{"version":3,"sources":["../src/parser/tree-sitter-loader.ts","../src/parser/typescript-extractor.ts","../src/parser/python-extractor.ts","../src/resolver/index.ts","../src/graph/index.ts","../src/render/index.ts","../src/lock/index.ts","../src/index.ts"],"sourcesContent":["import { Parser, Language } from 'web-tree-sitter';\n\nlet parserInitialized = false;\n\nexport async function initParser(): Promise<void> {\n if (parserInitialized) return;\n await Parser.init();\n parserInitialized = true;\n}\n\nconst languageCache = new Map<string, Language>();\n\nexport async function loadLanguage(name: 'typescript' | 'python'): Promise<Language> {\n if (languageCache.has(name)) {\n return languageCache.get(name)!;\n }\n\n await initParser();\n \n const wasmPath = await getWasmPath(name);\n const language = await Language.load(wasmPath);\n languageCache.set(name, language);\n \n return language;\n}\n\nasync function getWasmPath(name: string): Promise<string> {\n try {\n const { createRequire } = await import('node:module');\n const require = createRequire(import.meta.url);\n const wasmPath = require.resolve(`tree-sitter-${name}/tree-sitter-${name}.wasm`);\n return wasmPath;\n } catch {\n return `node_modules/tree-sitter-${name}/tree-sitter-${name}.wasm`;\n }\n}\n\nexport async function parseFile(content: string, language: 'typescript' | 'python'): Promise<import('web-tree-sitter').Tree> {\n const lang = await loadLanguage(language);\n const parser = new Parser();\n parser.setLanguage(lang);\n const tree = parser.parse(content);\n if (!tree) {\n throw new Error(`Failed to parse file with language: ${language}`);\n }\n return tree;\n}\n","import type { Node } from 'web-tree-sitter';\nimport type { Import, FileImports, Location } from '../types.js';\nimport { parseFile } from './tree-sitter-loader.js';\n\nexport async function extractTypeScriptImports(filePath: string, content: string): Promise<FileImports> {\n const tree = await parseFile(content, 'typescript');\n const imports: Import[] = [];\n\n visitNode(tree.rootNode, (node) => {\n if (node.type === 'import_statement') {\n const imp = extractImportStatement(node, filePath, content);\n if (imp) imports.push(imp);\n } else if (node.type === 'call_expression') {\n const imp = extractDynamicImport(node, filePath, content);\n if (imp) imports.push(imp);\n }\n });\n\n return { file: filePath, imports };\n}\n\nfunction extractImportStatement(node: Node, file: string, content: string): Import | null {\n const sourceNode = node.childForFieldName('source');\n if (!sourceNode) return null;\n\n const from = extractStringValue(sourceNode, content);\n if (!from) return null;\n\n return {\n from,\n location: getLocation(node, file),\n };\n}\n\nfunction extractDynamicImport(node: Node, file: string, content: string): Import | null {\n const func = node.childForFieldName('function');\n if (!func || func.text !== 'import') return null;\n\n const args = node.childForFieldName('arguments');\n if (!args) return null;\n\n const firstArg = args.children.find((c: Node) => c.type === 'string' || c.type === 'template_string');\n if (!firstArg) return null;\n\n const from = extractStringValue(firstArg, content);\n if (!from) return null;\n\n return {\n from,\n isDynamic: true,\n location: getLocation(node, file),\n };\n}\n\nfunction extractStringValue(node: Node, _content: string): string | null {\n const text = node.text;\n if (text.startsWith('\"') || text.startsWith(\"'\")) {\n return text.slice(1, -1);\n }\n if (text.startsWith('`')) {\n const withoutBackticks = text.slice(1, -1);\n if (!withoutBackticks.includes('${')) {\n return withoutBackticks;\n }\n }\n return null;\n}\n\nfunction getLocation(node: Node, file: string): Location {\n return {\n file,\n line: node.startPosition.row + 1,\n column: node.startPosition.column,\n };\n}\n\nfunction visitNode(node: Node, visitor: (node: Node) => void): void {\n visitor(node);\n for (const child of node.children) {\n visitNode(child, visitor);\n }\n}\n\nexport async function extractJavaScriptImports(filePath: string, content: string): Promise<FileImports> {\n return extractTypeScriptImports(filePath, content);\n}\n","import type { Node } from 'web-tree-sitter';\nimport type { Import, FileImports, Location } from '../types.js';\nimport { parseFile } from './tree-sitter-loader.js';\n\nexport async function extractPythonImports(filePath: string, content: string): Promise<FileImports> {\n const tree = await parseFile(content, 'python');\n const imports: Import[] = [];\n\n visitNode(tree.rootNode, (node) => {\n if (node.type === 'import_statement' || node.type === 'import_from_statement') {\n const imp = extractImport(node, filePath, content);\n if (imp) imports.push(imp);\n }\n });\n\n return { file: filePath, imports };\n}\n\nfunction extractImport(node: Node, file: string, _content: string): Import | null {\n if (node.type === 'import_statement') {\n return extractPlainImport(node, file);\n } else if (node.type === 'import_from_statement') {\n return extractFromImport(node, file);\n }\n return null;\n}\n\nfunction extractPlainImport(node: Node, file: string): Import | null {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return null;\n\n const moduleName = getModuleName(nameNode);\n if (!moduleName) return null;\n\n return {\n from: moduleName,\n location: getLocation(node, file),\n };\n}\n\nfunction extractFromImport(node: Node, file: string): Import | null {\n const moduleNode = node.childForFieldName('module_name');\n if (!moduleNode) return null;\n\n const moduleName = getModuleName(moduleNode);\n if (!moduleName) return null;\n\n return {\n from: moduleName,\n location: getLocation(node, file),\n };\n}\n\nfunction getModuleName(node: Node): string | null {\n if (node.type === 'dotted_name') {\n return node.text;\n } else if (node.type === 'relative_import') {\n return node.text;\n } else if (node.type === 'aliased_import') {\n const nameChild = node.childForFieldName('name');\n if (nameChild) {\n return getModuleName(nameChild);\n }\n }\n return node.text || null;\n}\n\nfunction getLocation(node: Node, file: string): Location {\n return {\n file,\n line: node.startPosition.row + 1,\n column: node.startPosition.column,\n };\n}\n\nfunction visitNode(node: Node, visitor: (node: Node) => void): void {\n visitor(node);\n for (const child of node.children) {\n visitNode(child, visitor);\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { FileImports, ResolvedImport } from '../types.js';\n\nexport interface ResolverConfig {\n rootDir: string;\n tsconfig?: TsConfigPaths;\n workspaces?: string[];\n}\n\nexport interface TsConfigPaths {\n baseUrl?: string;\n paths?: Record<string, string[]>;\n}\n\nexport async function resolveImports(\n fileImports: FileImports[],\n config: ResolverConfig\n): Promise<ResolvedImport[]> {\n const resolved: ResolvedImport[] = [];\n\n for (const { file, imports } of fileImports) {\n for (const imp of imports) {\n const resolvedPath = await resolveImport(imp.from, file, config);\n if (resolvedPath) {\n resolved.push({\n from: file,\n to: resolvedPath,\n location: imp.location,\n });\n }\n }\n }\n\n return resolved;\n}\n\nasync function resolveImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (isExternalModule(importPath)) {\n return null;\n }\n\n const fileExt = path.extname(fromFile);\n const isPython = fileExt === '.py';\n\n if (isPython) {\n return resolvePythonImport(importPath, fromFile, config);\n }\n\n return resolveTypeScriptImport(importPath, fromFile, config);\n}\n\nfunction isExternalModule(importPath: string): boolean {\n return !importPath.startsWith('.') && !importPath.startsWith('/');\n}\n\nasync function resolveTypeScriptImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (importPath.startsWith('.')) {\n return resolveRelativePath(importPath, fromFile, config);\n }\n\n if (config.tsconfig?.paths) {\n const aliasResolved = await resolvePathAlias(importPath, config);\n if (aliasResolved) return aliasResolved;\n }\n\n if (config.workspaces) {\n const workspaceResolved = await resolveWorkspace(importPath, config);\n if (workspaceResolved) return workspaceResolved;\n }\n\n return null;\n}\n\nasync function resolveRelativePath(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n const dir = path.dirname(fromFile);\n let candidatePath = path.join(dir, importPath);\n\n // Handle ESM-style TypeScript imports: map .js/.mjs/.cjs to their TS sources (B3)\n const esmExt = path.extname(candidatePath);\n if (esmExt === '.js' || esmExt === '.mjs' || esmExt === '.cjs') {\n const basePath = candidatePath.slice(0, -esmExt.length);\n \n // Map .js -> .ts/.tsx, .mjs -> .mts, .cjs -> .cts\n const tsExtensions = esmExt === '.mjs' ? ['.mts'] :\n esmExt === '.cjs' ? ['.cts'] :\n ['.ts', '.tsx'];\n \n for (const tsExt of tsExtensions) {\n const tsPath = basePath + tsExt;\n if (await fileExists(path.join(config.rootDir, tsPath))) {\n return tsPath;\n }\n }\n \n // If no TS source found, continue with normal resolution\n candidatePath = basePath;\n }\n\n const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts'];\n \n for (const ext of extensions) {\n const withExt = candidatePath + ext;\n if (await fileExists(path.join(config.rootDir, withExt))) {\n return withExt;\n }\n }\n\n for (const ext of ['index.ts', 'index.tsx', 'index.js', 'index.jsx']) {\n const indexPath = path.join(candidatePath, ext);\n if (await fileExists(path.join(config.rootDir, indexPath))) {\n return indexPath;\n }\n }\n\n return null;\n}\n\nasync function resolvePathAlias(\n importPath: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (!config.tsconfig?.paths) return null;\n\n const { paths, baseUrl = '.' } = config.tsconfig;\n\n for (const [pattern, mappings] of Object.entries(paths)) {\n const regex = patternToRegex(pattern);\n const match = importPath.match(regex);\n\n if (match) {\n for (const mapping of mappings) {\n const resolved = mapping.replace('*', match[1] || '');\n const fullPath = path.join(baseUrl, resolved);\n \n const candidate = await resolveRelativePath(`./${fullPath}`, '', {\n ...config,\n rootDir: config.rootDir,\n });\n \n if (candidate) return candidate;\n\n if (await fileExists(path.join(config.rootDir, fullPath))) {\n return fullPath;\n }\n }\n }\n }\n\n return null;\n}\n\nasync function resolveWorkspace(\n importPath: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (!config.workspaces) return null;\n\n for (const workspace of config.workspaces) {\n const packageJsonPath = path.join(config.rootDir, workspace, 'package.json');\n \n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n \n if (pkg.name === importPath || importPath.startsWith(pkg.name + '/')) {\n const subpath = importPath.slice(pkg.name.length + 1) || '.';\n const mainFile = pkg.main || pkg.module || 'index.js';\n \n if (subpath === '.') {\n return path.join(workspace, mainFile);\n }\n \n const resolved = await resolveRelativePath(`./${subpath}`, workspace, {\n ...config,\n rootDir: config.rootDir,\n });\n \n if (resolved) return resolved;\n }\n } catch {\n // Skip if package.json doesn't exist\n }\n }\n\n return null;\n}\n\nasync function resolvePythonImport(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n if (importPath.startsWith('.')) {\n return resolvePythonRelative(importPath, fromFile, config);\n }\n\n const parts = importPath.split('.');\n const possiblePaths = [\n path.join(...parts) + '.py',\n path.join(...parts, '__init__.py'),\n path.join('src', ...parts) + '.py',\n path.join('src', ...parts, '__init__.py'),\n ];\n\n for (const possiblePath of possiblePaths) {\n if (await fileExists(path.join(config.rootDir, possiblePath))) {\n return possiblePath;\n }\n }\n\n return null;\n}\n\nasync function resolvePythonRelative(\n importPath: string,\n fromFile: string,\n config: ResolverConfig\n): Promise<string | null> {\n const dir = path.dirname(fromFile);\n let targetDir = dir;\n\n const dots = importPath.match(/^\\.+/)?.[0] || '.';\n const rest = importPath.slice(dots.length);\n\n for (let i = 1; i < dots.length; i++) {\n targetDir = path.dirname(targetDir);\n }\n\n if (rest) {\n const parts = rest.split('.');\n targetDir = path.join(targetDir, ...parts);\n }\n\n const candidatePath = targetDir + '.py';\n if (await fileExists(path.join(config.rootDir, candidatePath))) {\n return candidatePath;\n }\n\n const initPath = path.join(targetDir, '__init__.py');\n if (await fileExists(path.join(config.rootDir, initPath))) {\n return initPath;\n }\n\n return null;\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const withWildcard = escaped.replace(/\\\\\\*/g, '(.*)');\n return new RegExp(`^${withWildcard}$`);\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function loadTsConfig(rootDir: string): Promise<TsConfigPaths | null> {\n const tsconfigPath = path.join(rootDir, 'tsconfig.json');\n \n try {\n const content = await fs.readFile(tsconfigPath, 'utf-8');\n const tsconfig = JSON.parse(content);\n \n return {\n baseUrl: tsconfig.compilerOptions?.baseUrl,\n paths: tsconfig.compilerOptions?.paths,\n };\n } catch {\n return null;\n }\n}\n\nexport async function findWorkspaces(rootDir: string): Promise<string[]> {\n const packageJsonPath = path.join(rootDir, 'package.json');\n \n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n \n if (pkg.workspaces) {\n const patterns = Array.isArray(pkg.workspaces) \n ? pkg.workspaces \n : pkg.workspaces.packages || [];\n \n const workspaces: string[] = [];\n for (const pattern of patterns) {\n if (!pattern.includes('*')) {\n workspaces.push(pattern);\n } else {\n const base = pattern.replace('/*', '');\n try {\n const entries = await fs.readdir(path.join(rootDir, base));\n for (const entry of entries) {\n const fullPath = path.join(base, entry);\n const pkgPath = path.join(rootDir, fullPath, 'package.json');\n if (await fileExists(pkgPath)) {\n workspaces.push(fullPath);\n }\n }\n } catch {\n // Skip if base doesn't exist\n }\n }\n }\n \n return workspaces;\n }\n } catch {\n // No package.json or not a workspace\n }\n \n return [];\n}\n","import * as path from 'node:path';\nimport type { ResolvedImport, Module, ModuleEdge, Graph } from '../types.js';\n\nexport interface ModuleConfig {\n roots?: string[];\n depth?: number;\n}\n\nexport function buildGraph(\n resolvedImports: ResolvedImport[],\n allFiles: string[],\n config: ModuleConfig = {}\n): Graph {\n const { roots = ['src', 'packages/*', 'apps/*'], depth = 1 } = config;\n\n const fileToModule = new Map<string, string>();\n \n for (const file of allFiles) {\n const moduleName = getModuleName(file, roots, depth);\n fileToModule.set(file, moduleName);\n }\n\n const moduleFiles = new Map<string, Set<string>>();\n for (const [file, module] of fileToModule) {\n if (!moduleFiles.has(module)) {\n moduleFiles.set(module, new Set());\n }\n moduleFiles.get(module)!.add(file);\n }\n\n const edgeMap = new Map<string, Map<string, ModuleEdge>>();\n const externalDeps = new Map<string, Set<string>>();\n\n for (const resolved of resolvedImports) {\n const fromModule = fileToModule.get(resolved.from);\n const toModule = fileToModule.get(resolved.to);\n\n if (!fromModule || !toModule || fromModule === toModule) {\n continue;\n }\n\n if (!edgeMap.has(fromModule)) {\n edgeMap.set(fromModule, new Map());\n }\n\n const fromEdges = edgeMap.get(fromModule)!;\n \n if (!fromEdges.has(toModule)) {\n fromEdges.set(toModule, {\n from: fromModule,\n to: toModule,\n weight: 0,\n locations: [],\n });\n }\n\n const edge = fromEdges.get(toModule)!;\n edge.weight++;\n edge.locations.push(resolved.location);\n }\n\n const edges: ModuleEdge[] = [];\n for (const fromEdges of edgeMap.values()) {\n for (const edge of fromEdges.values()) {\n edges.push(edge);\n }\n }\n\n const fanIn = new Map<string, number>();\n const fanOut = new Map<string, number>();\n\n for (const edge of edges) {\n fanOut.set(edge.from, (fanOut.get(edge.from) || 0) + 1);\n fanIn.set(edge.to, (fanIn.get(edge.to) || 0) + 1);\n }\n\n const modules: Module[] = [];\n for (const [moduleName, files] of moduleFiles) {\n modules.push({\n name: moduleName,\n files: Array.from(files).sort(),\n fanIn: fanIn.get(moduleName) || 0,\n fanOut: fanOut.get(moduleName) || 0,\n externalDeps: Array.from(externalDeps.get(moduleName) || []).sort(),\n });\n }\n\n modules.sort((a, b) => a.name.localeCompare(b.name));\n\n const cycles = detectCycles(edges, modules.map(m => m.name));\n\n return {\n modules,\n edges,\n cycles,\n };\n}\n\nfunction getModuleName(file: string, roots: string[], depth: number): string {\n const normalized = file.replace(/\\\\/g, '/');\n \n for (const root of roots) {\n if (root.endsWith('/*')) {\n const base = root.slice(0, -2);\n if (normalized.startsWith(base + '/')) {\n const rest = normalized.slice(base.length + 1);\n const parts = rest.split('/');\n if (parts.length > 0) {\n return path.join(base, parts[0]);\n }\n }\n } else {\n if (normalized.startsWith(root + '/')) {\n const rest = normalized.slice(root.length + 1);\n const parts = rest.split('/');\n if (depth === 0) {\n return root;\n }\n const moduleParts = parts.slice(0, depth);\n return path.join(root, ...moduleParts);\n }\n }\n }\n\n const parts = normalized.split('/');\n if (parts.length > 0) {\n return parts[0];\n }\n\n return normalized;\n}\n\nexport function detectCycles(edges: ModuleEdge[], modules: string[]): string[][] {\n const graph = new Map<string, string[]>();\n \n for (const module of modules) {\n graph.set(module, []);\n }\n\n for (const edge of edges) {\n if (!graph.has(edge.from)) {\n graph.set(edge.from, []);\n }\n graph.get(edge.from)!.push(edge.to);\n }\n\n return tarjan(graph);\n}\n\nfunction tarjan(graph: Map<string, string[]>): string[][] {\n let index = 0;\n const stack: string[] = [];\n const onStack = new Set<string>();\n const indices = new Map<string, number>();\n const lowlinks = new Map<string, number>();\n const sccs: string[][] = [];\n\n function strongConnect(v: string): void {\n indices.set(v, index);\n lowlinks.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n const neighbors = graph.get(v) || [];\n for (const w of neighbors) {\n if (!indices.has(w)) {\n strongConnect(w);\n lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));\n } else if (onStack.has(w)) {\n lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));\n }\n }\n\n if (lowlinks.get(v) === indices.get(v)) {\n const scc: string[] = [];\n let w: string;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n\n if (scc.length > 1) {\n sccs.push(scc.sort());\n }\n }\n }\n\n for (const v of graph.keys()) {\n if (!indices.has(v)) {\n strongConnect(v);\n }\n }\n\n return sccs;\n}\n\nexport function computeLOC(files: Map<string, string>): Map<string, number> {\n const loc = new Map<string, number>();\n\n for (const [file, content] of files) {\n const lines = content.split('\\n').filter(line => {\n const trimmed = line.trim();\n return trimmed.length > 0 && !trimmed.startsWith('//') && !trimmed.startsWith('#');\n });\n loc.set(file, lines.length);\n }\n\n return loc;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Graph, Module, ModuleEdge } from '../types.js';\n\nconst START_MARKER = '<!-- archmap:start -->';\nconst END_MARKER = '<!-- archmap:end -->';\n\nexport function renderMermaid(graph: Graph): string {\n const sections: string[] = [];\n\n sections.push('# Architecture\\n');\n sections.push(START_MARKER);\n sections.push('');\n sections.push('## Module Dependencies\\n');\n sections.push('```mermaid');\n sections.push(renderMermaidGraph(graph));\n sections.push('```\\n');\n\n sections.push('## Modules\\n');\n sections.push(renderModuleTable(graph.modules));\n sections.push('');\n\n if (graph.cycles.length > 0) {\n sections.push('## ⚠️ Cycles Detected\\n');\n sections.push(renderCycles(graph.cycles));\n sections.push('');\n }\n\n sections.push(END_MARKER);\n\n return sections.join('\\n');\n}\n\nfunction renderMermaidGraph(graph: Graph): string {\n const lines: string[] = ['flowchart LR'];\n\n const edgesSorted = [...graph.edges].sort((a, b) => {\n if (a.from !== b.from) return a.from.localeCompare(b.from);\n return a.to.localeCompare(b.to);\n });\n\n for (const edge of edgesSorted) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n const label = edge.weight > 1 ? `|${edge.weight}|` : '';\n const arrow = label ? `-->${label}` : '-->';\n lines.push(` ${fromId}[${edge.from}] ${arrow} ${toId}[${edge.to}]`);\n }\n\n if (edgesSorted.length === 0) {\n for (const module of graph.modules.slice(0, 5)) {\n const id = sanitizeId(module.name);\n lines.push(` ${id}[${module.name}]`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction renderModuleTable(modules: Module[]): string {\n const lines: string[] = [\n '| Module | Files | Fan-In | Fan-Out | External Deps |',\n '|--------|-------|--------|---------|---------------|',\n ];\n\n const sorted = [...modules].sort((a, b) => {\n const fanA = a.fanIn + a.fanOut;\n const fanB = b.fanIn + b.fanOut;\n if (fanB !== fanA) return fanB - fanA;\n return a.name.localeCompare(b.name);\n });\n\n for (const module of sorted) {\n const externalDeps = module.externalDeps.length > 0\n ? module.externalDeps.slice(0, 3).join(', ') +\n (module.externalDeps.length > 3 ? '...' : '')\n : '-';\n\n lines.push(\n `| \\`${module.name}\\` | ${module.files.length} | ${module.fanIn} | ${module.fanOut} | ${externalDeps} |`\n );\n }\n\n return lines.join('\\n');\n}\n\nfunction renderCycles(cycles: string[][]): string {\n const lines: string[] = [];\n\n for (let i = 0; i < cycles.length; i++) {\n const cycle = cycles[i];\n lines.push(`${i + 1}. ${cycle.map(m => `\\`${m}\\``).join(' → ')}`);\n }\n\n return lines.join('\\n');\n}\n\nfunction sanitizeId(name: string): string {\n return name.replace(/[^a-zA-Z0-9_]/g, '_');\n}\n\nexport async function writeArchitectureFile(\n filePath: string,\n graph: Graph\n): Promise<void> {\n let existingContent = '';\n \n try {\n existingContent = await fs.readFile(filePath, 'utf-8');\n } catch {\n // File doesn't exist, that's fine\n }\n\n const newContent = renderMermaid(graph);\n\n let finalContent: string;\n\n if (existingContent) {\n const startIndex = existingContent.indexOf(START_MARKER);\n const endIndex = existingContent.indexOf(END_MARKER);\n\n if (startIndex !== -1 && endIndex !== -1) {\n const before = existingContent.slice(0, startIndex);\n const after = existingContent.slice(endIndex + END_MARKER.length);\n \n const extractedSection = newContent.slice(\n newContent.indexOf(START_MARKER),\n newContent.indexOf(END_MARKER) + END_MARKER.length\n );\n\n finalContent = before + extractedSection + after;\n } else {\n finalContent = newContent + '\\n\\n' + existingContent;\n }\n } else {\n finalContent = newContent;\n }\n\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, finalContent, 'utf-8');\n}\n\nexport function renderDeltaDiagram(\n addedEdges: ModuleEdge[],\n removedEdges: ModuleEdge[],\n touchedModules: Set<string>\n): string {\n const lines: string[] = ['```mermaid', 'flowchart LR'];\n \n for (const module of touchedModules) {\n const id = sanitizeId(module);\n lines.push(` ${id}[${module}]`);\n }\n\n let edgeIndex = 0;\n\n for (const edge of addedEdges) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n lines.push(` ${fromId} ====> ${toId}`);\n lines.push(` linkStyle ${edgeIndex} stroke:#00ff00,stroke-width:3px`);\n edgeIndex++;\n }\n\n for (const edge of removedEdges) {\n const fromId = sanitizeId(edge.from);\n const toId = sanitizeId(edge.to);\n lines.push(` ${fromId} -.-> ${toId}`);\n lines.push(` linkStyle ${edgeIndex} stroke:#ff0000,stroke-width:2px,stroke-dasharray:5`);\n edgeIndex++;\n }\n\n lines.push('```');\n\n return lines.join('\\n');\n}\n","import * as fs from 'node:fs/promises';\nimport type { Graph, LockFile, GraphDiff, ModuleEdge } from '../types.js';\n\nconst LOCK_VERSION = '1';\n\nexport function graphToLock(graph: Graph): LockFile {\n const modules = graph.modules.map(m => m.name).sort();\n \n const edges = graph.edges\n .map(e => ({\n from: e.from,\n to: e.to,\n weight: e.weight,\n }))\n .sort((a, b) => {\n if (a.from !== b.from) return a.from.localeCompare(b.from);\n return a.to.localeCompare(b.to);\n });\n\n const externalDeps: Record<string, string[]> = {};\n for (const module of graph.modules) {\n if (module.externalDeps.length > 0) {\n externalDeps[module.name] = module.externalDeps.sort();\n }\n }\n\n return {\n version: LOCK_VERSION,\n modules,\n edges,\n externalDeps,\n };\n}\n\nexport async function writeLockFile(filePath: string, lock: LockFile): Promise<void> {\n const content = JSON.stringify(lock, null, 2) + '\\n';\n await fs.writeFile(filePath, content, 'utf-8');\n}\n\nexport async function readLockFile(filePath: string): Promise<LockFile | null> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\nexport function diffLocks(oldLock: LockFile | null, newLock: LockFile, newGraph?: Graph): GraphDiff {\n const oldEdges = oldLock?.edges || [];\n const newEdges = newLock.edges;\n\n const oldEdgeSet = new Set(oldEdges.map(edgeKey));\n const newEdgeSet = new Set(newEdges.map(edgeKey));\n\n // Build a map from edge key to full edge with locations (B6)\n const edgeLocationMap = new Map<string, ModuleEdge>();\n if (newGraph) {\n for (const edge of newGraph.edges) {\n edgeLocationMap.set(edgeKey(edge), edge);\n }\n }\n\n const added: ModuleEdge[] = [];\n const removed: ModuleEdge[] = [];\n\n for (const edge of newEdges) {\n if (!oldEdgeSet.has(edgeKey(edge))) {\n const fullEdge = edgeLocationMap.get(edgeKey(edge));\n added.push({\n from: edge.from,\n to: edge.to,\n weight: edge.weight,\n locations: fullEdge?.locations || [],\n });\n }\n }\n\n for (const edge of oldEdges) {\n if (!newEdgeSet.has(edgeKey(edge))) {\n removed.push({\n from: edge.from,\n to: edge.to,\n weight: edge.weight,\n locations: [],\n });\n }\n }\n\n const newCycles = detectNewCycles(oldLock, newLock);\n\n return {\n added,\n removed,\n newCycles,\n };\n}\n\nfunction edgeKey(edge: { from: string; to: string }): string {\n return `${edge.from}->${edge.to}`;\n}\n\nfunction detectNewCycles(oldLock: LockFile | null, newLock: LockFile): string[][] {\n if (!oldLock) {\n return [];\n }\n\n const oldCycles = findCyclesInLock(oldLock);\n const newCycles = findCyclesInLock(newLock);\n\n const oldCycleSet = new Set(oldCycles.map(cycleKey));\n const result: string[][] = [];\n\n for (const cycle of newCycles) {\n if (!oldCycleSet.has(cycleKey(cycle))) {\n result.push(cycle);\n }\n }\n\n return result;\n}\n\nfunction findCyclesInLock(lock: LockFile): string[][] {\n const graph = new Map<string, string[]>();\n\n for (const module of lock.modules) {\n graph.set(module, []);\n }\n\n for (const edge of lock.edges) {\n if (!graph.has(edge.from)) {\n graph.set(edge.from, []);\n }\n graph.get(edge.from)!.push(edge.to);\n }\n\n return tarjan(graph);\n}\n\nfunction tarjan(graph: Map<string, string[]>): string[][] {\n let index = 0;\n const stack: string[] = [];\n const onStack = new Set<string>();\n const indices = new Map<string, number>();\n const lowlinks = new Map<string, number>();\n const sccs: string[][] = [];\n\n function strongConnect(v: string): void {\n indices.set(v, index);\n lowlinks.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n const neighbors = graph.get(v) || [];\n for (const w of neighbors) {\n if (!indices.has(w)) {\n strongConnect(w);\n lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));\n } else if (onStack.has(w)) {\n lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));\n }\n }\n\n if (lowlinks.get(v) === indices.get(v)) {\n const scc: string[] = [];\n let w: string;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n\n if (scc.length > 1) {\n sccs.push(scc.sort());\n }\n }\n }\n\n for (const v of graph.keys()) {\n if (!indices.has(v)) {\n strongConnect(v);\n }\n }\n\n return sccs;\n}\n\nfunction cycleKey(cycle: string[]): string {\n return cycle.sort().join('->');\n}\n","export const version = '0.1.0';\n\nexport * from './parser/index.js';\nexport * from './resolver/index.js';\nexport * from './graph/index.js';\nexport * from './render/index.js';\nexport * from './lock/index.js';\nexport * from './types.js';\n"],"mappings":";AAAA,SAAS,QAAQ,gBAAgB;AAEjC,IAAI,oBAAoB;AAExB,eAAsB,aAA4B;AAChD,MAAI,kBAAmB;AACvB,QAAM,OAAO,KAAK;AAClB,sBAAoB;AACtB;AAEA,IAAM,gBAAgB,oBAAI,IAAsB;AAEhD,eAAsB,aAAa,MAAkD;AACnF,MAAI,cAAc,IAAI,IAAI,GAAG;AAC3B,WAAO,cAAc,IAAI,IAAI;AAAA,EAC/B;AAEA,QAAM,WAAW;AAEjB,QAAM,WAAW,MAAM,YAAY,IAAI;AACvC,QAAM,WAAW,MAAM,SAAS,KAAK,QAAQ;AAC7C,gBAAc,IAAI,MAAM,QAAQ;AAEhC,SAAO;AACT;AAEA,eAAe,YAAY,MAA+B;AACxD,MAAI;AACF,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,QAAa;AACpD,UAAMA,WAAU,cAAc,YAAY,GAAG;AAC7C,UAAM,WAAWA,SAAQ,QAAQ,eAAe,IAAI,gBAAgB,IAAI,OAAO;AAC/E,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,4BAA4B,IAAI,gBAAgB,IAAI;AAAA,EAC7D;AACF;AAEA,eAAsB,UAAU,SAAiB,UAA4E;AAC3H,QAAM,OAAO,MAAM,aAAa,QAAQ;AACxC,QAAM,SAAS,IAAI,OAAO;AAC1B,SAAO,YAAY,IAAI;AACvB,QAAM,OAAO,OAAO,MAAM,OAAO;AACjC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,uCAAuC,QAAQ,EAAE;AAAA,EACnE;AACA,SAAO;AACT;;;AC1CA,eAAsB,yBAAyB,UAAkB,SAAuC;AACtG,QAAM,OAAO,MAAM,UAAU,SAAS,YAAY;AAClD,QAAM,UAAoB,CAAC;AAE3B,YAAU,KAAK,UAAU,CAAC,SAAS;AACjC,QAAI,KAAK,SAAS,oBAAoB;AACpC,YAAM,MAAM,uBAAuB,MAAM,UAAU,OAAO;AAC1D,UAAI,IAAK,SAAQ,KAAK,GAAG;AAAA,IAC3B,WAAW,KAAK,SAAS,mBAAmB;AAC1C,YAAM,MAAM,qBAAqB,MAAM,UAAU,OAAO;AACxD,UAAI,IAAK,SAAQ,KAAK,GAAG;AAAA,IAC3B;AAAA,EACF,CAAC;AAED,SAAO,EAAE,MAAM,UAAU,QAAQ;AACnC;AAEA,SAAS,uBAAuB,MAAY,MAAc,SAAgC;AACxF,QAAM,aAAa,KAAK,kBAAkB,QAAQ;AAClD,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,OAAO,mBAAmB,YAAY,OAAO;AACnD,MAAI,CAAC,KAAM,QAAO;AAElB,SAAO;AAAA,IACL;AAAA,IACA,UAAU,YAAY,MAAM,IAAI;AAAA,EAClC;AACF;AAEA,SAAS,qBAAqB,MAAY,MAAc,SAAgC;AACtF,QAAM,OAAO,KAAK,kBAAkB,UAAU;AAC9C,MAAI,CAAC,QAAQ,KAAK,SAAS,SAAU,QAAO;AAE5C,QAAM,OAAO,KAAK,kBAAkB,WAAW;AAC/C,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,WAAW,KAAK,SAAS,KAAK,CAAC,MAAY,EAAE,SAAS,YAAY,EAAE,SAAS,iBAAiB;AACpG,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,OAAO,mBAAmB,UAAU,OAAO;AACjD,MAAI,CAAC,KAAM,QAAO;AAElB,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA,IACX,UAAU,YAAY,MAAM,IAAI;AAAA,EAClC;AACF;AAEA,SAAS,mBAAmB,MAAY,UAAiC;AACvE,QAAM,OAAO,KAAK;AAClB,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,GAAG;AAChD,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACzB;AACA,MAAI,KAAK,WAAW,GAAG,GAAG;AACxB,UAAM,mBAAmB,KAAK,MAAM,GAAG,EAAE;AACzC,QAAI,CAAC,iBAAiB,SAAS,IAAI,GAAG;AACpC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,MAAY,MAAwB;AACvD,SAAO;AAAA,IACL;AAAA,IACA,MAAM,KAAK,cAAc,MAAM;AAAA,IAC/B,QAAQ,KAAK,cAAc;AAAA,EAC7B;AACF;AAEA,SAAS,UAAU,MAAY,SAAqC;AAClE,UAAQ,IAAI;AACZ,aAAW,SAAS,KAAK,UAAU;AACjC,cAAU,OAAO,OAAO;AAAA,EAC1B;AACF;AAEA,eAAsB,yBAAyB,UAAkB,SAAuC;AACtG,SAAO,yBAAyB,UAAU,OAAO;AACnD;;;ACjFA,eAAsB,qBAAqB,UAAkB,SAAuC;AAClG,QAAM,OAAO,MAAM,UAAU,SAAS,QAAQ;AAC9C,QAAM,UAAoB,CAAC;AAE3B,EAAAC,WAAU,KAAK,UAAU,CAAC,SAAS;AACjC,QAAI,KAAK,SAAS,sBAAsB,KAAK,SAAS,yBAAyB;AAC7E,YAAM,MAAM,cAAc,MAAM,UAAU,OAAO;AACjD,UAAI,IAAK,SAAQ,KAAK,GAAG;AAAA,IAC3B;AAAA,EACF,CAAC;AAED,SAAO,EAAE,MAAM,UAAU,QAAQ;AACnC;AAEA,SAAS,cAAc,MAAY,MAAc,UAAiC;AAChF,MAAI,KAAK,SAAS,oBAAoB;AACpC,WAAO,mBAAmB,MAAM,IAAI;AAAA,EACtC,WAAW,KAAK,SAAS,yBAAyB;AAChD,WAAO,kBAAkB,MAAM,IAAI;AAAA,EACrC;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,MAAY,MAA6B;AACnE,QAAM,WAAW,KAAK,kBAAkB,MAAM;AAC9C,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,aAAa,cAAc,QAAQ;AACzC,MAAI,CAAC,WAAY,QAAO;AAExB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAUC,aAAY,MAAM,IAAI;AAAA,EAClC;AACF;AAEA,SAAS,kBAAkB,MAAY,MAA6B;AAClE,QAAM,aAAa,KAAK,kBAAkB,aAAa;AACvD,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,aAAa,cAAc,UAAU;AAC3C,MAAI,CAAC,WAAY,QAAO;AAExB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAUA,aAAY,MAAM,IAAI;AAAA,EAClC;AACF;AAEA,SAAS,cAAc,MAA2B;AAChD,MAAI,KAAK,SAAS,eAAe;AAC/B,WAAO,KAAK;AAAA,EACd,WAAW,KAAK,SAAS,mBAAmB;AAC1C,WAAO,KAAK;AAAA,EACd,WAAW,KAAK,SAAS,kBAAkB;AACzC,UAAM,YAAY,KAAK,kBAAkB,MAAM;AAC/C,QAAI,WAAW;AACb,aAAO,cAAc,SAAS;AAAA,IAChC;AAAA,EACF;AACA,SAAO,KAAK,QAAQ;AACtB;AAEA,SAASA,aAAY,MAAY,MAAwB;AACvD,SAAO;AAAA,IACL;AAAA,IACA,MAAM,KAAK,cAAc,MAAM;AAAA,IAC/B,QAAQ,KAAK,cAAc;AAAA,EAC7B;AACF;AAEA,SAASD,WAAU,MAAY,SAAqC;AAClE,UAAQ,IAAI;AACZ,aAAW,SAAS,KAAK,UAAU;AACjC,IAAAA,WAAU,OAAO,OAAO;AAAA,EAC1B;AACF;;;AChFA,YAAY,QAAQ;AACpB,YAAY,UAAU;AActB,eAAsB,eACpB,aACA,QAC2B;AAC3B,QAAM,WAA6B,CAAC;AAEpC,aAAW,EAAE,MAAM,QAAQ,KAAK,aAAa;AAC3C,eAAW,OAAO,SAAS;AACzB,YAAM,eAAe,MAAM,cAAc,IAAI,MAAM,MAAM,MAAM;AAC/D,UAAI,cAAc;AAChB,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,UAAU,IAAI;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,cACb,YACA,UACA,QACwB;AACxB,MAAI,iBAAiB,UAAU,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,QAAM,UAAe,aAAQ,QAAQ;AACrC,QAAM,WAAW,YAAY;AAE7B,MAAI,UAAU;AACZ,WAAO,oBAAoB,YAAY,UAAU,MAAM;AAAA,EACzD;AAEA,SAAO,wBAAwB,YAAY,UAAU,MAAM;AAC7D;AAEA,SAAS,iBAAiB,YAA6B;AACrD,SAAO,CAAC,WAAW,WAAW,GAAG,KAAK,CAAC,WAAW,WAAW,GAAG;AAClE;AAEA,eAAe,wBACb,YACA,UACA,QACwB;AACxB,MAAI,WAAW,WAAW,GAAG,GAAG;AAC9B,WAAO,oBAAoB,YAAY,UAAU,MAAM;AAAA,EACzD;AAEA,MAAI,OAAO,UAAU,OAAO;AAC1B,UAAM,gBAAgB,MAAM,iBAAiB,YAAY,MAAM;AAC/D,QAAI,cAAe,QAAO;AAAA,EAC5B;AAEA,MAAI,OAAO,YAAY;AACrB,UAAM,oBAAoB,MAAM,iBAAiB,YAAY,MAAM;AACnE,QAAI,kBAAmB,QAAO;AAAA,EAChC;AAEA,SAAO;AACT;AAEA,eAAe,oBACb,YACA,UACA,QACwB;AACxB,QAAM,MAAW,aAAQ,QAAQ;AACjC,MAAI,gBAAqB,UAAK,KAAK,UAAU;AAG7C,QAAM,SAAc,aAAQ,aAAa;AACzC,MAAI,WAAW,SAAS,WAAW,UAAU,WAAW,QAAQ;AAC9D,UAAM,WAAW,cAAc,MAAM,GAAG,CAAC,OAAO,MAAM;AAGtD,UAAM,eAAe,WAAW,SAAS,CAAC,MAAM,IAC3B,WAAW,SAAS,CAAC,MAAM,IAC3B,CAAC,OAAO,MAAM;AAEnC,eAAW,SAAS,cAAc;AAChC,YAAM,SAAS,WAAW;AAC1B,UAAI,MAAM,WAAgB,UAAK,OAAO,SAAS,MAAM,CAAC,GAAG;AACvD,eAAO;AAAA,MACT;AAAA,IACF;AAGA,oBAAgB;AAAA,EAClB;AAEA,QAAM,aAAa,CAAC,OAAO,QAAQ,OAAO,QAAQ,QAAQ,MAAM;AAEhE,aAAW,OAAO,YAAY;AAC5B,UAAM,UAAU,gBAAgB;AAChC,QAAI,MAAM,WAAgB,UAAK,OAAO,SAAS,OAAO,CAAC,GAAG;AACxD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,aAAW,OAAO,CAAC,YAAY,aAAa,YAAY,WAAW,GAAG;AACpE,UAAM,YAAiB,UAAK,eAAe,GAAG;AAC9C,QAAI,MAAM,WAAgB,UAAK,OAAO,SAAS,SAAS,CAAC,GAAG;AAC1D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,iBACb,YACA,QACwB;AACxB,MAAI,CAAC,OAAO,UAAU,MAAO,QAAO;AAEpC,QAAM,EAAE,OAAO,UAAU,IAAI,IAAI,OAAO;AAExC,aAAW,CAAC,SAAS,QAAQ,KAAK,OAAO,QAAQ,KAAK,GAAG;AACvD,UAAM,QAAQ,eAAe,OAAO;AACpC,UAAM,QAAQ,WAAW,MAAM,KAAK;AAEpC,QAAI,OAAO;AACT,iBAAW,WAAW,UAAU;AAC9B,cAAM,WAAW,QAAQ,QAAQ,KAAK,MAAM,CAAC,KAAK,EAAE;AACpD,cAAM,WAAgB,UAAK,SAAS,QAAQ;AAE5C,cAAM,YAAY,MAAM,oBAAoB,KAAK,QAAQ,IAAI,IAAI;AAAA,UAC/D,GAAG;AAAA,UACH,SAAS,OAAO;AAAA,QAClB,CAAC;AAED,YAAI,UAAW,QAAO;AAEtB,YAAI,MAAM,WAAgB,UAAK,OAAO,SAAS,QAAQ,CAAC,GAAG;AACzD,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,iBACb,YACA,QACwB;AACxB,MAAI,CAAC,OAAO,WAAY,QAAO;AAE/B,aAAW,aAAa,OAAO,YAAY;AACzC,UAAM,kBAAuB,UAAK,OAAO,SAAS,WAAW,cAAc;AAE3E,QAAI;AACF,YAAM,UAAU,MAAS,YAAS,iBAAiB,OAAO;AAC1D,YAAM,MAAM,KAAK,MAAM,OAAO;AAE9B,UAAI,IAAI,SAAS,cAAc,WAAW,WAAW,IAAI,OAAO,GAAG,GAAG;AACpE,cAAM,UAAU,WAAW,MAAM,IAAI,KAAK,SAAS,CAAC,KAAK;AACzD,cAAM,WAAW,IAAI,QAAQ,IAAI,UAAU;AAE3C,YAAI,YAAY,KAAK;AACnB,iBAAY,UAAK,WAAW,QAAQ;AAAA,QACtC;AAEA,cAAM,WAAW,MAAM,oBAAoB,KAAK,OAAO,IAAI,WAAW;AAAA,UACpE,GAAG;AAAA,UACH,SAAS,OAAO;AAAA,QAClB,CAAC;AAED,YAAI,SAAU,QAAO;AAAA,MACvB;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,oBACb,YACA,UACA,QACwB;AACxB,MAAI,WAAW,WAAW,GAAG,GAAG;AAC9B,WAAO,sBAAsB,YAAY,UAAU,MAAM;AAAA,EAC3D;AAEA,QAAM,QAAQ,WAAW,MAAM,GAAG;AAClC,QAAM,gBAAgB;AAAA,IACf,UAAK,GAAG,KAAK,IAAI;AAAA,IACjB,UAAK,GAAG,OAAO,aAAa;AAAA,IAC5B,UAAK,OAAO,GAAG,KAAK,IAAI;AAAA,IACxB,UAAK,OAAO,GAAG,OAAO,aAAa;AAAA,EAC1C;AAEA,aAAW,gBAAgB,eAAe;AACxC,QAAI,MAAM,WAAgB,UAAK,OAAO,SAAS,YAAY,CAAC,GAAG;AAC7D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,sBACb,YACA,UACA,QACwB;AACxB,QAAM,MAAW,aAAQ,QAAQ;AACjC,MAAI,YAAY;AAEhB,QAAM,OAAO,WAAW,MAAM,MAAM,IAAI,CAAC,KAAK;AAC9C,QAAM,OAAO,WAAW,MAAM,KAAK,MAAM;AAEzC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,gBAAiB,aAAQ,SAAS;AAAA,EACpC;AAEA,MAAI,MAAM;AACR,UAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,gBAAiB,UAAK,WAAW,GAAG,KAAK;AAAA,EAC3C;AAEA,QAAM,gBAAgB,YAAY;AAClC,MAAI,MAAM,WAAgB,UAAK,OAAO,SAAS,aAAa,CAAC,GAAG;AAC9D,WAAO;AAAA,EACT;AAEA,QAAM,WAAgB,UAAK,WAAW,aAAa;AACnD,MAAI,MAAM,WAAgB,UAAK,OAAO,SAAS,QAAQ,CAAC,GAAG;AACzD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,SAAyB;AAC/C,QAAM,UAAU,QAAQ,QAAQ,uBAAuB,MAAM;AAC7D,QAAM,eAAe,QAAQ,QAAQ,SAAS,MAAM;AACpD,SAAO,IAAI,OAAO,IAAI,YAAY,GAAG;AACvC;AAEA,eAAe,WAAW,UAAoC;AAC5D,MAAI;AACF,UAAS,UAAO,QAAQ;AACxB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,aAAa,SAAgD;AACjF,QAAM,eAAoB,UAAK,SAAS,eAAe;AAEvD,MAAI;AACF,UAAM,UAAU,MAAS,YAAS,cAAc,OAAO;AACvD,UAAM,WAAW,KAAK,MAAM,OAAO;AAEnC,WAAO;AAAA,MACL,SAAS,SAAS,iBAAiB;AAAA,MACnC,OAAO,SAAS,iBAAiB;AAAA,IACnC;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,eAAe,SAAoC;AACvE,QAAM,kBAAuB,UAAK,SAAS,cAAc;AAEzD,MAAI;AACF,UAAM,UAAU,MAAS,YAAS,iBAAiB,OAAO;AAC1D,UAAM,MAAM,KAAK,MAAM,OAAO;AAE9B,QAAI,IAAI,YAAY;AAClB,YAAM,WAAW,MAAM,QAAQ,IAAI,UAAU,IACzC,IAAI,aACJ,IAAI,WAAW,YAAY,CAAC;AAEhC,YAAM,aAAuB,CAAC;AAC9B,iBAAW,WAAW,UAAU;AAC9B,YAAI,CAAC,QAAQ,SAAS,GAAG,GAAG;AAC1B,qBAAW,KAAK,OAAO;AAAA,QACzB,OAAO;AACL,gBAAM,OAAO,QAAQ,QAAQ,MAAM,EAAE;AACrC,cAAI;AACF,kBAAM,UAAU,MAAS,WAAa,UAAK,SAAS,IAAI,CAAC;AACzD,uBAAW,SAAS,SAAS;AAC3B,oBAAM,WAAgB,UAAK,MAAM,KAAK;AACtC,oBAAM,UAAe,UAAK,SAAS,UAAU,cAAc;AAC3D,kBAAI,MAAM,WAAW,OAAO,GAAG;AAC7B,2BAAW,KAAK,QAAQ;AAAA,cAC1B;AAAA,YACF;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO,CAAC;AACV;;;AC1UA,YAAYE,WAAU;AAQf,SAAS,WACd,iBACA,UACA,SAAuB,CAAC,GACjB;AACP,QAAM,EAAE,QAAQ,CAAC,OAAO,cAAc,QAAQ,GAAG,QAAQ,EAAE,IAAI;AAE/D,QAAM,eAAe,oBAAI,IAAoB;AAE7C,aAAW,QAAQ,UAAU;AAC3B,UAAM,aAAaC,eAAc,MAAM,OAAO,KAAK;AACnD,iBAAa,IAAI,MAAM,UAAU;AAAA,EACnC;AAEA,QAAM,cAAc,oBAAI,IAAyB;AACjD,aAAW,CAAC,MAAM,MAAM,KAAK,cAAc;AACzC,QAAI,CAAC,YAAY,IAAI,MAAM,GAAG;AAC5B,kBAAY,IAAI,QAAQ,oBAAI,IAAI,CAAC;AAAA,IACnC;AACA,gBAAY,IAAI,MAAM,EAAG,IAAI,IAAI;AAAA,EACnC;AAEA,QAAM,UAAU,oBAAI,IAAqC;AACzD,QAAM,eAAe,oBAAI,IAAyB;AAElD,aAAW,YAAY,iBAAiB;AACtC,UAAM,aAAa,aAAa,IAAI,SAAS,IAAI;AACjD,UAAM,WAAW,aAAa,IAAI,SAAS,EAAE;AAE7C,QAAI,CAAC,cAAc,CAAC,YAAY,eAAe,UAAU;AACvD;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ,IAAI,UAAU,GAAG;AAC5B,cAAQ,IAAI,YAAY,oBAAI,IAAI,CAAC;AAAA,IACnC;AAEA,UAAM,YAAY,QAAQ,IAAI,UAAU;AAExC,QAAI,CAAC,UAAU,IAAI,QAAQ,GAAG;AAC5B,gBAAU,IAAI,UAAU;AAAA,QACtB,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,WAAW,CAAC;AAAA,MACd,CAAC;AAAA,IACH;AAEA,UAAM,OAAO,UAAU,IAAI,QAAQ;AACnC,SAAK;AACL,SAAK,UAAU,KAAK,SAAS,QAAQ;AAAA,EACvC;AAEA,QAAM,QAAsB,CAAC;AAC7B,aAAW,aAAa,QAAQ,OAAO,GAAG;AACxC,eAAW,QAAQ,UAAU,OAAO,GAAG;AACrC,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,SAAS,oBAAI,IAAoB;AAEvC,aAAW,QAAQ,OAAO;AACxB,WAAO,IAAI,KAAK,OAAO,OAAO,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC;AACtD,UAAM,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,EAAE,KAAK,KAAK,CAAC;AAAA,EAClD;AAEA,QAAM,UAAoB,CAAC;AAC3B,aAAW,CAAC,YAAY,KAAK,KAAK,aAAa;AAC7C,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,MAAM,KAAK,KAAK,EAAE,KAAK;AAAA,MAC9B,OAAO,MAAM,IAAI,UAAU,KAAK;AAAA,MAChC,QAAQ,OAAO,IAAI,UAAU,KAAK;AAAA,MAClC,cAAc,MAAM,KAAK,aAAa,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,KAAK;AAAA,IACpE,CAAC;AAAA,EACH;AAEA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAEnD,QAAM,SAAS,aAAa,OAAO,QAAQ,IAAI,OAAK,EAAE,IAAI,CAAC;AAE3D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAASA,eAAc,MAAc,OAAiB,OAAuB;AAC3E,QAAM,aAAa,KAAK,QAAQ,OAAO,GAAG;AAE1C,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,IAAI,GAAG;AACvB,YAAM,OAAO,KAAK,MAAM,GAAG,EAAE;AAC7B,UAAI,WAAW,WAAW,OAAO,GAAG,GAAG;AACrC,cAAM,OAAO,WAAW,MAAM,KAAK,SAAS,CAAC;AAC7C,cAAMC,SAAQ,KAAK,MAAM,GAAG;AAC5B,YAAIA,OAAM,SAAS,GAAG;AACpB,iBAAY,WAAK,MAAMA,OAAM,CAAC,CAAC;AAAA,QACjC;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,WAAW,WAAW,OAAO,GAAG,GAAG;AACrC,cAAM,OAAO,WAAW,MAAM,KAAK,SAAS,CAAC;AAC7C,cAAMA,SAAQ,KAAK,MAAM,GAAG;AAC5B,YAAI,UAAU,GAAG;AACf,iBAAO;AAAA,QACT;AACA,cAAM,cAAcA,OAAM,MAAM,GAAG,KAAK;AACxC,eAAY,WAAK,MAAM,GAAG,WAAW;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,WAAW,MAAM,GAAG;AAClC,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,MAAM,CAAC;AAAA,EAChB;AAEA,SAAO;AACT;AAEO,SAAS,aAAa,OAAqB,SAA+B;AAC/E,QAAM,QAAQ,oBAAI,IAAsB;AAExC,aAAW,UAAU,SAAS;AAC5B,UAAM,IAAI,QAAQ,CAAC,CAAC;AAAA,EACtB;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,MAAM,IAAI,KAAK,IAAI,GAAG;AACzB,YAAM,IAAI,KAAK,MAAM,CAAC,CAAC;AAAA,IACzB;AACA,UAAM,IAAI,KAAK,IAAI,EAAG,KAAK,KAAK,EAAE;AAAA,EACpC;AAEA,SAAO,OAAO,KAAK;AACrB;AAEA,SAAS,OAAO,OAA0C;AACxD,MAAI,QAAQ;AACZ,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,UAAU,oBAAI,IAAoB;AACxC,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,OAAmB,CAAC;AAE1B,WAAS,cAAc,GAAiB;AACtC,YAAQ,IAAI,GAAG,KAAK;AACpB,aAAS,IAAI,GAAG,KAAK;AACrB;AACA,UAAM,KAAK,CAAC;AACZ,YAAQ,IAAI,CAAC;AAEb,UAAM,YAAY,MAAM,IAAI,CAAC,KAAK,CAAC;AACnC,eAAW,KAAK,WAAW;AACzB,UAAI,CAAC,QAAQ,IAAI,CAAC,GAAG;AACnB,sBAAc,CAAC;AACf,iBAAS,IAAI,GAAG,KAAK,IAAI,SAAS,IAAI,CAAC,GAAI,SAAS,IAAI,CAAC,CAAE,CAAC;AAAA,MAC9D,WAAW,QAAQ,IAAI,CAAC,GAAG;AACzB,iBAAS,IAAI,GAAG,KAAK,IAAI,SAAS,IAAI,CAAC,GAAI,QAAQ,IAAI,CAAC,CAAE,CAAC;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI,SAAS,IAAI,CAAC,MAAM,QAAQ,IAAI,CAAC,GAAG;AACtC,YAAM,MAAgB,CAAC;AACvB,UAAI;AACJ,SAAG;AACD,YAAI,MAAM,IAAI;AACd,gBAAQ,OAAO,CAAC;AAChB,YAAI,KAAK,CAAC;AAAA,MACZ,SAAS,MAAM;AAEf,UAAI,IAAI,SAAS,GAAG;AAClB,aAAK,KAAK,IAAI,KAAK,CAAC;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,KAAK,MAAM,KAAK,GAAG;AAC5B,QAAI,CAAC,QAAQ,IAAI,CAAC,GAAG;AACnB,oBAAc,CAAC;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,WAAW,OAAiD;AAC1E,QAAM,MAAM,oBAAI,IAAoB;AAEpC,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO;AACnC,UAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE,OAAO,UAAQ;AAC/C,YAAM,UAAU,KAAK,KAAK;AAC1B,aAAO,QAAQ,SAAS,KAAK,CAAC,QAAQ,WAAW,IAAI,KAAK,CAAC,QAAQ,WAAW,GAAG;AAAA,IACnF,CAAC;AACD,QAAI,IAAI,MAAM,MAAM,MAAM;AAAA,EAC5B;AAEA,SAAO;AACT;;;AClNA,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AAGtB,IAAM,eAAe;AACrB,IAAM,aAAa;AAEZ,SAAS,cAAc,OAAsB;AAClD,QAAM,WAAqB,CAAC;AAE5B,WAAS,KAAK,kBAAkB;AAChC,WAAS,KAAK,YAAY;AAC1B,WAAS,KAAK,EAAE;AAChB,WAAS,KAAK,0BAA0B;AACxC,WAAS,KAAK,YAAY;AAC1B,WAAS,KAAK,mBAAmB,KAAK,CAAC;AACvC,WAAS,KAAK,OAAO;AAErB,WAAS,KAAK,cAAc;AAC5B,WAAS,KAAK,kBAAkB,MAAM,OAAO,CAAC;AAC9C,WAAS,KAAK,EAAE;AAEhB,MAAI,MAAM,OAAO,SAAS,GAAG;AAC3B,aAAS,KAAK,mCAAyB;AACvC,aAAS,KAAK,aAAa,MAAM,MAAM,CAAC;AACxC,aAAS,KAAK,EAAE;AAAA,EAClB;AAEA,WAAS,KAAK,UAAU;AAExB,SAAO,SAAS,KAAK,IAAI;AAC3B;AAEA,SAAS,mBAAmB,OAAsB;AAChD,QAAM,QAAkB,CAAC,cAAc;AAEvC,QAAM,cAAc,CAAC,GAAG,MAAM,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAClD,QAAI,EAAE,SAAS,EAAE,KAAM,QAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AACzD,WAAO,EAAE,GAAG,cAAc,EAAE,EAAE;AAAA,EAChC,CAAC;AAED,aAAW,QAAQ,aAAa;AAC9B,UAAM,SAAS,WAAW,KAAK,IAAI;AACnC,UAAM,OAAO,WAAW,KAAK,EAAE;AAC/B,UAAM,QAAQ,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,MAAM;AACrD,UAAM,QAAQ,QAAQ,MAAM,KAAK,KAAK;AACtC,UAAM,KAAK,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE,GAAG;AAAA,EACrE;AAEA,MAAI,YAAY,WAAW,GAAG;AAC5B,eAAW,UAAU,MAAM,QAAQ,MAAM,GAAG,CAAC,GAAG;AAC9C,YAAM,KAAK,WAAW,OAAO,IAAI;AACjC,YAAM,KAAK,KAAK,EAAE,IAAI,OAAO,IAAI,GAAG;AAAA,IACtC;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,kBAAkB,SAA2B;AACpD,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AAEA,QAAM,SAAS,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACzC,UAAM,OAAO,EAAE,QAAQ,EAAE;AACzB,UAAM,OAAO,EAAE,QAAQ,EAAE;AACzB,QAAI,SAAS,KAAM,QAAO,OAAO;AACjC,WAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EACpC,CAAC;AAED,aAAW,UAAU,QAAQ;AAC3B,UAAM,eAAe,OAAO,aAAa,SAAS,IAC9C,OAAO,aAAa,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,KACxC,OAAO,aAAa,SAAS,IAAI,QAAQ,MAC1C;AAEJ,UAAM;AAAA,MACJ,OAAO,OAAO,IAAI,QAAQ,OAAO,MAAM,MAAM,MAAM,OAAO,KAAK,MAAM,OAAO,MAAM,MAAM,YAAY;AAAA,IACtG;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,aAAa,QAA4B;AAChD,QAAM,QAAkB,CAAC;AAEzB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,KAAK,GAAG,IAAI,CAAC,KAAK,MAAM,IAAI,OAAK,KAAK,CAAC,IAAI,EAAE,KAAK,UAAK,CAAC,EAAE;AAAA,EAClE;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,WAAW,MAAsB;AACxC,SAAO,KAAK,QAAQ,kBAAkB,GAAG;AAC3C;AAEA,eAAsB,sBACpB,UACA,OACe;AACf,MAAI,kBAAkB;AAEtB,MAAI;AACF,sBAAkB,MAAS,aAAS,UAAU,OAAO;AAAA,EACvD,QAAQ;AAAA,EAER;AAEA,QAAM,aAAa,cAAc,KAAK;AAEtC,MAAI;AAEJ,MAAI,iBAAiB;AACnB,UAAM,aAAa,gBAAgB,QAAQ,YAAY;AACvD,UAAM,WAAW,gBAAgB,QAAQ,UAAU;AAEnD,QAAI,eAAe,MAAM,aAAa,IAAI;AACxC,YAAM,SAAS,gBAAgB,MAAM,GAAG,UAAU;AAClD,YAAM,QAAQ,gBAAgB,MAAM,WAAW,WAAW,MAAM;AAEhE,YAAM,mBAAmB,WAAW;AAAA,QAClC,WAAW,QAAQ,YAAY;AAAA,QAC/B,WAAW,QAAQ,UAAU,IAAI,WAAW;AAAA,MAC9C;AAEA,qBAAe,SAAS,mBAAmB;AAAA,IAC7C,OAAO;AACL,qBAAe,aAAa,SAAS;AAAA,IACvC;AAAA,EACF,OAAO;AACL,mBAAe;AAAA,EACjB;AAEA,QAAS,UAAW,cAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAC1D,QAAS,cAAU,UAAU,cAAc,OAAO;AACpD;AAEO,SAAS,mBACd,YACA,cACA,gBACQ;AACR,QAAM,QAAkB,CAAC,cAAc,cAAc;AAErD,aAAW,UAAU,gBAAgB;AACnC,UAAM,KAAK,WAAW,MAAM;AAC5B,UAAM,KAAK,KAAK,EAAE,IAAI,MAAM,GAAG;AAAA,EACjC;AAEA,MAAI,YAAY;AAEhB,aAAW,QAAQ,YAAY;AAC7B,UAAM,SAAS,WAAW,KAAK,IAAI;AACnC,UAAM,OAAO,WAAW,KAAK,EAAE;AAC/B,UAAM,KAAK,KAAK,MAAM,UAAU,IAAI,EAAE;AACtC,UAAM,KAAK,eAAe,SAAS,kCAAkC;AACrE;AAAA,EACF;AAEA,aAAW,QAAQ,cAAc;AAC/B,UAAM,SAAS,WAAW,KAAK,IAAI;AACnC,UAAM,OAAO,WAAW,KAAK,EAAE;AAC/B,UAAM,KAAK,KAAK,MAAM,SAAS,IAAI,EAAE;AACrC,UAAM,KAAK,eAAe,SAAS,qDAAqD;AACxF;AAAA,EACF;AAEA,QAAM,KAAK,KAAK;AAEhB,SAAO,MAAM,KAAK,IAAI;AACxB;;;AC/KA,YAAYC,SAAQ;AAGpB,IAAM,eAAe;AAEd,SAAS,YAAY,OAAwB;AAClD,QAAM,UAAU,MAAM,QAAQ,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK;AAEpD,QAAM,QAAQ,MAAM,MACjB,IAAI,QAAM;AAAA,IACT,MAAM,EAAE;AAAA,IACR,IAAI,EAAE;AAAA,IACN,QAAQ,EAAE;AAAA,EACZ,EAAE,EACD,KAAK,CAAC,GAAG,MAAM;AACd,QAAI,EAAE,SAAS,EAAE,KAAM,QAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AACzD,WAAO,EAAE,GAAG,cAAc,EAAE,EAAE;AAAA,EAChC,CAAC;AAEH,QAAM,eAAyC,CAAC;AAChD,aAAW,UAAU,MAAM,SAAS;AAClC,QAAI,OAAO,aAAa,SAAS,GAAG;AAClC,mBAAa,OAAO,IAAI,IAAI,OAAO,aAAa,KAAK;AAAA,IACvD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,cAAc,UAAkB,MAA+B;AACnF,QAAM,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI;AAChD,QAAS,cAAU,UAAU,SAAS,OAAO;AAC/C;AAEA,eAAsB,aAAa,UAA4C;AAC7E,MAAI;AACF,UAAM,UAAU,MAAS,aAAS,UAAU,OAAO;AACnD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,UAAU,SAA0B,SAAmB,UAA6B;AAClG,QAAM,WAAW,SAAS,SAAS,CAAC;AACpC,QAAM,WAAW,QAAQ;AAEzB,QAAM,aAAa,IAAI,IAAI,SAAS,IAAI,OAAO,CAAC;AAChD,QAAM,aAAa,IAAI,IAAI,SAAS,IAAI,OAAO,CAAC;AAGhD,QAAM,kBAAkB,oBAAI,IAAwB;AACpD,MAAI,UAAU;AACZ,eAAW,QAAQ,SAAS,OAAO;AACjC,sBAAgB,IAAI,QAAQ,IAAI,GAAG,IAAI;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,QAAsB,CAAC;AAC7B,QAAM,UAAwB,CAAC;AAE/B,aAAW,QAAQ,UAAU;AAC3B,QAAI,CAAC,WAAW,IAAI,QAAQ,IAAI,CAAC,GAAG;AAClC,YAAM,WAAW,gBAAgB,IAAI,QAAQ,IAAI,CAAC;AAClD,YAAM,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,IAAI,KAAK;AAAA,QACT,QAAQ,KAAK;AAAA,QACb,WAAW,UAAU,aAAa,CAAC;AAAA,MACrC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,aAAW,QAAQ,UAAU;AAC3B,QAAI,CAAC,WAAW,IAAI,QAAQ,IAAI,CAAC,GAAG;AAClC,cAAQ,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,IAAI,KAAK;AAAA,QACT,QAAQ,KAAK;AAAA,QACb,WAAW,CAAC;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,YAAY,gBAAgB,SAAS,OAAO;AAElD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,QAAQ,MAA4C;AAC3D,SAAO,GAAG,KAAK,IAAI,KAAK,KAAK,EAAE;AACjC;AAEA,SAAS,gBAAgB,SAA0B,SAA+B;AAChF,MAAI,CAAC,SAAS;AACZ,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,YAAY,iBAAiB,OAAO;AAC1C,QAAM,YAAY,iBAAiB,OAAO;AAE1C,QAAM,cAAc,IAAI,IAAI,UAAU,IAAI,QAAQ,CAAC;AACnD,QAAM,SAAqB,CAAC;AAE5B,aAAW,SAAS,WAAW;AAC7B,QAAI,CAAC,YAAY,IAAI,SAAS,KAAK,CAAC,GAAG;AACrC,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAA4B;AACpD,QAAM,QAAQ,oBAAI,IAAsB;AAExC,aAAW,UAAU,KAAK,SAAS;AACjC,UAAM,IAAI,QAAQ,CAAC,CAAC;AAAA,EACtB;AAEA,aAAW,QAAQ,KAAK,OAAO;AAC7B,QAAI,CAAC,MAAM,IAAI,KAAK,IAAI,GAAG;AACzB,YAAM,IAAI,KAAK,MAAM,CAAC,CAAC;AAAA,IACzB;AACA,UAAM,IAAI,KAAK,IAAI,EAAG,KAAK,KAAK,EAAE;AAAA,EACpC;AAEA,SAAOC,QAAO,KAAK;AACrB;AAEA,SAASA,QAAO,OAA0C;AACxD,MAAI,QAAQ;AACZ,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,UAAU,oBAAI,IAAoB;AACxC,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,OAAmB,CAAC;AAE1B,WAAS,cAAc,GAAiB;AACtC,YAAQ,IAAI,GAAG,KAAK;AACpB,aAAS,IAAI,GAAG,KAAK;AACrB;AACA,UAAM,KAAK,CAAC;AACZ,YAAQ,IAAI,CAAC;AAEb,UAAM,YAAY,MAAM,IAAI,CAAC,KAAK,CAAC;AACnC,eAAW,KAAK,WAAW;AACzB,UAAI,CAAC,QAAQ,IAAI,CAAC,GAAG;AACnB,sBAAc,CAAC;AACf,iBAAS,IAAI,GAAG,KAAK,IAAI,SAAS,IAAI,CAAC,GAAI,SAAS,IAAI,CAAC,CAAE,CAAC;AAAA,MAC9D,WAAW,QAAQ,IAAI,CAAC,GAAG;AACzB,iBAAS,IAAI,GAAG,KAAK,IAAI,SAAS,IAAI,CAAC,GAAI,QAAQ,IAAI,CAAC,CAAE,CAAC;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI,SAAS,IAAI,CAAC,MAAM,QAAQ,IAAI,CAAC,GAAG;AACtC,YAAM,MAAgB,CAAC;AACvB,UAAI;AACJ,SAAG;AACD,YAAI,MAAM,IAAI;AACd,gBAAQ,OAAO,CAAC;AAChB,YAAI,KAAK,CAAC;AAAA,MACZ,SAAS,MAAM;AAEf,UAAI,IAAI,SAAS,GAAG;AAClB,aAAK,KAAK,IAAI,KAAK,CAAC;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,KAAK,MAAM,KAAK,GAAG;AAC5B,QAAI,CAAC,QAAQ,IAAI,CAAC,GAAG;AACnB,oBAAc,CAAC;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,SAAS,OAAyB;AACzC,SAAO,MAAM,KAAK,EAAE,KAAK,IAAI;AAC/B;;;AC9LO,IAAM,UAAU;","names":["require","visitNode","getLocation","path","getModuleName","parts","fs","path","fs","tarjan"]}
|
package/package.json
CHANGED