Require Node.js 22 to match project runtime requirements Handle malformed or failing node version output safely Improve install success guidance and PATH diagnostics
284 lines
7.6 KiB
Bash
Executable File
284 lines
7.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# OpenChamber Install Script
|
|
# Usage: curl -fsSL https://raw.githubusercontent.com/btriapitsyn/openchamber/main/scripts/install.sh | bash
|
|
|
|
set -euo pipefail
|
|
|
|
PACKAGE_NAME="@openchamber/web"
|
|
BIN_NAME="openchamber"
|
|
MIN_NODE_VERSION=22
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
info() {
|
|
echo -e "${BLUE}info${NC} $1"
|
|
}
|
|
|
|
success() {
|
|
echo -e "${GREEN}success${NC} $1"
|
|
}
|
|
|
|
warn() {
|
|
echo -e "${YELLOW}warn${NC} $1"
|
|
}
|
|
|
|
error() {
|
|
echo -e "${RED}error${NC} $1"
|
|
}
|
|
|
|
# Check if a command exists
|
|
command_exists() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
# Get Node.js major version
|
|
get_node_version() {
|
|
if command_exists node; then
|
|
local version
|
|
version=$(node -v 2>/dev/null || true)
|
|
version=${version#v}
|
|
version=${version%%.*}
|
|
if [[ "$version" =~ ^[0-9]+$ ]]; then
|
|
echo "$version"
|
|
else
|
|
echo "0"
|
|
fi
|
|
else
|
|
echo "0"
|
|
fi
|
|
}
|
|
|
|
# Detect preferred package manager
|
|
detect_package_manager() {
|
|
# Check if running inside an npm/pnpm/yarn/bun context
|
|
if [ -n "${npm_config_user_agent:-}" ]; then
|
|
case "$npm_config_user_agent" in
|
|
pnpm*) echo "pnpm"; return ;;
|
|
yarn*) echo "yarn"; return ;;
|
|
bun*) echo "bun"; return ;;
|
|
npm*) echo "npm"; return ;;
|
|
esac
|
|
fi
|
|
|
|
# Check for lockfiles in current directory (user preference)
|
|
if [ -f "pnpm-lock.yaml" ]; then
|
|
echo "pnpm"; return
|
|
elif [ -f "yarn.lock" ]; then
|
|
echo "yarn"; return
|
|
elif [ -f "bun.lock" ] || [ -f "bun.lockb" ]; then
|
|
echo "bun"; return
|
|
elif [ -f "package-lock.json" ]; then
|
|
echo "npm"; return
|
|
fi
|
|
|
|
# Check which package managers are available (prefer pnpm > bun > yarn > npm)
|
|
if command_exists pnpm; then
|
|
echo "pnpm"
|
|
elif command_exists bun; then
|
|
echo "bun"
|
|
elif command_exists yarn; then
|
|
echo "yarn"
|
|
elif command_exists npm; then
|
|
echo "npm"
|
|
else
|
|
echo "none"
|
|
fi
|
|
}
|
|
|
|
# Get install command for package manager
|
|
get_install_command() {
|
|
local pm=$1
|
|
case "$pm" in
|
|
pnpm) echo "pnpm add -g $PACKAGE_NAME" ;;
|
|
yarn) echo "yarn global add $PACKAGE_NAME" ;;
|
|
bun) echo "bun add -g $PACKAGE_NAME" ;;
|
|
npm) echo "npm install -g $PACKAGE_NAME" ;;
|
|
*) echo "" ;;
|
|
esac
|
|
}
|
|
|
|
# Install Node.js suggestion
|
|
suggest_node_install() {
|
|
echo ""
|
|
error "Node.js $MIN_NODE_VERSION+ is required but not found."
|
|
echo ""
|
|
echo "Install Node.js using one of these methods:"
|
|
echo ""
|
|
|
|
if [[ "${OSTYPE:-}" == "darwin"* ]]; then
|
|
echo " Using Homebrew:"
|
|
echo " brew install node"
|
|
echo ""
|
|
fi
|
|
|
|
echo " Using nvm (recommended):"
|
|
echo " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash"
|
|
echo " nvm install $MIN_NODE_VERSION"
|
|
echo ""
|
|
echo " Using fnm:"
|
|
echo " curl -fsSL https://fnm.vercel.app/install | bash"
|
|
echo " fnm install $MIN_NODE_VERSION"
|
|
echo ""
|
|
echo " Official installer:"
|
|
echo " https://nodejs.org/"
|
|
echo ""
|
|
exit 1
|
|
}
|
|
|
|
# Install package manager suggestion
|
|
suggest_pm_install() {
|
|
echo ""
|
|
error "No package manager found (npm, pnpm, yarn, or bun)."
|
|
echo ""
|
|
echo "Install a package manager:"
|
|
echo ""
|
|
echo " npm (comes with Node.js):"
|
|
echo " Install Node.js from https://nodejs.org/"
|
|
echo ""
|
|
echo " pnpm (recommended):"
|
|
echo " curl -fsSL https://get.pnpm.io/install.sh | sh -"
|
|
echo ""
|
|
echo " bun:"
|
|
echo " curl -fsSL https://bun.sh/install | bash"
|
|
echo ""
|
|
echo " yarn:"
|
|
echo " npm install -g yarn"
|
|
echo ""
|
|
exit 1
|
|
}
|
|
|
|
main() {
|
|
echo ""
|
|
echo " ╭───────────────────────────────────╮"
|
|
echo " │ │"
|
|
echo " │ OpenChamber Installer │"
|
|
echo " │ Web interface for OpenCode │"
|
|
echo " │ │"
|
|
echo " ╰───────────────────────────────────╯"
|
|
echo ""
|
|
|
|
# Check Node.js
|
|
info "Checking Node.js..."
|
|
NODE_VERSION=$(get_node_version)
|
|
|
|
if [ "$NODE_VERSION" -lt "$MIN_NODE_VERSION" ]; then
|
|
if [ "$NODE_VERSION" -eq "0" ]; then
|
|
suggest_node_install
|
|
else
|
|
error "Node.js $MIN_NODE_VERSION+ required, found v$NODE_VERSION"
|
|
suggest_node_install
|
|
fi
|
|
fi
|
|
success "Node.js v$NODE_VERSION found"
|
|
|
|
# If OpenChamber is already installed, hand off to its own updater instead
|
|
# of guessing a package manager. `openchamber update` detects which manager
|
|
# actually owns the existing global install and reinstalls with that one —
|
|
# reinstalling with a different manager here would orphan files and break PATH.
|
|
if command_exists "$BIN_NAME"; then
|
|
info "OpenChamber is already installed — updating via 'openchamber update'..."
|
|
echo ""
|
|
if openchamber update; then
|
|
echo ""
|
|
success "OpenChamber is up to date!"
|
|
exit 0
|
|
fi
|
|
echo ""
|
|
error "Update failed."
|
|
echo ""
|
|
echo " Try running it manually:"
|
|
echo " openchamber update"
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
|
|
# Detect package manager
|
|
info "Detecting package manager..."
|
|
PM=$(detect_package_manager)
|
|
|
|
if [ "$PM" = "none" ]; then
|
|
suggest_pm_install
|
|
fi
|
|
success "Using $PM"
|
|
|
|
# Get install command
|
|
INSTALL_CMD=$(get_install_command "$PM")
|
|
|
|
if [ -z "$INSTALL_CMD" ]; then
|
|
error "Could not determine install command"
|
|
exit 1
|
|
fi
|
|
|
|
# Install
|
|
echo ""
|
|
info "Installing OpenChamber..."
|
|
echo " Running: $INSTALL_CMD"
|
|
echo ""
|
|
|
|
if eval "$INSTALL_CMD"; then
|
|
echo ""
|
|
# Wordmark (toilet "pagga", "Open"/"Chamber" stacked).
|
|
# Hardcoded so the user needs no extra tools.
|
|
printf '%b' "$BLUE"
|
|
cat <<'EOF'
|
|
░█▀█░█▀█░█▀▀░█▀█
|
|
░█░█░█▀▀░█▀▀░█░█
|
|
░▀▀▀░▀░░░▀▀▀░▀░▀
|
|
░█▀▀░█░█░█▀█░█▄█░█▀▄░█▀▀░█▀▄
|
|
░█░░░█▀█░█▀█░█░█░█▀▄░█▀▀░█▀▄
|
|
░▀▀▀░▀░▀░▀░▀░▀░▀░▀▀░░▀▀▀░▀░▀
|
|
EOF
|
|
printf '%b\n' "$NC"
|
|
success "OpenChamber installed successfully!"
|
|
echo ""
|
|
|
|
# Verify the binary is actually reachable. Global installs frequently
|
|
# land in a directory that isn't on PATH — surface that instead of
|
|
# letting the user hit a confusing "command not found".
|
|
if command_exists "$BIN_NAME"; then
|
|
echo " Get started:"
|
|
echo " openchamber # Start server on port 3000"
|
|
echo " openchamber --help # Show all options"
|
|
else
|
|
warn "'$BIN_NAME' was installed but isn't on your PATH yet."
|
|
echo ""
|
|
bin_dir=""
|
|
case "$PM" in
|
|
npm) bin_dir=$(npm prefix -g 2>/dev/null)/bin ;;
|
|
pnpm) bin_dir=$(pnpm bin -g 2>/dev/null || true) ;;
|
|
yarn) bin_dir=$(yarn global bin 2>/dev/null || true) ;;
|
|
bun) bin_dir="${BUN_INSTALL:-$HOME/.bun}/bin" ;;
|
|
esac
|
|
if [ -n "$bin_dir" ]; then
|
|
echo " Add it to your PATH (then restart your terminal):"
|
|
echo " export PATH=\"$bin_dir:\$PATH\""
|
|
else
|
|
echo " Add your package manager's global bin directory to PATH,"
|
|
echo " then restart your terminal and run: openchamber"
|
|
fi
|
|
fi
|
|
echo ""
|
|
echo " Prerequisites:"
|
|
echo " Make sure OpenCode is running: opencode serve"
|
|
echo ""
|
|
else
|
|
echo ""
|
|
error "Installation failed"
|
|
echo ""
|
|
echo " Try running manually:"
|
|
echo " $INSTALL_CMD"
|
|
echo ""
|
|
echo " If you get permission errors, see:"
|
|
echo " https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally"
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
main "$@"
|