dx/dxkit/core/loader.sh

122 lines
No EOL
2.8 KiB
Bash

#!/usr/bin/env bash
function require_file() {
[[ -f "$1" ]]
}
function require_directory() {
[[ -d "$1" ]]
}
function load_file() {
local mode="required"
local file
# Check if first argument is a mode
if [[ "$1" == "required" || "$1" == "optional" ]]; then
mode="$1"
shift
fi
file="$1"
if [[ "$mode" == "required" && ! -f "$file" ]]; then
echo "❌ Missing file: $file" >&2
return 1
fi
# Source if file exists
if [[ -f "$file" ]]; then
source "$file"
fi
}
# ============================================
# load_module — Loads $(ctx::modules)/<name>.module.sh
# Always required.
# ============================================
function load_module() {
local name="$1"
# Wildcard: Load all submodules
if [[ "$name" == *"/*" ]]; then
local dir="${name%/*}"
local module_dir
module_dir="$(ctx::modules)/${dir}"
if [[ ! -d "$module_dir" ]]; then
log::error "Module directory not found: ${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
return 0
fi
# Normal single module load
local file
file="$(ctx::modules)/${name}.module.sh"
module::loaded "$name" && return 0
if [[ ! -f "$file" ]]; then
log::error "Module not found: ${name}"
return 1
fi
source "$file"
_LOADED_MODULES["$name"]=1
core::call_if_exists "$(module::to_namespace "$name")::on_load"
}
# ============================================
# load_command — Loads $(ctx::commands)/<name>.command.sh
#
# Returns:
# 0 — file found and sourced
# 1 — file not found (caller decides how to handle)
#
# After sourcing, does NOT validate ::run here —
# that's the dispatcher's job, keeping this function
# a clean "did the file exist?" predicate.
# ============================================
function load_command() {
local name="$1"
local file
file="$(ctx::commands)/${name}.command.sh"
if [[ ! -f "$file" ]]; then
return 1 # No command file, not an error by itself
fi
source "$file"
_LOADED_COMMANDS["$name"]=1
core::call_if_exists "$(command::fn "$name" on_load)"
# core::call_if_exists "$(command::to_namespace "$name")::on_load"
return 0
}
# ============================================
# load_command_strict — Load + assert ::run exists
# ============================================
function load_command_strict() {
local name="$1"
if ! load_command "$name"; then
echo "❌ No command file found for: '${name}'" >&2
return 1
fi
if ! core::function_exists "${name}::run"; then
echo "❌ Command '${name}' loaded but '${name}::run' is not defined" >&2
echo " Expected function: ${name}::run()" >&2
return 1
fi
}