dx/dxkit/commands/workspace.command.sh

145 lines
No EOL
4 KiB
Bash

#!/usr/bin/env bash
# ============================================
# Workspace Command
# ============================================
#
# Drops into a subshell with all driver commands
# AND all static dx commands available as plain
# functions — no 'dx' prefix needed.
#
# The prompt changes to signal you are inside
# the dx workspace.
#
# Usage:
# dx workspace
# dx ws
function cmd::workspace::run() {
local framework
framework="$(app::framework)"
local driver
driver="$(driver::resolve)"
local driver_file
driver_file="$(ctx::dxkit)/drivers/${driver}/driver.sh"
if [[ ! -f "$driver_file" ]]; then
log::error "No driver found for framework '${framework}' (resolved: ${driver})"
log::error "Cannot start dx workspace without an active driver."
return 1
fi
local rc_file
rc_file="$(mktemp /tmp/dx-workspace-rc.XXXXXX)"
cat > "$rc_file" <<RCEOF
# ============================================
# dx workspace rc — sourced for subshell only
# ============================================
# Carry over user's existing rc if present
if [[ -f "\$HOME/.bashrc" ]]; then
source "\$HOME/.bashrc" 2>/dev/null || true
elif [[ -f "\$HOME/.bash_profile" ]]; then
source "\$HOME/.bash_profile" 2>/dev/null || true
fi
# Load dxkit bootstrap — sources core, detects platform,
# applies MSYS2 guards, and defines dx::load_modules
source "$(ctx::dxkit)/bootstrap.sh"
# Set framework before loading app so app::on_load
# resolves the correct framework module
export APP_FRAMEWORK="${framework}"
# Load all standard modules (mirrors dx entrypoint)
dx::load_modules
load_module app
env::load_env_files
# Source the active driver so its functions are in scope
source "${driver_file}"
# ============================================
# Driver command wrappers (run in-process)
# e.g. migrate-create → yii2::migrate::create
# ============================================
$(
for cmd in "${!DRIVER_COMMANDS[@]}"; do
echo "function ${cmd}() { ${DRIVER_COMMANDS[$cmd]} \"\$@\"; }"
done
)
# ============================================
# Static dx command wrappers (subprocess)
# Uses \$PROJECT_ROOT/dx to avoid path mangling
# on Windows/MSYS2 — PROJECT_ROOT is exported
# by bootstrap so it is always available here.
# ============================================
$(
while IFS= read -r -d '' cmd_file; do
cmd_name="$(basename "$cmd_file" .command.sh)"
[[ "$cmd_name" == "workspace" ]] && continue
echo "function ${cmd_name}() { \"\$PROJECT_ROOT/dx\" ${cmd_name} \"\$@\"; }"
done < <(find "$(ctx::dxkit)/commands" -name "*.command.sh" -print0)
)
# ============================================
# Prompt
# ============================================
export PS1="\[\033[0;36m\][dx:${driver}]\[\033[0m\] \w \$ "
# ============================================
# Welcome
# ============================================
echo ""
echo " dx workspace — ${framework}"
echo " Type 'exit' to return to your shell."
echo ""
echo " Framework commands:"
$(
for cmd in $(echo "${!DRIVER_COMMANDS[@]}" | tr ' ' '\n' | sort); do
echo " echo \" ${cmd}\""
done
)
echo ""
RCEOF
bash --rcfile "$rc_file" -i
rm -f "$rc_file"
}
function cmd::workspace::help() {
local framework
framework="$(app::framework)"
cat <<EOF
Usage: dx workspace
dx ws
Drops into a subshell with all framework and dx commands
available without the 'dx' prefix. Type 'exit' to return.
Active framework: ${framework}
Inside dx workspace, all of these work without 'dx':
Framework commands:
$(
for cmd in $(echo "${!DRIVER_COMMANDS[@]}" | tr ' ' '\n' | sort); do
printf " %-28s\n" "$cmd"
done
)
Static dx commands:
$(
while IFS= read -r -d '' cmd_file; do
cmd_name="$(basename "$cmd_file" .command.sh)"
[[ "$cmd_name" == "workspace" ]] && continue
printf " %-28s\n" "$cmd_name"
done < <(find "$(ctx::dxkit)/commands" -name "*.command.sh" -print0)
)
Shorthand: dx ws
EOF
}