#!/usr/bin/env nu # Layered Module Resolver # Provides unified resolution across 3 layers: System → Workspace → Infrastructure use ../../taskservs/discover.nu * use ../../providers/discover.nu * use ../../clusters/discover.nu * # Resolve module path with layer information # Returns: {path: string, layer: string, name: string, type: string, found: bool} export def resolve-module [ module_name: string module_type: string # "taskserv", "provider", "cluster" --workspace: string = "" # Workspace path for Layer 2 --infra: string = "" # Infrastructure path for Layer 3 ]: nothing -> record { # Layer 3: Infrastructure-specific (highest priority) if ($infra | is-not-empty) and ($infra | path exists) { let infra_path = match $module_type { "taskserv" => ($infra | path join ".taskservs" $module_name) "provider" => ($infra | path join ".providers" $module_name) "cluster" => ($infra | path join ".clusters" $module_name) _ => "" } if ($infra_path | path exists) { return { path: $infra_path layer: "infra" layer_number: 3 name: $module_name type: $module_type found: true } } } # Layer 2: Workspace-shared (medium priority) if ($workspace | is-not-empty) and ($workspace | path exists) { let workspace_path = match $module_type { "taskserv" => ($workspace | path join ".taskservs" $module_name) "provider" => ($workspace | path join ".providers" $module_name) "cluster" => ($workspace | path join ".clusters" $module_name) _ => "" } if ($workspace_path | path exists) { return { path: $workspace_path layer: "workspace" layer_number: 2 name: $module_name type: $module_type found: true } } } # Layer 1: System extensions (lowest priority) let system_result = resolve-system-module $module_name $module_type if $system_result.found { return $system_result } # Not found in any layer { path: "" layer: "none" layer_number: 0 name: $module_name type: $module_type found: false } } # Resolve module from system extensions (Layer 1) def resolve-system-module [name: string, type: string]: nothing -> record { match $type { "taskserv" => { try { let info = (get-taskserv-info $name) { path: $info.kcl_path layer: "system" layer_number: 1 name: $name type: "taskserv" found: true metadata: $info } } catch { {found: false} } } "provider" => { try { let info = (get-provider-info $name) { path: $info.kcl_path layer: "system" layer_number: 1 name: $name type: "provider" found: true metadata: $info } } catch { {found: false} } } "cluster" => { try { let info = (get-cluster-info $name) { path: $info.kcl_path layer: "system" layer_number: 1 name: $name type: "cluster" found: true metadata: $info } } catch { {found: false} } } _ => { {found: false} } } } # List all available modules across layers export def list-modules-by-layer [ module_type: string --workspace: string = "" --infra: string = "" ]: nothing -> table { mut modules = [] # Layer 1: System let system_modules = match $module_type { "taskserv" => (discover-taskservs | each {|m| $m | insert layer "system" | insert layer_number 1}) "provider" => (discover-providers | each {|m| $m | insert layer "system" | insert layer_number 1}) "cluster" => (discover-clusters | each {|m| $m | insert layer "system" | insert layer_number 1}) _ => [] } $modules = ($modules | append $system_modules) # Layer 2: Workspace if ($workspace | is-not-empty) and ($workspace | path exists) { let ws_dir = match $module_type { "taskserv" => ($workspace | path join ".taskservs") "provider" => ($workspace | path join ".providers") "cluster" => ($workspace | path join ".clusters") _ => "" } if ($ws_dir | path exists) { let ws_modules = (ls $ws_dir | where type == "dir" | each {|dir| { name: ($dir.name | path basename) type: $module_type layer: "workspace" layer_number: 2 path: $dir.name } }) $modules = ($modules | append $ws_modules) } } # Layer 3: Infrastructure if ($infra | is-not-empty) and ($infra | path exists) { let infra_dir = match $module_type { "taskserv" => ($infra | path join ".taskservs") "provider" => ($infra | path join ".providers") "cluster" => ($infra | path join ".clusters") _ => "" } if ($infra_dir | path exists) { let infra_modules = (ls $infra_dir | where type == "dir" | each {|dir| { name: ($dir.name | path basename) type: $module_type layer: "infra" layer_number: 3 path: $dir.name } }) $modules = ($modules | append $infra_modules) } } $modules } # Show effective modules (deduplicated by resolution order) export def show-effective-modules [ module_type: string --workspace: string = "" --infra: string = "" ]: nothing -> table { let all_modules = (list-modules-by-layer $module_type --workspace $workspace --infra $infra) # Group by name and pick highest layer number $all_modules | group-by name | items {|name, versions| let effective = ($versions | sort-by layer_number | reverse | first) $effective | insert overrides (($versions | length) - 1) } } # Determine target layer from context export def determine-layer [ --workspace: string = "" --infra: string = "" --level: string = "" # Explicit level: "workspace", "infra", or auto-detect ]: nothing -> record { # Explicit level takes precedence if ($level | is-not-empty) { if $level == "workspace" { return { layer: "workspace" layer_number: 2 path: $workspace } } else if $level == "infra" { return { layer: "infra" layer_number: 3 path: $infra } } } # Auto-detect based on current directory let pwd = $env.PWD # Check if we're in an infrastructure directory if ($pwd | str contains "/infra/") { let infra_path = if ($infra | is-not-empty) { $infra } else { # Try to find infra path from current directory let parts = ($pwd | path split) let infra_idx = ($parts | enumerate | where item == "infra" | get index | first) if ($infra_idx | is-not-empty) { let infra_parts = ($parts | take ($infra_idx + 2)) $infra_parts | path join } else { $pwd } } return { layer: "infra" layer_number: 3 path: $infra_path } } # Check if we're in a workspace directory if ($workspace | is-not-empty) and ($workspace | path exists) { return { layer: "workspace" layer_number: 2 path: $workspace } } # Check if current directory has .taskservs (workspace marker) if (($pwd | path join ".taskservs") | path exists) and (($pwd | path join "infra") | path exists) { return { layer: "workspace" layer_number: 2 path: $pwd } } # Default to infrastructure level { layer: "infra" layer_number: 3 path: ($infra | default $pwd) } } # Print resolution information for debugging export def print-resolution [resolution: record]: nothing -> nothing { if $resolution.found { print $"✅ Found ($resolution.name) at Layer ($resolution.layer_number) \(($resolution.layer)\)" print $" Path: ($resolution.path)" } else { print $"❌ Module ($resolution.name) not found in any layer" } }