#!/usr/bin/env bash # # aricode — remote installer # # Intended to be served from: # https://install.aricode.dev # # Usage: # curl -fsSL https://install.aricode.dev | sh set -euo pipefail PACKAGE_NAME="aricode" PACKAGE_VERSION="0.5.0" REQUIRED_NODE_MAJOR=22 INSTALL_BASE_URL="${ARICODE_INSTALL_BASE_URL:-https://install.aricode.dev}" PACKAGE_LATEST_URL="${INSTALL_BASE_URL}/releases/aricode-latest.tgz" PACKAGE_VERSION_URL="${INSTALL_BASE_URL}/releases/aricode-${PACKAGE_VERSION}.tgz" PURPLE='\033[38;5;183m' BOLD='\033[1m' DIM='\033[2m' GREEN='\033[32m' RED='\033[31m' YELLOW='\033[33m' RESET='\033[0m' info() { printf "${PURPLE}◆${RESET} %s\n" "$1"; } ok() { printf "${GREEN}✓${RESET} %s\n" "$1"; } warn() { printf "${YELLOW}!${RESET} %s\n" "$1"; } fail() { printf "${RED}✗${RESET} %s\n" "$1"; exit 1; } cleanup() { if [ -n "${TMP_TARBALL:-}" ] && [ -f "${TMP_TARBALL}" ]; then rm -f "${TMP_TARBALL}" fi } trap cleanup EXIT check_node_version() { if ! command -v node >/dev/null 2>&1; then return 1 fi local ver ver="$(node -v 2>/dev/null | sed 's/^v//')" local major major="$(echo "$ver" | cut -d. -f1)" [ "$major" -ge "$REQUIRED_NODE_MAJOR" ] 2>/dev/null } install_node_via_nvm() { info "Installing Node.js via nvm..." if [ -z "${NVM_DIR:-}" ]; then export NVM_DIR="$HOME/.nvm" fi if [ ! -s "$NVM_DIR/nvm.sh" ]; then info "Installing nvm..." curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash fi # shellcheck disable=SC1091 [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" if ! command -v nvm >/dev/null 2>&1; then fail "nvm installation failed. Please install Node.js >= $REQUIRED_NODE_MAJOR manually: https://nodejs.org" fi nvm install "$REQUIRED_NODE_MAJOR" --default nvm use "$REQUIRED_NODE_MAJOR" ok "Node.js $(node -v) installed via nvm" } ensure_path() { local npm_bin npm_bin="$(npm config get prefix)/bin" if echo "$PATH" | tr ':' '\n' | grep -qx "$npm_bin"; then export PATH="$npm_bin:$PATH" return 0 fi local shell_rc="" if [ -n "${ZSH_VERSION:-}" ] || [ "$(basename "${SHELL:-}")" = "zsh" ]; then shell_rc="$HOME/.zshrc" elif [ -n "${BASH_VERSION:-}" ] || [ "$(basename "${SHELL:-}")" = "bash" ]; then shell_rc="$HOME/.bashrc" fi if [ -n "$shell_rc" ]; then touch "$shell_rc" if ! grep -q "$npm_bin" "$shell_rc" 2>/dev/null; then printf "\n# Added by aricode installer\nexport PATH=\"%s:\$PATH\"\n" "$npm_bin" >> "$shell_rc" info "Added $npm_bin to $shell_rc" fi fi export PATH="$npm_bin:$PATH" } download_package() { local target target="$(mktemp "/tmp/aricode-installer.XXXXXX.tgz")" info "Downloading ${PACKAGE_NAME} package..." if curl -fL --progress-bar "$PACKAGE_LATEST_URL" -o "$target"; then TMP_TARBALL="$target" ok "Downloaded latest package artifact" return 0 fi warn "Latest artifact unavailable, trying versioned release..." if curl -fL --progress-bar "$PACKAGE_VERSION_URL" -o "$target"; then TMP_TARBALL="$target" ok "Downloaded ${PACKAGE_NAME} ${PACKAGE_VERSION}" return 0 fi rm -f "$target" fail "Could not download the aricode installer artifact from ${INSTALL_BASE_URL}" } printf "\n" printf "${BOLD}${PURPLE} ◆ aricode Installer${RESET}\n" printf "${DIM} Installing from install.aricode.dev release artifacts${RESET}\n" printf "\n" if check_node_version; then ok "Node.js $(node -v) detected" else if command -v node >/dev/null 2>&1; then warn "Node.js $(node -v) found but >= $REQUIRED_NODE_MAJOR is required" else warn "Node.js not found" fi install_node_via_nvm fi if ! command -v npm >/dev/null 2>&1; then fail "npm is required but was not found." fi download_package info "Installing ${PACKAGE_NAME} from downloaded package..." npm install -g --ignore-scripts --no-audit --no-fund "$TMP_TARBALL" ok "Package installed" ensure_path printf "\n" if command -v aricode >/dev/null 2>&1; then ok "aricode command is available" printf "${DIM} installed at: $(command -v aricode)${RESET}\n" else warn "aricode command not found on PATH" warn "Restart your shell and try again." printf "\n" exit 0 fi if aricode --help >/dev/null 2>&1; then ok "aricode launcher responds" else fail "aricode was installed but failed to launch" fi printf "\n" printf "${BOLD}${PURPLE} ◆ aricode is ready${RESET}\n" printf "${DIM} Type ${RESET}${BOLD}aricode${RESET}${DIM} to start.${RESET}\n" printf "${DIM} Type ${RESET}${BOLD}aricode --help${RESET}${DIM} for usage.${RESET}\n" printf "\n"