prvng_core/nulib/taskservs/discover.nu

187 lines
5.7 KiB
Plaintext
Raw Normal View History

2025-10-07 10:32:04 +01:00
#!/usr/bin/env nu
# Taskserv Discovery System (UPDATED for grouped structure)
# Discovers available taskservs with metadata extraction from grouped directories
use ../lib_provisioning/config/accessor.nu config-get
# Discover all available taskservs (updated for grouped structure)
export def discover-taskservs [] {
2025-10-07 10:32:04 +01:00
# Get absolute path to extensions directory from config
let taskservs_path = (config-get "paths.taskservs" | path expand)
if not ($taskservs_path | path exists) {
error make { msg: $"Taskservs path not found: ($taskservs_path)" }
}
# Find taskservs in both flat and grouped structure
mut taskservs = []
# Get all items in taskservs directory
let items = ls $taskservs_path | where type == "dir"
for item in $items {
let item_name = ($item.name | path basename)
let schema_path = ($item.name | path join "nickel")
let mod_path = ($schema_path | path join "nickel.mod")
2025-10-07 10:32:04 +01:00
# Check if this is a group directory with nickel/nickel.mod (has applications inside)
if ($mod_path | path exists) {
# This is a group - list the applications/profiles inside
let group_result = (do { ls $item.name } | complete)
let group_items = if $group_result.exit_code == 0 { $group_result.stdout } else { [] }
2025-10-07 10:32:04 +01:00
# Get all subdirectories (applications/profiles) except 'nickel' and 'images'
for subitem in ($group_items | where type == "dir" | where { |it|
let name = ($it.name | path basename)
$name != "nickel" and $name != "images"
}) {
let app_name = ($subitem.name | path basename)
let metadata = {
name: $app_name
type: "taskserv"
group: $item_name
version: ""
schema_path: $schema_path
main_schema: ""
dependencies: []
description: ""
available: true
last_updated: ($subitem.modified)
2025-10-07 10:32:04 +01:00
}
$taskservs = ($taskservs | append $metadata)
2025-10-07 10:32:04 +01:00
}
}
}
$taskservs | sort-by name
}
# Extract metadata from a taskserv's Nickel module (updated with group info)
def extract_taskserv_metadata [name: string, schema_path: string, group: string] {
let mod_path = ($schema_path | path join "nickel.mod")
2025-10-07 10:32:04 +01:00
# Try to parse TOML, skip if corrupted
let toml_result = (do {
open $mod_path | from toml
} | complete)
if $toml_result.exit_code != 0 {
print $"⚠️ Skipping ($name): corrupted nickel.mod file"
2025-10-07 10:32:04 +01:00
return null
}
let mod_content = $toml_result.stdout
# Find Nickel schema files
let schema_files = (glob ($schema_path | path join "*.ncl"))
2025-10-07 10:32:04 +01:00
let main_schema = ($schema_files | where ($it | str contains $name) | first | default "")
# Extract dependencies
let dependencies = ($mod_content.dependencies? | default {} | columns)
# Get description from schema file if available
let description = if ($main_schema != "") {
extract_schema_description $main_schema
} else {
""
}
{
name: $name
type: "taskserv"
group: $group
version: $mod_content.package.version
schema_path: $schema_path
2025-10-07 10:32:04 +01:00
main_schema: $main_schema
dependencies: $dependencies
description: $description
available: true
last_updated: (ls $mod_path | get 0.modified)
2025-10-07 10:32:04 +01:00
}
}
# Extract description from Nickel schema file
def extract_schema_description [schema_file: string] {
2025-10-07 10:32:04 +01:00
if not ($schema_file | path exists) {
return ""
}
# Read first few lines to find description
let content = (open $schema_file | lines | take 10)
let description_lines = ($content | where ($it | str starts-with "# ") | take 3)
if ($description_lines | is-empty) {
return ""
}
$description_lines
| str replace "^# " ""
| str join " "
| str trim
}
# Search taskservs by name or description
export def search-taskservs [query: string] {
2025-10-07 10:32:04 +01:00
discover-taskservs
| where ($it.name | str contains $query) or ($it.description | str contains $query)
}
# Get specific taskserv info (updated to search both flat and grouped)
export def get-taskserv-info [name: string] {
2025-10-07 10:32:04 +01:00
let taskservs = (discover-taskservs)
let found = ($taskservs | where name == $name | first)
if ($found | is-empty) {
error make { msg: $"Taskserv '($name)' not found" }
}
$found
}
# List taskservs by group
export def list-taskservs-by-group [group: string] {
2025-10-07 10:32:04 +01:00
discover-taskservs
| where group == $group
}
# List all groups
export def list-taskserv-groups [] {
2025-10-07 10:32:04 +01:00
discover-taskservs
| get group
| uniq
| sort
}
# List taskservs by category/tag (legacy support)
export def list-taskservs-by-tag [tag: string] {
2025-10-07 10:32:04 +01:00
discover-taskservs
| where ($it.description | str contains $tag) or ($it.group | str contains $tag)
}
# Validate taskserv availability
export def validate-taskservs [names: list<string>] {
2025-10-07 10:32:04 +01:00
let available = (discover-taskservs | get name)
let missing = ($names | where ($it not-in $available))
let found = ($names | where ($it in $available))
{
requested: $names
found: $found
missing: $missing
valid: ($missing | is-empty)
}
}
# Get taskserv path (helper for tools)
export def get-taskserv-path [name: string] {
2025-10-07 10:32:04 +01:00
let taskserv_info = get-taskserv-info $name
let base_path = "/Users/Akasha/project-provisioning/provisioning/extensions/taskservs"
if $taskserv_info.group == "root" {
$"($base_path)/($name)"
} else {
$"($base_path)/($taskserv_info.group)/($name)"
}
}