301 lines
9.1 KiB
Plaintext
301 lines
9.1 KiB
Plaintext
#!/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"
|
|
}
|
|
} |