#!/usr/bin/env bash
# Las corridas del apunte que usan el registro de npm. Cada comando se imprime
# con $, como en una terminal, y la salida es la de hoy: puede no coincidir con
# la del apunte, porque el registro cambia.
set -u
unset MAKELEVEL MAKEFLAGS MFLAGS
HERE="$(cd "$(dirname "$0")" && pwd)"
KALLPA="${KALLPA:-$HERE/../../kallpa}"
TOOLS=(typescript@6.0.3 @types/node@26.6.6 eslint@10.14.0 @eslint/js@10.0.1 typescript-eslint@8.72.1 fast-check@4.10.2)
RUNNER_PATH_BASE=/usr/local/bin:/usr/bin:/bin

# Con una tubería, el código de salida sería el del último comando: no se muestra.
show() {
  echo; echo "\$ $*"
  bash -c "$*" 2>&1
  local code=$?
  case "$*" in *\|*) ;; *) echo "[código de salida: $code]" ;; esac
}

# El error de uso de npm trae toda la ayuda de la orden: se corta antes de ella.
short() { echo; echo "\$ $*"; bash -c "$*" 2>&1 | sed '/^npm error Clean install a project/,$d'; echo "[código de salida: ${PIPESTATUS[0]}]"; }

quiet_install() {
  local dir="$HERE/build/$1"
  rm -rf "$dir"
  mkdir -p "$HERE/build"
  cp -r "$KALLPA" "$dir"
  rm -f "$dir"/data/*.db "$dir"/data/*.db-*
  cd "$dir" || exit 2
  npm install --no-audit --no-fund --save-dev --save-exact "${TOOLS[@]}" >/dev/null 2>&1
}

case "${1:-}" in
  arbol)
    rm -rf "$HERE/build/arbol"; mkdir -p "$HERE/build"; cp -r "$KALLPA" "$HERE/build/arbol"
    cd "$HERE/build/arbol" || exit 2
    show "npm install --save-dev --save-exact ${TOOLS[*]}"
    show "npm ls"
    show "npm ls --all --parseable | wc -l"
    show "npm ls minimatch"
    show "npm explain minimatch | head -5"
    show "npm explain debug | head -4"
    show "wc -l package-lock.json"
    show "du -sh node_modules"
    ;;
  runner)
    quiet_install runner
    show "rm -rf node_modules && npm ci --no-fund"
    show "env PATH=\"\$PWD/node_modules/.bin:$RUNNER_PATH_BASE\" make check | tail -9"
    show "env PATH=$RUNNER_PATH_BASE make check"
    ;;
  lockfile)
    quiet_install lockfile
    cp package.json /tmp/w12-package.json; cp package-lock.json /tmp/w12-lock.json
    echo "--- alguien edita package.json y se olvida del lockfile"
    sed -i 's/"fast-check": "4.10.2"/"fast-check": "4.10.1"/' package.json
    short "npm ci"
    cp /tmp/w12-package.json package.json
    echo; echo "--- no hay lockfile"
    rm package-lock.json
    short "npm ci"
    cp /tmp/w12-lock.json package-lock.json
    echo; echo "--- el hash de ms en el lockfile no es el del paquete que llega"
    node -e "const fs=require('fs');const l=JSON.parse(fs.readFileSync('package-lock.json'));l.packages['node_modules/ms'].integrity=l.packages['node_modules/fast-check'].integrity;fs.writeFileSync('package-lock.json',JSON.stringify(l,null,2))"
    rm -rf node_modules; npm cache clean --force >/dev/null 2>&1
    show "npm ci 2>&1 | grep -E 'code EINTEGRITY|integrity checksum' | cut -c1-110"
    cp /tmp/w12-lock.json package-lock.json
    rm -f /tmp/w12-package.json /tmp/w12-lock.json
    ;;
  auditar)
    quiet_install auditar
    show "npm audit | grep -v -E 'Depends on|node_modules/'"
    show "npm audit --omit=dev"
    show "npm audit --audit-level=high > /dev/null"
    show "npm audit --audit-level=moderate > /dev/null"
    show "npm audit --json | jq -c '.metadata.vulnerabilities'"
    show "npm audit --json | jq -r '.vulnerabilities | to_entries[] | select(.value.isDirect) | .key'"
    show "npm outdated"
    show "npm audit signatures"
    ;;
  fuerza)
    quiet_install fuerza
    show "npm audit fix --force --dry-run 2>&1 | grep -E 'Updating'"
    show "npm audit fix --force --no-fund > /dev/null 2>&1"
    show "npm pkg get devDependencies"
    show "npm audit 2>&1 | tail -7 | head -1"
    show "env PATH=\"\$PWD/node_modules/.bin:$RUNNER_PATH_BASE\" make check"
    ;;
  peer)
    quiet_install peer
    show "npm view typescript-eslint@8.72.1 peerDependencies"
    show "npm install --no-audit --no-fund --save-dev --save-exact typescript@7.0.2 2>&1 | cut -c1-90 | grep -v 'overriding peer' | sed -n 1,12p"
    show "env PATH=\"\$PWD/node_modules/.bin:$RUNNER_PATH_BASE\" make typecheck"
    show "env PATH=\"\$PWD/node_modules/.bin:$RUNNER_PATH_BASE\" make lint 2>&1 | head -3 | cut -c1-90"
    show "rm -rf node_modules && npm ci 2>&1 | cut -c1-90 | sed -n 1,5p"
    ;;
  rangos)
    rm -rf "$HERE/build/rangos"; mkdir -p "$HERE/build/rangos/antes" "$HERE/build/rangos/hoy"
    for dir in antes hoy; do
      echo '{ "name": "rangos", "private": true, "devDependencies": { "eslint": "^10.0.0" } }' > "$HERE/build/rangos/$dir/package.json"
    done
    cd "$HERE/build/rangos/antes" || exit 2
    show "npm install --no-audit --no-fund --before=2026-03-01"
    show "npm ls eslint --depth=0"
    cd "$HERE/build/rangos/hoy" || exit 2
    show "npm install --no-audit --no-fund"
    show "npm ls eslint --depth=0"
    show "npm view '@eslint/config-array@^0.23.5' version | tail -1"
    ;;
  falta)
    quiet_install falta
    show "npm uninstall --no-audit --no-fund @eslint/js"
    show "make check | tail -8"
    ;;
  sbom)
    quiet_install sbom
    show "npm sbom --sbom-format cyclonedx | jq -r '.bomFormat, .specVersion, (.components | length)'"
    show "npm sbom --sbom-format cyclonedx --omit=dev | jq '.components | length'"
    show "npm sbom --sbom-format cyclonedx | jq -c '.components[] | select(.name == \"minimatch\") | {name, version, purl, licenses}'"
    ;;
  paquetes)
    show "npm view request name version license repository.url time.modified deprecated"
    show "npm view fast-check name version license repository.url time.modified dependencies"
    show "npm view kallpa-slots-helper name version license repository.url time.modified | cut -c1-90"
    show "npm view debug@4.4.2 version 2>&1 | head -2"
    ;;
  *)
    echo "Uso: registro.sh arbol|runner|falta|lockfile|auditar|fuerza|peer|rangos|sbom|paquetes" >&2
    exit 2
    ;;
esac
