2025-10-07 10:32:04 +01:00
|
|
|
# Extension Registry
|
|
|
|
|
# Manages registration and lookup of providers, taskservs, and hooks
|
|
|
|
|
|
|
|
|
|
use ../config/accessor.nu *
|
|
|
|
|
use loader.nu *
|
|
|
|
|
|
|
|
|
|
# Get default extension registry
|
2026-01-14 02:00:23 +00:00
|
|
|
export def get-default-registry [] {
|
2025-10-07 10:32:04 +01:00
|
|
|
{
|
|
|
|
|
providers: {},
|
|
|
|
|
taskservs: {},
|
|
|
|
|
hooks: {
|
|
|
|
|
pre_server_create: [],
|
|
|
|
|
post_server_create: [],
|
|
|
|
|
pre_server_delete: [],
|
|
|
|
|
post_server_delete: [],
|
|
|
|
|
pre_taskserv_install: [],
|
|
|
|
|
post_taskserv_install: [],
|
|
|
|
|
pre_taskserv_delete: [],
|
|
|
|
|
post_taskserv_delete: []
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get registry cache file path
|
2026-01-14 02:00:23 +00:00
|
|
|
def get-registry-cache-file [] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let cache_dir = ($env.HOME | path join ".cache" "provisioning")
|
|
|
|
|
if not ($cache_dir | path exists) {
|
|
|
|
|
mkdir $cache_dir
|
|
|
|
|
}
|
|
|
|
|
$cache_dir | path join "extension-registry.json"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Load registry from cache or initialize
|
2026-01-14 02:00:23 +00:00
|
|
|
export def load-registry [] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let cache_file = (get-registry-cache-file)
|
|
|
|
|
if ($cache_file | path exists) {
|
|
|
|
|
open $cache_file
|
|
|
|
|
} else {
|
|
|
|
|
get-default-registry
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Save registry to cache
|
2026-01-14 02:00:23 +00:00
|
|
|
export def save-registry [registry: record] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let cache_file = (get-registry-cache-file)
|
|
|
|
|
$registry | to json | save -f $cache_file
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Initialize extension registry
|
2026-01-14 02:00:23 +00:00
|
|
|
export def init-registry [] {
|
2025-10-07 10:32:04 +01:00
|
|
|
# Load all discovered extensions
|
|
|
|
|
let providers = (discover-providers)
|
|
|
|
|
let taskservs = (discover-taskservs)
|
|
|
|
|
|
|
|
|
|
# Build provider entries
|
|
|
|
|
let provider_entries = ($providers | reduce -f {} {|provider, acc|
|
|
|
|
|
let provider_entry = {
|
|
|
|
|
name: $provider.name
|
|
|
|
|
path: $provider.path
|
|
|
|
|
manifest: $provider.manifest
|
|
|
|
|
entry_point: ($provider.path | path join "nulib" $provider.name)
|
|
|
|
|
available: ($provider.path | path join "nulib" $provider.name | path exists)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if $provider_entry.available {
|
|
|
|
|
$acc | insert $provider.name $provider_entry
|
|
|
|
|
} else {
|
|
|
|
|
$acc
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
# Build taskserv entries
|
|
|
|
|
let taskserv_entries = ($taskservs | reduce -f {} {|taskserv, acc|
|
|
|
|
|
let taskserv_entry = {
|
|
|
|
|
name: $taskserv.name
|
|
|
|
|
path: $taskserv.path
|
|
|
|
|
manifest: $taskserv.manifest
|
|
|
|
|
profiles: (glob ($taskserv.path | path join "*") | where ($it | path type) == "dir" | each { path basename })
|
|
|
|
|
available: true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$acc | insert $taskserv.name $taskserv_entry
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
# Build hooks (simplified for now)
|
|
|
|
|
let hook_entries = (get-default-registry).hooks
|
|
|
|
|
|
|
|
|
|
# Build final registry
|
|
|
|
|
let registry = {
|
|
|
|
|
providers: $provider_entries
|
|
|
|
|
taskservs: $taskserv_entries
|
|
|
|
|
hooks: $hook_entries
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Save registry to cache
|
|
|
|
|
save-registry $registry
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Register a provider
|
2026-01-14 02:00:23 +00:00
|
|
|
export def --env register-provider [name: string, path: string, manifest: record] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let provider_entry = {
|
|
|
|
|
name: $name
|
|
|
|
|
path: $path
|
|
|
|
|
manifest: $manifest
|
|
|
|
|
entry_point: ($path | path join "nulib" $name)
|
|
|
|
|
available: ($path | path join "nulib" $name | path exists)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if $provider_entry.available {
|
|
|
|
|
let current_registry = ($env.EXTENSION_REGISTRY? | default (get-default-registry))
|
|
|
|
|
$env.EXTENSION_REGISTRY = ($current_registry
|
|
|
|
|
| update providers ($current_registry.providers | insert $name $provider_entry))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Register a taskserv
|
2026-01-14 02:00:23 +00:00
|
|
|
export def --env register-taskserv [name: string, path: string, manifest: record] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let taskserv_entry = {
|
|
|
|
|
name: $name
|
|
|
|
|
path: $path
|
|
|
|
|
manifest: $manifest
|
|
|
|
|
profiles: (glob ($path | path join "*") | where ($it | path type) == "dir" | each { path basename })
|
|
|
|
|
available: true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let current_registry = ($env.EXTENSION_REGISTRY? | default (get-default-registry))
|
|
|
|
|
$env.EXTENSION_REGISTRY = ($current_registry
|
|
|
|
|
| update taskservs ($current_registry.taskservs | insert $name $taskserv_entry))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Register a hook
|
2026-01-14 02:00:23 +00:00
|
|
|
export def --env register-hook [hook_type: string, hook_path: string, extension_name: string] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let hook_entry = {
|
|
|
|
|
path: $hook_path
|
|
|
|
|
extension: $extension_name
|
|
|
|
|
enabled: true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let current_registry = ($env.EXTENSION_REGISTRY? | default (get-default-registry))
|
2025-12-11 21:57:05 +00:00
|
|
|
let hooks = ($current_registry.hooks? | default {})
|
|
|
|
|
let current_hooks = if ($hook_type in ($hooks | columns)) { $hooks | get $hook_type } else { [] }
|
2025-10-07 10:32:04 +01:00
|
|
|
$env.EXTENSION_REGISTRY = ($current_registry
|
|
|
|
|
| update hooks ($current_registry.hooks? | default (get-default-registry).hooks
|
|
|
|
|
| update $hook_type ($current_hooks | append $hook_entry)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get registered provider
|
2026-01-14 02:00:23 +00:00
|
|
|
export def get-provider [name: string] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let registry = (load-registry)
|
2025-12-11 21:57:05 +00:00
|
|
|
if ($name in ($registry.providers | columns)) { $registry.providers | get $name } else { {} }
|
2025-10-07 10:32:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# List all registered providers
|
2026-01-14 02:00:23 +00:00
|
|
|
export def list-providers [] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let registry = (load-registry)
|
|
|
|
|
$registry.providers | items {|name, provider|
|
|
|
|
|
{
|
|
|
|
|
name: $name
|
|
|
|
|
path: $provider.path
|
|
|
|
|
version: $provider.manifest.version
|
|
|
|
|
available: $provider.available
|
|
|
|
|
source: ($provider.path | str replace $env.HOME "~")
|
|
|
|
|
}
|
|
|
|
|
} | flatten
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get registered taskserv
|
2026-01-14 02:00:23 +00:00
|
|
|
export def get-taskserv [name: string] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let registry = (load-registry)
|
2025-12-11 21:57:05 +00:00
|
|
|
if ($name in ($registry.taskservs | columns)) { $registry.taskservs | get $name } else { {} }
|
2025-10-07 10:32:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# List all registered taskservs
|
2026-01-14 02:00:23 +00:00
|
|
|
export def list-taskservs [] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let registry = (load-registry)
|
|
|
|
|
$registry.taskservs | items {|name, taskserv|
|
|
|
|
|
{
|
|
|
|
|
name: $name
|
|
|
|
|
path: $taskserv.path
|
|
|
|
|
version: $taskserv.manifest.version
|
|
|
|
|
profiles: ($taskserv.profiles | str join ", ")
|
|
|
|
|
source: ($taskserv.path | str replace $env.HOME "~")
|
|
|
|
|
}
|
|
|
|
|
} | flatten
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Execute hooks
|
2026-01-14 02:00:23 +00:00
|
|
|
export def execute-hooks [hook_type: string, context: record] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let registry = (load-registry)
|
2025-12-11 21:57:05 +00:00
|
|
|
let hooks_all = ($registry.hooks? | default {})
|
|
|
|
|
let hooks = if ($hook_type in ($hooks_all | columns)) { $hooks_all | get $hook_type } else { [] }
|
2025-10-07 10:32:04 +01:00
|
|
|
$hooks | where enabled | each {|hook|
|
|
|
|
|
let result = (do { nu $hook.path ($context | to json) } | complete)
|
|
|
|
|
if $result.exit_code == 0 {
|
|
|
|
|
{
|
|
|
|
|
hook: $hook.path
|
|
|
|
|
extension: $hook.extension
|
|
|
|
|
output: $result.stdout
|
|
|
|
|
success: true
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
{
|
|
|
|
|
hook: $hook.path
|
|
|
|
|
extension: $hook.extension
|
|
|
|
|
error: $result.stderr
|
|
|
|
|
success: false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Check if provider exists (core or extension)
|
2026-01-14 02:00:23 +00:00
|
|
|
export def provider-exists [name: string] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let core_providers = ["aws", "local", "upcloud"]
|
|
|
|
|
($name in $core_providers) or ((get-provider $name) | is-not-empty)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Check if taskserv exists (core or extension)
|
2026-01-14 02:00:23 +00:00
|
|
|
export def taskserv-exists [name: string] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let core_path = ((get-taskservs-path) | path join $name)
|
|
|
|
|
let extension_taskserv = (get-taskserv $name)
|
|
|
|
|
|
|
|
|
|
($core_path | path exists) or ($extension_taskserv | is-not-empty)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get taskserv path (core or extension)
|
2026-01-14 02:00:23 +00:00
|
|
|
export def get-taskserv-path [name: string] {
|
2025-10-07 10:32:04 +01:00
|
|
|
let core_path = ((get-taskservs-path) | path join $name)
|
|
|
|
|
if ($core_path | path exists) {
|
|
|
|
|
$core_path
|
|
|
|
|
} else {
|
|
|
|
|
let extension_taskserv = (get-taskserv $name)
|
|
|
|
|
if ($extension_taskserv | is-not-empty) {
|
|
|
|
|
$extension_taskserv.path
|
|
|
|
|
} else {
|
|
|
|
|
""
|
|
|
|
|
}
|
|
|
|
|
}
|
chore: complete KCL to Nickel migration cleanup and setup pre-commit
Clean up 404 KCL references (99.75% complete):
- Rename kcl_* variables to schema_*/nickel_* (kcl_path→schema_path, etc.)
- Update functions: parse_kcl_file→parse_nickel_file
- Update env vars: KCL_MOD_PATH→NICKEL_IMPORT_PATH
- Fix cli/providers-install: add has_nickel and nickel_version variables
- Correct import syntax: .nickel.→.ncl.
- Update 57 files across core, CLI, config, and utilities
Configure pre-commit hooks:
- Activate: nushell-check, nickel-typecheck, markdownlint
- Comment out: Rust hooks (fmt, clippy, test), check-yaml
Testing:
- Module discovery: 9 modules (6 providers, 1 taskserv, 2 clusters) ✅
- Syntax validation: 15 core files ✅
- Pre-commit hooks: all passing ✅
2026-01-08 20:08:46 +00:00
|
|
|
}
|