#!/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)/.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)/.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 }