# Extension Registry # Manages registration and lookup of providers, taskservs, and hooks use loader.nu * # Get default extension registry export def get-default-registry []: nothing -> record { { 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 def get-registry-cache-file []: nothing -> string { 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 export def load-registry []: nothing -> record { let cache_file = (get-registry-cache-file) if ($cache_file | path exists) { open $cache_file } else { get-default-registry } } # Save registry to cache export def save-registry [registry: record]: nothing -> nothing { let cache_file = (get-registry-cache-file) $registry | to json | save -f $cache_file } # Initialize extension registry export def init-registry []: nothing -> nothing { # 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 export def --env register-provider [name: string, path: string, manifest: record]: nothing -> nothing { 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 export def --env register-taskserv [name: string, path: string, manifest: record]: nothing -> nothing { 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 export def --env register-hook [hook_type: string, hook_path: string, extension_name: string]: nothing -> nothing { let hook_entry = { path: $hook_path extension: $extension_name enabled: true } let current_registry = ($env.EXTENSION_REGISTRY? | default (get-default-registry)) let current_hooks = ($current_registry.hooks? | get -o $hook_type | default []) $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 export def get-provider [name: string]: nothing -> record { let registry = (load-registry) $registry.providers | get -o $name | default {} } # List all registered providers export def list-providers []: nothing -> table { 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 export def get-taskserv [name: string]: nothing -> record { let registry = (load-registry) $registry.taskservs | get -o $name | default {} } # List all registered taskservs export def list-taskservs []: nothing -> table { 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 export def execute-hooks [hook_type: string, context: record]: nothing -> list { let registry = (load-registry) let hooks = ($registry.hooks? | get -o $hook_type | default []) $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) export def provider-exists [name: string]: nothing -> bool { let core_providers = ["aws", "local", "upcloud"] ($name in $core_providers) or ((get-provider $name) | is-not-empty) } # Check if taskserv exists (core or extension) export def taskserv-exists [name: string]: nothing -> bool { let core_path = ($env.PROVISIONING_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) export def get-taskserv-path [name: string]: nothing -> string { let core_path = ($env.PROVISIONING_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 { "" } } }