wgctl/core/framework/module.sh
Nuno Duque Nunes 290ac24d88 refactor: core directory restructure
- core/framework/: flag.sh, hook.sh, help.sh, command.sh, mixin.sh
- core/app/: wgctl-specific context.sh, json.sh
- core/framework/mixins/: json_output, no_color mixins
- core/core.sh: sources framework/core.sh + app/core.sh
- PYTHONPATH exported in app/core.sh for lib/ module resolution
- command::_load_mixins: uses _FRAMEWORK_DIR for mixin path
2026-05-30 02:50:43 +00:00

78 lines
No EOL
1.9 KiB
Bash

#!/usr/bin/env bash
# ============================================
# Module Registry
# ============================================
declare -A _LOADED_MODULES=()
readonly _MODULE_AUTO_LOAD_HOOK="on_load"
# ============================================
# Helpers
# ============================================
function module::loaded() { [[ -n "${_LOADED_MODULES["$1"]:-}" ]]; }
# Convert path-style name to namespace
# e.g. firewall/iptables -> fw::iptables
function module::to_namespace() { echo "${1//\//:}"; }
# Build fully qualified function name
# e.g. module::fn "firewall/iptables" "on_load" -> fw::iptables::on_load
function module::fn() {
local namespace
namespace=$(module::to_namespace "$1")
echo "${namespace}::${2}"
}
function module::has_function() { declare -F "$(module::fn "$1" "$2")" >/dev/null 2>&1; }
function module::is_auto_load() { declare -F "$(module::fn "$1" on_load)" >/dev/null 2>&1; }
# ============================================
# Loader
# ============================================
function load_module() {
local name="$1"
# Wildcard: load all submodules in a directory
if [[ "$name" == *"/*" ]]; then
_load_module_dir "${name%/*}"
return $?
fi
module::loaded "$name" && return 0
local path
path="$(ctx::modules)/${name}.module.sh"
if [[ ! -f "$path" ]]; then
log::error "Module not found: ${name} (${path})"
return 1
fi
source "$path"
_LOADED_MODULES["$name"]=1
core::call_if_exists "$(module::fn "$name" on_load)"
return 0
}
function _load_module_dir() {
local dir="${1:-}"
local module_dir
module_dir="$(ctx::modules)/${dir}"
if [[ ! -d "$module_dir" ]]; then
log::error "Module directory not found: ${dir} (${module_dir})"
return 1
fi
for file in "${module_dir}"/*.module.sh; do
[[ -f "$file" ]] || continue
local subname="${dir}/$(basename "${file%.module.sh}")"
load_module "$subname"
done
}