#!/usr/bin/env bash # Absolute DB v9.5.1 # Copyright (c) 2024-2026 D.H.Maree. All rights reserved. # Author/Creator: David H Maree # Owner: D.H.Maree (ABN 21 498 105 915) — sole IP holder # Licensed to: SupportCALL AU — primary distributor # SPDX-License-Identifier: BSL-1.1 # https://absolutedb.com/ # https://downloads.absolutedb.com/install-macos.sh # # Tested on: macOS 12 Monterey, 13 Ventura, 14 Sonoma, 15 Sequoia (Intel + Apple Silicon) # Starts from a completely fresh macOS install — no prior tools required. # # Usage: # bash install-macos.sh # bash install-macos.sh --no-service # skip LaunchAgent setup # bash install-macos.sh --no-test # skip post-build test suite # bash install-macos.sh --uninstall # remove Absolute DB # bash install-macos.sh --prefix=/opt/absdb # custom install prefix # bash install-macos.sh --branch=master # checkout specific branch # # Copyright 2024-2026 SupportCALL AU & D.H.Maree # SPDX-License-Identifier: BSL-1.1 set -euo pipefail # ── Constants ───────────────────────────────────────────────────────────────── VERSION="9.5.1" REPO="https://github.com/supportcall/AbsoluteDB.git" INSTALL_DIR="${HOME}/AbsoluteDB" DATA_DIR="${HOME}/.absdb" PG_PORT=5433 REST_PORT=8080 GRPC_PORT=9090 PLIST="${HOME}/Library/LaunchAgents/com.absdb.server.plist" CONF_DIR="${HOME}/.config/absdb" CONF_FILE="${CONF_DIR}/absdb.conf" LOG_FILE="${DATA_DIR}/install.log" MIN_MACOS_MAJOR=12 # ── Colour helpers ──────────────────────────────────────────────────────────── GRN='\033[0;32m'; BLU='\033[0;34m'; YLW='\033[0;33m' RED='\033[0;31m'; CYN='\033[0;36m'; NC='\033[0m'; BOLD='\033[1m' info() { echo -e "${BLU}[INFO]${NC} $*"; } ok() { echo -e "${GRN}[ OK ]${NC} $*"; } warn() { echo -e "${YLW}[WARN]${NC} $*"; } step() { echo -e "\n${BOLD}${CYN}$*${NC}"; } die() { echo -e "\n${RED}${BOLD}[FAIL]${NC} $*" >&2 echo -e "${YLW}${BOLD}Troubleshooting guide:${NC}" >&2 echo -e " 1. Full install log: ${LOG_FILE}" >&2 echo -e " 2. Re-run with verbose output: bash -x install-macos.sh" >&2 echo -e " 3. Xcode tools missing? Run: xcode-select --install" >&2 echo -e " 4. Homebrew install failed? Visit: https://brew.sh" >&2 echo -e " 5. Apple Silicon path issue? Ensure /opt/homebrew/bin is in PATH" >&2 echo -e " 6. SIP/Gatekeeper blocking binary? Run:" >&2 echo -e " xattr -d com.apple.quarantine ${BIN_DIR}/absdb" >&2 echo -e " 7. Port ${PG_PORT} in use? Check: lsof -i :${PG_PORT}" >&2 echo -e " 8. LaunchAgent not loading? Check: launchctl error log" >&2 echo -e " log show --predicate 'subsystem == \"com.apple.xpc.launchd\"' --last 1m" >&2 echo -e " 9. See full docs: https://absolutedb.com/docs/install-macos" >&2 exit 1 } # Redirect all output to log file while keeping terminal output mkdir -p "${HOME}/.absdb" 2>/dev/null || true exec > >(tee -a "${LOG_FILE}") 2>&1 # ── Argument parsing ────────────────────────────────────────────────────────── OPT_NO_SERVICE=0 OPT_NO_TEST=0 OPT_UNINSTALL=0 BRANCH="main" for a in "$@"; do case "$a" in --no-service) OPT_NO_SERVICE=1 ;; --no-test) OPT_NO_TEST=1 ;; --uninstall) OPT_UNINSTALL=1 ;; --prefix=*) BIN_PREFIX="${a#--prefix=}" ;; --branch=*) BRANCH="${a#--branch=}" ;; --help|-h) echo "Usage: bash install-macos.sh [OPTIONS]" echo " --no-service Skip LaunchAgent setup" echo " --no-test Skip post-build test suite" echo " --uninstall Remove Absolute DB" echo " --prefix= Install binaries to /bin (default: auto-detect)" echo " --branch= Git branch to install (default: main)" exit 0 ;; *) warn "Unknown option: $a (ignored)" ;; esac done # ── Detect architecture and set prefix ─────────────────────────────────────── ARCH=$(uname -m) # Rosetta 2 detection: on Apple Silicon with Rosetta, uname -m reports x86_64 # but sysctl.proc_translated = 1. Warn the user to re-open a native terminal. if [ "${ARCH}" = "x86_64" ] && sysctl -n sysctl.proc_translated 2>/dev/null | grep -q "^1$"; then warn "Rosetta 2 translation detected. You are running an x86_64 shell on Apple Silicon." warn "For best performance, open a native arm64 terminal:" warn " Applications → Utilities → Terminal → right-click → Get Info → uncheck 'Open using Rosetta'" warn "Continuing with x86_64 build — performance will be sub-optimal." ARCH="x86_64" fi if [ "${ARCH}" = "arm64" ]; then PLATFORM="Apple Silicon (arm64)" DEFAULT_PREFIX="/opt/homebrew" HOMEBREW_PREFIX="/opt/homebrew" else PLATFORM="Intel (x86_64)" DEFAULT_PREFIX="/usr/local" HOMEBREW_PREFIX="/usr/local" fi BIN_PREFIX="${BIN_PREFIX:-${DEFAULT_PREFIX}}" BIN_DIR="${BIN_PREFIX}/bin" # ── Banner ──────────────────────────────────────────────────────────────────── echo "" echo -e "${BOLD}${GRN}╔══════════════════════════════════════════════════╗${NC}" echo -e "${BOLD}${GRN}║ Absolute DB v${VERSION} — macOS Installer ║${NC}" echo -e "${BOLD}${GRN}╚══════════════════════════════════════════════════╝${NC}" echo "" echo -e " Platform : ${BOLD}${PLATFORM}${NC}" echo -e " Install : ${BOLD}${INSTALL_DIR}${NC}" echo -e " Binaries : ${BOLD}${BIN_DIR}${NC}" echo -e " Data : ${BOLD}${DATA_DIR}${NC}" echo -e " Branch : ${BOLD}${BRANCH}${NC}" echo -e " Log : ${BOLD}${LOG_FILE}${NC}" echo "" # ── Uninstall ───────────────────────────────────────────────────────────────── if [ "${OPT_UNINSTALL}" -eq 1 ]; then step "Uninstalling Absolute DB v${VERSION}..." launchctl unload "${PLIST}" 2>/dev/null || true rm -f "${PLIST}" rm -f "${BIN_DIR}/absdb" "${BIN_DIR}/absdb-server" "${BIN_DIR}/absdb-bench" "${BIN_DIR}/adb_admin" rm -rf "${BIN_PREFIX}/include/absdb" "${BIN_PREFIX}/share/doc/absdb" rm -rf "${INSTALL_DIR}" ok "Absolute DB removed." warn "Data directory ${DATA_DIR} was NOT removed (remove manually if desired)." exit 0 fi # ── Step 1/5: Check macOS version ───────────────────────────────────────────── step "Step 1/5: Checking system requirements" MACOS_VER=$(sw_vers -productVersion 2>/dev/null || echo "0.0") MACOS_MAJOR=$(echo "${MACOS_VER}" | cut -d. -f1) info "macOS version: ${MACOS_VER}" if [ "${MACOS_MAJOR}" -lt "${MIN_MACOS_MAJOR}" ] 2>/dev/null; then warn "macOS ${MACOS_VER} is below the minimum supported version (${MIN_MACOS_MAJOR}.x)." warn "Absolute DB v${VERSION} is tested on macOS 12 and later." warn "Proceeding anyway — some features may not work correctly." else ok "macOS ${MACOS_VER} — supported" fi # Check available disk space (need at least 1.5 GB for build objects + static lib) AVAIL_KB=$(df -k "${HOME}" | awk 'NR==2 {print $4}') if [ "${AVAIL_KB:-0}" -lt 1572864 ]; then warn "Less than 1.5 GB disk space available ($(( ${AVAIL_KB:-0} / 1024 )) MB). Build may fail." else ok "Disk space: $(( ${AVAIL_KB:-0} / 1024 )) MB available" fi # Check available RAM RAM_MB=$(( $(sysctl -n hw.memsize 2>/dev/null || echo 0) / 1048576 )) if [ "${RAM_MB}" -lt 512 ]; then warn "Only ${RAM_MB} MB RAM detected. Recommend at least 512 MB." else ok "RAM: ${RAM_MB} MB" fi # ── Step 2/5: Xcode Command Line Tools ──────────────────────────────────────── step "Step 2/5: Checking Xcode Command Line Tools" XCODE_OK=0 if xcode-select -p &>/dev/null && command -v gcc &>/dev/null && command -v make &>/dev/null; then XCODE_OK=1 fi if [ "${XCODE_OK}" -eq 0 ]; then warn "Xcode Command Line Tools are not installed." echo "" echo -e "${BOLD} How to install:${NC}" echo " 1. A system dialog will appear after this script runs:" echo " xcode-select --install" echo " 2. Click 'Install' (NOT 'Get Xcode') in the dialog." echo " 3. Accept the license agreement." echo " 4. Wait 5-10 minutes for the download to complete." echo " 5. Run this installer again:" echo " bash install-macos.sh" echo "" info "Launching Xcode tools installer dialog now..." xcode-select --install 2>/dev/null || true echo "" warn "IMPORTANT: After the dialog install completes, re-run: bash install-macos.sh" exit 0 fi GCC_VER=$(gcc --version 2>/dev/null | head -1 || echo "unknown") ok "Compiler: ${GCC_VER}" # On macOS, 'gcc' is Clang — this is expected and fully supported. if gcc --version 2>/dev/null | grep -q "clang"; then info "Note: 'gcc' on macOS is Apple Clang (expected). Absolute DB builds cleanly with Clang." fi ok "make: $(make --version 2>/dev/null | head -1)" ok "Xcode tools path: $(xcode-select -p)" # ── Step 3/5: Install Homebrew + git ────────────────────────────────────────── step "Step 3/5: Checking package manager and git" # Check for git (comes with Xcode tools, but verify) if ! command -v git &>/dev/null; then info "git not found — attempting to install via Homebrew..." if ! command -v brew &>/dev/null; then info "Installing Homebrew (this requires your password for sudo)..." if command -v curl &>/dev/null; then NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || { echo "" echo -e "${RED}Homebrew installation failed.${NC}" echo " Manual install: https://brew.sh" echo " Then run: brew install git" die "Homebrew install failed — cannot continue without git" } # Add Homebrew to PATH for this session if [ "${ARCH}" = "arm64" ]; then eval "$(/opt/homebrew/bin/brew shellenv)" else eval "$(/usr/local/bin/brew shellenv)" fi ok "Homebrew installed: $(brew --version | head -1)" else die "curl not found. Install curl first or install Xcode Command Line Tools." fi fi brew install git -q fi ok "git: $(git --version)" # Verify curl is available (macOS ships with it) if command -v curl &>/dev/null; then ok "curl: $(curl --version 2>/dev/null | head -1)" else die "curl not found — macOS should include curl. Check your PATH." fi # Install Homebrew if not present (useful for future installs) if ! command -v brew &>/dev/null; then info "Homebrew not found — it is optional but recommended for managing psql and other tools." warn "To install Homebrew later: /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" fi # ── Branch detection and clone helpers ──────────────────────────────────────── _detect_branch() { local remote="${1:-origin}" if git ls-remote --heads "${remote}" main 2>/dev/null | grep -q "refs/heads/main"; then echo "main" elif git ls-remote --heads "${remote}" master 2>/dev/null | grep -q "refs/heads/master"; then echo "master" else echo "main" fi } _git_clone_with_retry() { local branch="$1" dest="$2" repo="$3" local attempt=1 delay=4 while [ "${attempt}" -le 3 ]; do # Remove any partial clone directory before each attempt if [ -d "${dest}" ] && [ ! -f "${dest}/.git/HEAD" ]; then warn "Removing incomplete directory ${dest} before retry..." rm -rf "${dest}" || true fi if git clone --depth=1 --branch="${branch}" "${repo}" "${dest}" 2>&1; then return 0 fi if [ "${attempt}" -lt 3 ]; then warn "Clone attempt ${attempt}/3 failed — retrying in ${delay}s..." sleep "${delay}"; delay=$(( delay * 2 )) fi attempt=$(( attempt + 1 )) done die "git clone failed after 3 attempts. Check: internet, DNS, firewall, VPN settings." } # ── Step 4/5: Clone and build ────────────────────────────────────────────────── step "Step 4/5: Downloading and building Absolute DB" # Detect actual branch from remote (prefers 'main') if [ "${BRANCH}" = "main" ]; then _detected="$( _detect_branch "${REPO}" )" [ "${_detected}" != "${BRANCH}" ] && { info "Remote branch detected: ${_detected}"; BRANCH="${_detected}"; } fi if [ -d "${INSTALL_DIR}/.git" ]; then info "Existing installation found — updating to v${VERSION}..." cd "${INSTALL_DIR}" info "Fetching latest source (branch: ${BRANCH})..." if ! git fetch --depth=1 origin "${BRANCH}" 2>&1; then warn "git fetch failed — removing and recloning from scratch..." cd /; rm -rf "${INSTALL_DIR}" _git_clone_with_retry "${BRANCH}" "${INSTALL_DIR}" "${REPO}" ok "Source recloned to ${INSTALL_DIR}" else # Use FETCH_HEAD — always valid after fetch, works correctly on shallow clones git reset --hard FETCH_HEAD ok "Source updated to latest ${BRANCH}" fi else [ -d "${INSTALL_DIR}" ] && rm -rf "${INSTALL_DIR}" info "Cloning Absolute DB from GitHub (30-90 seconds on first install)..." _git_clone_with_retry "${BRANCH}" "${INSTALL_DIR}" "${REPO}" ok "Source cloned to ${INSTALL_DIR}" fi cd "${INSTALL_DIR}" # Cap parallel jobs at 8 to avoid thermal throttling on high-core-count Macs _cores=$(sysctl -n hw.logicalcpu 2>/dev/null || echo 4) _jobs=$(( _cores > 8 ? 8 : _cores )) info "Compiling (using ${_jobs} of ${_cores} CPU cores)..." make clean -s 2>/dev/null || true make release -j"${_jobs}" || \ die "Build failed. Check output above. Common cause: Xcode tools update required." # Verify mandatory build artifacts exist [ -x "build/absdb" ] || [ -x "bin/absdb" ] || die "absdb binary not found after build" [ -x "build/absdb-server" ] || [ -x "bin/absdb-server" ] || die "absdb-server binary not found after build" [ -x "build/adb_admin" ] || [ -x "bin/adb_admin" ] || \ warn "adb_admin not found — protocol management CLI will not be installed" ok "Build complete" # Run test suite (unless --no-test) if [ "${OPT_NO_TEST}" -eq 0 ]; then info "Running test suite..." make test 2>&1 | tail -5 || warn "Some tests reported failures — check output above" ok "Test suite complete" else info "Test suite skipped (--no-test)" fi # Install binaries info "Installing binaries to ${BIN_DIR}..." mkdir -p "${BIN_DIR}" 2>/dev/null || true # Try without sudo first (Homebrew-managed /opt/homebrew is user-writable on Apple Silicon) if [ -w "${BIN_DIR}" ]; then install -m 755 build/absdb "${BIN_DIR}/absdb" install -m 755 build/absdb-server "${BIN_DIR}/absdb-server" install -m 755 build/absdb-bench "${BIN_DIR}/absdb-bench" 2>/dev/null || true install -m 755 build/adb_admin "${BIN_DIR}/adb_admin" 2>/dev/null || true else info "Directory ${BIN_DIR} requires sudo..." sudo install -m 755 build/absdb "${BIN_DIR}/absdb" sudo install -m 755 build/absdb-server "${BIN_DIR}/absdb-server" sudo install -m 755 build/absdb-bench "${BIN_DIR}/absdb-bench" 2>/dev/null || true sudo install -m 755 build/adb_admin "${BIN_DIR}/adb_admin" 2>/dev/null || true fi # Strip Gatekeeper quarantine attribute if present xattr -d com.apple.quarantine "${BIN_DIR}/absdb" 2>/dev/null || true xattr -d com.apple.quarantine "${BIN_DIR}/absdb-server" 2>/dev/null || true xattr -d com.apple.quarantine "${BIN_DIR}/absdb-bench" 2>/dev/null || true xattr -d com.apple.quarantine "${BIN_DIR}/adb_admin" 2>/dev/null || true # Install headers and docs if [ -w "${BIN_PREFIX}/include" ] 2>/dev/null || mkdir -p "${BIN_PREFIX}/include/absdb" 2>/dev/null; then mkdir -p "${BIN_PREFIX}/include/absdb" "${BIN_PREFIX}/share/doc/absdb" 2>/dev/null || true cp include/absolute.h include/adb_types.h "${BIN_PREFIX}/include/absdb/" 2>/dev/null || true cp README.md LICENSE "${BIN_PREFIX}/share/doc/absdb/" 2>/dev/null || true fi # Verify installed binaries actually run "${BIN_DIR}/absdb" --version &>/dev/null || warn "absdb --version failed — binary may need PATH update" "${BIN_DIR}/absdb-server" --version &>/dev/null || warn "absdb-server --version failed — check ${BIN_DIR} is in PATH" if [ -x "${BIN_DIR}/adb_admin" ]; then ok "Binaries installed and verified: ${BIN_DIR}/absdb, ${BIN_DIR}/absdb-server, ${BIN_DIR}/adb_admin" else ok "Binaries installed and verified: ${BIN_DIR}/absdb, ${BIN_DIR}/absdb-server" warn "adb_admin not installed — protocol management requires rebuilding with make release" fi # Ensure BIN_DIR is in PATH if ! echo ":${PATH}:" | grep -q ":${BIN_DIR}:"; then warn "${BIN_DIR} is not in your PATH." SHELL_NAME=$(basename "${SHELL:-bash}") if [ "${SHELL_NAME}" = "zsh" ]; then RCFILE="${HOME}/.zshrc" else RCFILE="${HOME}/.bash_profile" fi warn "Add to ${RCFILE}:" warn " export PATH=\"${BIN_DIR}:\$PATH\"" warn "Then run: source ${RCFILE}" fi # ── Step 5/5: LaunchAgent setup ─────────────────────────────────────────────── step "Step 5/5: Service setup" # ── Protocol Selection Wizard ───────────────────────────────────────────────── if [ -t 0 ] && [ -t 1 ]; then echo "" echo -e " ${BOLD}Adaptive Protocol Manager — select which ports to open${NC}" echo -e " ${DIM}Only the ports you enable will be opened (least-protocol principle).${NC}" echo "" echo -e " ${CYN}1)${NC} Minimal — PostgreSQL wire + REST ${DIM}(default)${NC}" echo -e " ${CYN}2)${NC} Web App — PostgreSQL + REST + Redis" echo -e " ${CYN}3)${NC} Microservices — PostgreSQL + REST + gRPC" echo -e " ${CYN}4)${NC} Enterprise — All protocols" echo "" read -rp " Protocol preset [1-4, default=1]: " _proto_choice _proto_choice="${_proto_choice:-1}" case "${_proto_choice}" in 2) _grpc=off; _redis=on; _prometheus=off ;; 3) _grpc=on; _redis=off; _prometheus=off ;; 4) _grpc=on; _redis=on; _prometheus=on ;; *) _grpc=off; _redis=off; _prometheus=off ;; esac else # Non-interactive (curl | bash): auto-select Minimal warn "Non-interactive shell detected — applying Minimal preset (pg_wire + rest)." warn "Re-run wizard any time: ${BIN_DIR:-/usr/local/bin}/absdb-server --setup" _grpc=off; _redis=off; _prometheus=off fi # Write config file (always — interactive and non-interactive) mkdir -p "${CONF_DIR}" cat > "${CONF_FILE}" <${NC}" echo "" # ───────────────────────────────────────────────────────────────────────────── mkdir -p "${DATA_DIR}" if [ "${OPT_NO_SERVICE}" -eq 0 ]; then info "Creating LaunchAgent for auto-start on login..." mkdir -p "${HOME}/Library/LaunchAgents" cat > "${PLIST}" < Label com.absdb.server ProgramArguments ${BIN_DIR}/absdb-server -c ${CONF_FILE} RunAtLoad KeepAlive SuccessfulExit ThrottleInterval 10 StandardOutPath ${DATA_DIR}/absdb.log StandardErrorPath ${DATA_DIR}/absdb-error.log WorkingDirectory ${DATA_DIR} PLIST_EOF # Pre-flight: check ports are not already bound by another process for _port in "${PG_PORT}" "${REST_PORT}"; do if lsof -iTCP:"${_port}" -sTCP:LISTEN &>/dev/null 2>&1; then warn "Port ${_port} is already in use — service may fail to start." warn "Check with: lsof -i :${_port}" fi done # Unload any previous version, then load the new one launchctl unload "${PLIST}" 2>/dev/null || true if ! launchctl load "${PLIST}" 2>/dev/null; then warn "launchctl load failed — attempting with launchctl bootstrap (macOS 10.15+)..." launchctl bootstrap "gui/$(id -u)" "${PLIST}" 2>/dev/null || \ die "LaunchAgent failed to load. Check: log show --predicate 'subsystem == \"com.apple.xpc.launchd\"' --last 1m" fi ok "LaunchAgent loaded: ${PLIST}" # Brief delay to let launchd start the process sleep 2 # Check if the process exited immediately (indicates a startup error) if launchctl list 2>/dev/null | grep -q "com.absdb.server"; then _exit_code=$(launchctl list 2>/dev/null | awk '/com\.absdb\.server/{print $1}') if [ "${_exit_code:-0}" != "0" ] && [ "${_exit_code:-0}" != "-" ]; then warn "LaunchAgent process exited with code ${_exit_code}." warn "Check: tail -50 ${DATA_DIR}/absdb-error.log" fi fi # Wait for server to start (up to 15 seconds) info "Waiting for server to start..." STARTED=0 for i in $(seq 1 15); do sleep 1 if lsof -iTCP:"${PG_PORT}" -sTCP:LISTEN &>/dev/null 2>&1; then ok "Server is listening on port ${PG_PORT}" STARTED=1 break fi done if [ "${STARTED}" -eq 0 ]; then warn "Server did not start within 15 seconds." warn " Check LaunchAgent log: tail -f ${DATA_DIR}/absdb-error.log" warn " Check system log: log show --predicate 'subsystem == \"com.apple.xpc.launchd\"' --last 2m" warn " Port ${PG_PORT} in use? Run: lsof -i :${PG_PORT}" fi else info "LaunchAgent setup skipped (--no-service)" info "To start manually:" info " ${BIN_DIR}/absdb-server -c ${CONF_FILE}" fi # ── Health check ───────────────────────────────────────────────────────────── if [ "${OPT_NO_SERVICE}" -eq 0 ]; then echo "" info "Testing REST API health endpoint..." REST_OK=0 for i in $(seq 1 10); do sleep 1 HEALTH=$(curl -sf --connect-timeout 2 "http://localhost:${REST_PORT}/health" 2>/dev/null || true) if echo "${HEALTH}" | grep -q '"status"'; then ok "REST API healthy: ${HEALTH}" REST_OK=1 break fi done if [ "${REST_OK}" -eq 0 ]; then warn "REST API on port ${REST_PORT} did not respond within 10 seconds." warn " Check logs: tail -f ${DATA_DIR}/absdb.log" fi fi # ── Production vs Testing wizard ───────────────────────────────────────────── if [ -t 0 ] && [ -t 1 ]; then echo "" echo -e " ${BOLD}Is this installation for Production or Testing/Evaluation?${NC}" echo "" echo -e " ${BOLD}${RED}┌─────────────────────────────────────────────────────────────────┐${NC}" echo -e " ${BOLD}${RED}│${NC} ${CYN}1)${NC} ${BOLD}Production${NC} — clean start, no sample data ${BOLD}${RED}│${NC}" echo -e " ${BOLD}${RED}│${NC} ${CYN}2)${NC} ${BOLD}Testing${NC} — optionally load tier-sized sample data ${BOLD}${RED}│${NC}" echo -e " ${BOLD}${RED}└─────────────────────────────────────────────────────────────────┘${NC}" echo "" INSTALL_TYPE="" while true; do read -rp " Enter choice [1/2] (default: 1): " _it _it="${_it:-1}" case "${_it}" in 1|production|prod) INSTALL_TYPE="production"; break ;; 2|testing|test) INSTALL_TYPE="testing"; break ;; *) echo " Enter 1 or 2." ;; esac done if [ "${INSTALL_TYPE}" = "testing" ]; then echo "" read -rp " Generate sample/test data now? [y/N]: " _wd _wd="${_wd:-n}" if [[ "${_wd,,}" == "y" || "${_wd,,}" == "yes" ]]; then echo "" echo -e " ${BOLD}Select tier size:${NC}" echo "" echo -e " ${CYN}1)${NC} Community — ${YLW}2 GB${NC}" echo -e " ${CYN}2)${NC} SME — ${YLW}3 GB${NC}" echo -e " ${CYN}3)${NC} Professional — ${YLW}10 GB${NC}" echo -e " ${CYN}4)${NC} Enterprise — ${YLW}20 GB${NC}" echo "" DATA_TIER="" while true; do read -rp " Enter tier [1-4 or name]: " _dt _dt="${_dt,,}" case "${_dt}" in 1|community) DATA_TIER="community"; break ;; 2|sme) DATA_TIER="sme"; break ;; 3|pro|professional) DATA_TIER="pro"; break ;; 4|enterprise) DATA_TIER="enterprise"; break ;; *) echo " Enter 1–4 or community/sme/pro/enterprise." ;; esac done GEN_SH="${INSTALL_DIR:-${HOME}/AbsoluteDB}/tools/gen_test_data.sh" GEN_PY="${INSTALL_DIR:-${HOME}/AbsoluteDB}/tools/gen_test_data.py" if [ -f "${GEN_SH}" ]; then bash "${GEN_SH}" --tier "${DATA_TIER}" --host 127.0.0.1 \ --port "${PG_PORT:-5433}" --dbname absdb --drop-existing \ || echo "[WARN] Sample data generation encountered errors." elif [ -f "${GEN_PY}" ] && command -v python3 &>/dev/null; then python3 -c "import psycopg2" &>/dev/null 2>&1 \ || python3 -m pip install --quiet psycopg2-binary python3 "${GEN_PY}" --tier "${DATA_TIER}" --host 127.0.0.1 \ --port "${PG_PORT:-5433}" --dbname absdb --drop-existing \ || echo "[WARN] Sample data generation encountered errors." else echo "[WARN] gen_test_data.sh not found. Run later:" echo " bash ${GEN_SH} --tier ${DATA_TIER}" fi fi else echo " Production install — no sample data loaded." echo " To generate test data later: bash tools/gen_test_data.sh" fi fi # ── Final summary ───────────────────────────────────────────────────────────── SHELL_NAME=$(basename "${SHELL:-bash}") echo "" echo -e "${BOLD}${GRN}╔══════════════════════════════════════════════════════════╗${NC}" echo -e "${BOLD}${GRN}║ Absolute DB v${VERSION} installed successfully! ║${NC}" echo -e "${BOLD}${GRN}╚══════════════════════════════════════════════════════════╝${NC}" echo "" echo -e "${BOLD} Quick start:${NC}" echo "" echo -e " ${CYN}REST API:${NC}" echo " curl http://localhost:${REST_PORT}/health" echo " curl -X POST http://localhost:${REST_PORT}/sql \\" echo " -H 'Content-Type: application/json' \\" echo " -d '{\"sql\":\"SELECT 1+1 AS result\"}'" echo "" echo -e " ${CYN}PostgreSQL wire (psql):${NC}" if command -v psql &>/dev/null; then echo " psql -h localhost -p ${PG_PORT}" else echo " # Install psql first:" echo " brew install libpq && brew link --force libpq" echo " psql -h localhost -p ${PG_PORT}" fi echo "" echo -e " ${CYN}gRPC (port ${GRPC_PORT}):${NC}" echo " grpcurl -plaintext localhost:${GRPC_PORT} list" echo "" echo -e " ${CYN}CLI:${NC}" echo " absdb # interactive shell" echo " absdb -c \"SELECT version()\" # single query" echo "" echo -e " ${CYN}Service management:${NC}" echo " launchctl list | grep absdb # check status" echo " launchctl unload ${PLIST} # stop" echo " launchctl load ${PLIST} # start" echo " tail -f ${DATA_DIR}/absdb.log # view logs" echo "" echo -e "${BOLD} Next steps:${NC}" echo "" echo -e " ${YLW}1. macOS firewall:${NC} If you have the Application Firewall enabled" echo -e " (System Settings → Network → Firewall), allow absdb-server when prompted," echo -e " or add it manually under Firewall Options." echo "" echo -e " ${YLW}2. Default ports:${NC}" echo -e " ${DIM}PostgreSQL wire:${NC} ${PG_PORT} ${DIM}REST API + Web console:${NC} ${REST_PORT}" echo -e " ${DIM}gRPC / HTTP/2:${NC} ${GRPC_PORT} ${DIM}Redis RESP3:${NC} 6379" echo "" echo -e " ${YLW}3. Open the web management console:${NC}" echo -e " ${CYN}open http://localhost:${REST_PORT}/console${NC}" echo "" echo -e " ${YLW}4. Enable TLS for production:${NC}" echo -e " See ${DIM}https://absolutedb.com/docs/tls${NC}" echo "" echo -e " ${CYN}Uninstall:${NC}" echo " bash install-macos.sh --uninstall" echo "" echo -e " ${CYN}Docs:${NC} https://absolutedb.com/docs" echo -e " ${CYN}Support:${NC} https://absolutedb.com/support" echo ""