var shop = use('shop') if (!args || args.length < 1) { log.console("Usage: cell why ") $_.stop() return } var target = args[0] log.console("Searching for '" + target + "'...") var target_clean = target if (target_clean.startsWith('/')) target_clean = target_clean.substring(1) var found = false // DFS to find paths // current_pkg: canonical path of current package (null for root) // stack: array of {alias, pkg} leading to current_pkg function search(current_pkg, stack) { var deps = shop.dependencies(current_pkg) // Sort for consistent output var aliases = [] for (var k in deps) aliases.push(k) aliases.sort() for (var i = 0; i < aliases.length; i++) { var alias = aliases[i] var locator = deps[alias] var parsed = shop.parse_package(locator) if (!parsed) continue var canon = parsed.path var locator_clean = locator if (locator.includes('@')) locator_clean = locator.split('@')[0] // Check if match // 1. Alias matches // 2. Package name matches // 3. Canonical path matches (exact or clean) // 4. Locator matches (exact or clean) var match = (alias == target) || (parsed.name == target) || (canon == target) || (canon == target_clean) || (locator == target) || (locator_clean == target) var node = { alias: alias, pkg: canon, locator: locator } var new_stack = stack.concat([node]) if (match) { found = true print_stack(new_stack) // Don't recurse if we found the target in this branch continue } // Recurse if not seen in current stack (cycle detection) var cycle = false for (var j = 0; j < stack.length; j++) { if (stack[j].pkg == canon) { cycle = true break } } if (!cycle) { search(canon, new_stack) } } } function print_stack(stack) { // Calculate max width for alignment if needed, but simple tree is fine var output = "project" log.console(output) for (var i = 0; i < stack.length; i++) { var node = stack[i] var indent = "" for (var j = 0; j <= i; j++) indent += " " var info = node.locator if (node.alias != parsed_name(node.locator)) { // info += " (aliased as " + node.alias + ")" } log.console(indent + "-> " + node.alias + " (" + info + ")") } log.console("") } function parsed_name(locator) { var parsed = shop.parse_package(locator) return parsed ? parsed.name : "" } search(null, []) if (!found) { log.console("Package '" + target + "' not found in dependency tree.") } $_.stop()