# Extension Loader # Discovers and loads extensions from multiple sources use ../config/accessor.nu * # Extension discovery paths in priority order export def get-extension-paths []: nothing -> list { [ # Project-specific extensions (highest priority) ($env.PWD | path join ".provisioning" "extensions") # User extensions ($env.HOME | path join ".provisioning-extensions") # System-wide extensions "/opt/provisioning-extensions" # Environment variable override (get-extensions-path) ] | where ($it | is-not-empty) | where ($it | path exists) } # Load extension manifest export def load-manifest [extension_path: string]: nothing -> record { let manifest_file = ($extension_path | path join "manifest.yaml") if ($manifest_file | path exists) { open $manifest_file } else { { name: ($extension_path | path basename) version: "1.0.0" type: "unknown" requires: [] permissions: [] hooks: {} } } } # Check if extension is allowed export def is-extension-allowed [manifest: record]: nothing -> bool { let mode = (get-extension-mode) let allowed = (get-allowed-extensions | split row "," | each { str trim }) let blocked = (get-blocked-extensions | split row "," | each { str trim }) match $mode { "disabled" => false, "restricted" => { if ($blocked | any {|x| $x == $manifest.name}) { false } else if ($allowed | is-empty) { true } else { ($allowed | any {|x| $x == $manifest.name}) } }, _ => { not ($blocked | any {|x| $x == $manifest.name}) } } } # Discover providers in extension paths export def discover-providers []: nothing -> table { get-extension-paths | each {|ext_path| let providers_path = ($ext_path | path join "providers") if ($providers_path | path exists) { glob ($providers_path | path join "*") | where ($it | path type) == "dir" | each {|provider_path| let manifest = (load-manifest $provider_path) if (is-extension-allowed $manifest) and $manifest.type == "provider" { { name: ($provider_path | path basename) path: $provider_path manifest: $manifest source: $ext_path } } else { null } } | where ($it != null) } else { [] } } | flatten } # Discover taskservs in extension paths export def discover-taskservs []: nothing -> table { get-extension-paths | each {|ext_path| let taskservs_path = ($ext_path | path join "taskservs") if ($taskservs_path | path exists) { glob ($taskservs_path | path join "*") | where ($it | path type) == "dir" | each {|taskserv_path| let manifest = (load-manifest $taskserv_path) if (is-extension-allowed $manifest) and $manifest.type == "taskserv" { { name: ($taskserv_path | path basename) path: $taskserv_path manifest: $manifest source: $ext_path } } else { null } } | where ($it != null) } else { [] } } | flatten } # Check extension requirements export def check-requirements [manifest: record]: nothing -> bool { if ($manifest.requires | is-empty) { true } else { $manifest.requires | all {|req| (which $req | length) > 0 } } } # Load extension hooks export def load-hooks [extension_path: string, manifest: record]: nothing -> record { if ($manifest.hooks | is-not-empty) { $manifest.hooks | items {|key, value| let hook_file = ($extension_path | path join $value) if ($hook_file | path exists) { {key: $key, value: $hook_file} } } | reduce --fold {} {|it, acc| $acc | insert $it.key $it.value} } else { {} } }