dev-deploy/installSaltcorn.sh
2026-05-17 17:31:49 -05:00

150 lines
4.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# installSaltcorn.sh -- reproduce this Saltcorn dev environment from scratch.
#
# Layout created:
# <dest>/
# saltcorn/ upstream saltcorn checkout (cloned + built)
# .dev-state/ per-instance state (sqlite, files, env.sh, sessions)
# startServer.sh launcher
#
# After this, `cd <dest> && ./startServer.sh` boots Saltcorn on
# http://localhost:3000/.
#
# Usage: ./installSaltcorn.sh [destination] (default: ./saltcorn)
set -euo pipefail
DEST="${1:-./saltcorn}"
REPO_URL="https://github.com/saltcorn/saltcorn.git"
ADMIN_EMAIL="admin@local"
ADMIN_PASSWORD="AdminP@ss1"
# --- prerequisites ---
for cmd in git curl; do
command -v "$cmd" >/dev/null || { echo "$cmd not found in PATH"; exit 1; }
done
# Use a user-local nvm at ~/.nvm rather than system node, matching this dev
# environment. The .dev-state/env.sh written below sources the same nvm, so
# `saltcorn` keeps working in fresh shells without further setup.
export NVM_DIR="$HOME/.nvm"
NVM_VERSION="v0.40.1"
if [ ! -s "$NVM_DIR/nvm.sh" ]; then
echo "==> nvm not found at $NVM_DIR -- installing $NVM_VERSION"
curl -fsSL "https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh" | bash
if [ ! -s "$NVM_DIR/nvm.sh" ]; then
echo "nvm install did not produce $NVM_DIR/nvm.sh"
exit 1
fi
fi
# nvm.sh references some unset variables on load; relax 'set -u' while sourcing.
set +u
# shellcheck source=/dev/null
. "$NVM_DIR/nvm.sh"
set -u
echo "==> Ensuring node 20 is installed and active"
nvm install 20
nvm use 20
NODE_MAJOR=$(node -p 'process.versions.node.split(".")[0]')
if [ "$NODE_MAJOR" -lt 18 ]; then
echo "node >= 18 required, found $(node --version)"
exit 1
fi
# Refuse to clobber an existing saltcorn subfolder, but allow $DEST itself to
# pre-exist (it might already contain dev-deploy/ or other user work).
if [ -e "$DEST/saltcorn" ]; then
echo "$DEST/saltcorn already exists; refusing to overwrite"
exit 1
fi
# --- clone + build ---
mkdir -p "$DEST"
DEST_ABS="$(cd "$DEST" && pwd)"
echo "==> Cloning $REPO_URL into $DEST_ABS/saltcorn"
git clone "$REPO_URL" "$DEST_ABS/saltcorn"
echo "==> npm install (resolves workspaces; takes several minutes)"
(cd "$DEST_ABS/saltcorn" && npm install)
echo "==> npm run tsc"
(cd "$DEST_ABS/saltcorn" && npm run tsc)
# --- .dev-state/ with generated session secret ---
DEV_DIR="$DEST_ABS/.dev-state"
mkdir -p "$DEV_DIR/files"
SECRET=$(node -e 'console.log(require("crypto").randomBytes(32).toString("hex"))')
cat > "$DEV_DIR/env.sh" <<EOF
#!/usr/bin/env bash
# Source this file before running saltcorn: source .dev-state/env.sh
# Keeps all dev state (DB + uploaded files) under .dev-state/ inside the
# project root. Upstream saltcorn lives in <project-root>/saltcorn/.
__SC_DEV_DIR="\$(cd "\$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
__SC_REPO_DIR="\$(dirname "\$__SC_DEV_DIR")"
export NVM_DIR="\$HOME/.nvm"
# shellcheck disable=SC1091
[ -s "\$NVM_DIR/nvm.sh" ] && . "\$NVM_DIR/nvm.sh"
export SQLITE_FILEPATH="\$__SC_DEV_DIR/saltcorn.sqlite"
export SALTCORN_FILE_STORE="\$__SC_DEV_DIR/files"
export SALTCORN_SESSION_SECRET="$SECRET"
# Put the in-tree CLI on PATH so \`saltcorn ...\` resolves to this checkout.
case ":\$PATH:" in
*":\$__SC_REPO_DIR/saltcorn/packages/saltcorn-cli/bin:"*) ;;
*) export PATH="\$__SC_REPO_DIR/saltcorn/packages/saltcorn-cli/bin:\$PATH" ;;
esac
unset __SC_DEV_DIR __SC_REPO_DIR
EOF
chmod +x "$DEV_DIR/env.sh"
# --- initialize schema and admin user ---
# shellcheck source=/dev/null
source "$DEV_DIR/env.sh"
echo "==> Initializing SQLite schema at $SQLITE_FILEPATH"
saltcorn reset-schema -f
echo "==> Creating admin user $ADMIN_EMAIL"
saltcorn create-user -a -e "$ADMIN_EMAIL" -p "$ADMIN_PASSWORD"
# --- startServer.sh ---
cat > "$DEST_ABS/startServer.sh" <<'EOF'
#!/usr/bin/env bash
set -e
cd "$(dirname "$0")"
source .dev-state/env.sh
# Pick up any local plugin source changes before booting the server.
# install-plugin copies ./dev-deploy into Saltcorn's
# plugins_folder/.../localversion/, so source edits go live on each restart.
# Failures here are non-fatal: the previously-installed version still loads.
saltcorn install-plugin -d ./dev-deploy 2>&1 | tail -2 || true
# Saltcorn's SQLite session store writes sessions.sqlite at process cwd
# (packages/server/routes/utils.js). Run from inside .dev-state/ so each
# instance gets its own sessions.sqlite alongside its saltcorn.sqlite.
cd .dev-state
exec saltcorn serve "$@"
EOF
chmod +x "$DEST_ABS/startServer.sh"
echo
echo "Done."
echo " cd $DEST_ABS && ./startServer.sh"
echo " -> http://localhost:3000/ (login: $ADMIN_EMAIL / $ADMIN_PASSWORD)"