#!/usr/bin/env bash # Path: Commands/Local/Dev/scripts/dev-stack.sh set -euo pipefail action=${1:-up} script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) project_root=$(cd -- "$script_dir/../../../.." && pwd) posix_root="$project_root/POSIX" frontend_dir="$project_root/Frontend" frontend_bake="$frontend_dir/docker-bake.hcl" backend_dir="$project_root/Backend" backend_bake="$backend_dir/docker-bake.hcl" env_dir="$project_root/Env" compose_file="$project_root/Docker/docker-compose.local.dev.yaml" local_uid=$(id -u) local_gid=$(id -g) frontend_image="moku/work-frontend:dev" backend_image="moku/work-backend:dev" frontend_volume="moku_work_frontend_node_modules" backend_go_pkg_volume="moku_work_backend_go_pkg" backend_go_build_volume="moku_work_backend_go_build" backend_runtime_dir="$backend_dir/tmp/dev" source "$script_dir/docker.sh" source "$script_dir/env.sh" source "$project_root/Commands/Local/scripts/common.sh" build_frontend() { cd "$frontend_dir" docker buildx bake -f "$frontend_bake" dev } build_backend() { cd "$backend_dir" docker buildx bake -f "$backend_bake" dev } build_images() { build_frontend build_backend } up_stack() { LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" up -d --remove-orphans --force-recreate } down_stack() { LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" down --remove-orphans --volumes } follow_logs() { LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" logs -f } clean_stack() { LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" down --remove-orphans --volumes >/dev/null 2>&1 || true remove_docker_image_if_present "$frontend_image" remove_docker_image_if_present "$backend_image" remove_docker_volume_if_present "$frontend_volume" remove_docker_volume_if_present "$backend_go_pkg_volume" remove_docker_volume_if_present "$backend_go_build_volume" rm -rf "$backend_runtime_dir" } start_stack() { build_images up_stack run_compose_api_migrations "$compose_file" "api" } case "$action" in build) ensure_docker 'docker is required for the local development stack. Install Docker first.' ensure_posix_root "$project_root" "$posix_root" build_images ;; up|start|rebuild) ensure_docker 'docker is required for the local development stack. Install Docker first.' ensure_local_env_file "$env_dir" ensure_posix_root "$project_root" "$posix_root" start_stack ;; down) ensure_docker 'docker is required for the local development stack. Install Docker first.' ensure_local_env_file "$env_dir" ensure_posix_root "$project_root" "$posix_root" confirm_destructive_action 'This will stop the local development stack and remove its containers and volumes. Continue?' down_stack ;; restart) ensure_docker 'docker is required for the local development stack. Install Docker first.' ensure_local_env_file "$env_dir" ensure_posix_root "$project_root" "$posix_root" LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" restart ;; logs) ensure_docker 'docker is required for the local development stack. Install Docker first.' ensure_local_env_file "$env_dir" ensure_posix_root "$project_root" "$posix_root" follow_logs ;; clean) ensure_docker 'docker is required for the local development stack. Install Docker first.' ensure_local_env_file "$env_dir" ensure_posix_root "$project_root" "$posix_root" confirm_destructive_action 'This will remove the local development stack, local images, volumes, backend dev state, and the local POSIX folder. Continue?' clean_stack rm -rf "$posix_root" ;; *) printf 'Unsupported dev stack action: %s\n' "$action" >&2 exit 1 ;; esac