#!/usr/bin/env bash # Lance en mode développement le backend Node (port 8080) et le frontend Angular # (port 4200), qui lit les specs directement dans ../docs/specs-pre-projet. # À utiliser hors Docker, pour le développement / la préparation d'atelier en local. # # Usage : ./run-dev.sh # Arrêt : Ctrl+C (les deux processus sont arrêtés ensemble). set -uo pipefail RACINE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # --- Lecture facultative du .env (comptes + secret JWT) --------------------- # On lit JWT_SECRET et AUTH_USERS depuis .env s'ils existent, sans l'exporter en bloc # (le .env peut contenir des commentaires). Variables déjà présentes dans # l'environnement prioritaires. lire_env() { local cle="$1" [[ -f "$RACINE/.env" ]] || return 0 grep -E "^${cle}=" "$RACINE/.env" | head -n1 | cut -d= -f2- || true } # --- Secret JWT ------------------------------------------------------------- # Priorité : variable d'environnement > .env > secret de dev aléatoire. # Un placeholder copié tel quel depuis .env.example est ignoré. if [[ -z "${JWT_SECRET:-}" ]]; then JWT_FROM_ENV="$(lire_env JWT_SECRET)" PLACEHOLDER="change-me-generer-une-longue-chaine-aleatoire-de-32-caracteres-min" if [[ -n "$JWT_FROM_ENV" && "$JWT_FROM_ENV" != "$PLACEHOLDER" ]]; then export JWT_SECRET="$JWT_FROM_ENV" echo "→ Secret JWT chargé depuis .env." else if command -v openssl >/dev/null 2>&1; then export JWT_SECRET="$(openssl rand -base64 48)" else export JWT_SECRET="$(head -c 48 /dev/urandom | base64)" fi echo "⚠ Aucun secret JWT exploitable dans .env : secret de dev aléatoire généré" echo " (les sessions sont invalidées à chaque relance du script)." fi fi # --- Compte administrateur -------------------------------------------------- # Priorité : variable d'environnement > .env > défaut dev (admin/admin). if [[ -z "${ADMIN_USER:-}" ]]; then ADMIN_USER_ENV="$(lire_env ADMIN_USER)" export ADMIN_USER="${ADMIN_USER_ENV:-admin}" fi if [[ -z "${ADMIN_PASSWORD:-}" ]]; then ADMIN_PWD_ENV="$(lire_env ADMIN_PASSWORD)" export ADMIN_PASSWORD="${ADMIN_PWD_ENV:-admin}" fi echo "→ Administrateur : ${ADMIN_USER}." # Amorçage des comptes initiaux (facultatif, repris du .env). if [[ -z "${SEED_USERS:-}" ]]; then SEED_ENV="$(lire_env SEED_USERS)" [[ -n "$SEED_ENV" ]] && export SEED_USERS="$SEED_ENV" fi # Dossier des specs lues en direct (chemin absolu pour être indépendant du cwd). export SPECS_DIR="${SPECS_DIR:-$RACINE/../docs/specs-pre-projet}" # Dossier d'écriture des annotations en dev local. export ANNOTATIONS_DIR="${ANNOTATIONS_DIR:-$RACINE/annotations}" # Dossier d'écriture des comptes gérés en dev local. export USERS_DIR="${USERS_DIR:-$RACINE/users}" export PORT="${PORT:-8080}" # --- Backend (Node) --------------------------------------------------------- if [[ ! -d "$RACINE/backend/node_modules" ]]; then echo "→ Installation des dépendances backend (npm install)…" ( cd "$RACINE/backend" && npm install --no-audit --no-fund ) fi echo "→ Démarrage du backend sur http://localhost:${PORT} (specs : $SPECS_DIR)" ( cd "$RACINE/backend" && node src/server.js ) & PID_BACK=$! # --- Frontend (Angular) ----------------------------------------------------- if [[ ! -d "$RACINE/frontend/node_modules" ]]; then echo "→ Installation des dépendances frontend (npm install)…" ( cd "$RACINE/frontend" && npm install --no-audit --no-fund ) fi echo "→ Nettoyage du cache Angular (.angular/cache)" rm -rf "$RACINE/frontend/.angular/cache" echo "→ Démarrage du frontend sur http://localhost:4200 (première compilation : patiente…)" ( cd "$RACINE/frontend" && npm start ) & PID_FRONT=$! # --- Arrêt propre des deux processus ---------------------------------------- cleanup() { echo "" echo "→ Arrêt…" kill "$PID_BACK" "$PID_FRONT" 2>/dev/null || true } trap cleanup EXIT INT TERM # --- Attente active : ng serve prêt à répondre en HTTP 200 ------------------ attendre_frontend() { local url="http://localhost:4200/" local max=120 # secondes local t=0 printf "→ Compilation du frontend" while [ "$t" -lt "$max" ]; do if ! kill -0 "$PID_FRONT" 2>/dev/null; then echo "" echo "✗ Le frontend s'est arrêté avant d'être prêt (voir les logs ci-dessus)." return 1 fi local code code=$(curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo 000) if [ "$code" = "200" ]; then echo " prêt." return 0 fi printf "." sleep 2 t=$((t + 2)) done echo "" echo "✗ Le frontend n'a pas répondu 200 au bout de ${max}s. Vérifie les logs ng serve." return 1 } if attendre_frontend; then echo "" echo "======================================================================" echo " Site des specs SatPRO prêt." echo " Backend : http://localhost:${PORT}/api" echo " Frontend : http://localhost:4200 ← ouvre cette URL maintenant" echo "" echo " Admin : ${ADMIN_USER} (gère les accès via « Gestion des accès »)." echo " Autres comptes : amorcés au 1er démarrage puis gérés dans l'application." echo " Les specs sont lues en direct dans : $SPECS_DIR" echo " Comptes gérés : $USERS_DIR/users.json" echo " Après édition d'un .md, clique « Rafraîchir » dans la page." echo "======================================================================" echo "" fi wait