mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-02 19:32:43 +00:00
90 lines
2.9 KiB
Bash
90 lines
2.9 KiB
Bash
#!/usr/bin/env bash
|
||||
|
|
# fzf package.json script runner with auto-detected package manager.
|
|||
|
|
|
|||
|
|
# ── Locate nearest package.json (walk up) ──────────────────────────
|
|||
|
|
dir=$PWD
|
|||
|
|
pkg=""
|
|||
|
|
while :; do
|
|||
|
|
if [ -f "$dir/package.json" ]; then
|
|||
|
|
pkg="$dir/package.json"
|
|||
|
|
break
|
|||
|
|
fi
|
|||
|
|
[ "$dir" = / ] && break
|
|||
|
|
dir=$(dirname "$dir")
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
if [ -z "$pkg" ]; then
|
|||
|
|
echo "pj: no package.json found in this tree" >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
root=$(dirname "$pkg")
|
|||
|
|
|
|||
|
|
# ── Detect package manager ─────────────────────────────────────────
|
|||
|
|
# Priority: packageManager field (corepack) → lockfiles (walking up
|
|||
|
|
# past $root to catch monorepo-root locks) → npm fallback
|
|||
|
|
pm=$(jq -r '.packageManager // empty' "$pkg")
|
|||
|
|
pm=${pm%%@*}
|
|||
|
|
|
|||
|
|
if [ -z "$pm" ]; then
|
|||
|
|
d=$root
|
|||
|
|
while [ -z "$pm" ]; do
|
|||
|
|
if [ -f "$d/bun.lockb" ] || [ -f "$d/bun.lock" ]; then
|
|||
|
|
pm=bun
|
|||
|
|
elif [ -f "$d/pnpm-lock.yaml" ]; then
|
|||
|
|
pm=pnpm
|
|||
|
|
elif [ -f "$d/yarn.lock" ]; then
|
|||
|
|
pm=yarn
|
|||
|
|
elif [ -f "$d/package-lock.json" ]; then
|
|||
|
|
pm=npm
|
|||
|
|
fi
|
|||
|
|
[ "$d" = / ] && break
|
|||
|
|
d=$(dirname "$d")
|
|||
|
|
done
|
|||
|
|
[ -n "$pm" ] || pm=npm
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# ── Pick a script ──────────────────────────────────────────────────
|
|||
|
|
script=$(jq -r '.scripts // {} | keys[]' "$pkg" | fzf \
|
|||
|
|
--prompt="$pm run ❯ " \
|
|||
|
|
--header="$root" \
|
|||
|
|
--height=40% --layout=reverse --border \
|
|||
|
|
--preview="jq -r --arg s {} '.scripts[\$s]' \"$pkg\"" \
|
|||
|
|
--preview-window=up:2:wrap)
|
|||
|
|
|
|||
|
|
[ -n "$script" ] || exit 0
|
|||
|
|
|
|||
|
|
# ── Run (npm needs `--` to forward extra args) ────────────────────
|
|||
|
|
extra=("$@")
|
|||
|
|
if [ "$pm" = npm ] && [ $# -gt 0 ]; then
|
|||
|
|
extra=(-- "$@")
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Wrap long-running server scripts in openlogs (live log tail for agents).
|
|||
|
|
# Matches dev/start/serve and namespaced variants like dev:web, start:api.
|
|||
|
|
wrapper=""
|
|||
|
|
if [[ $script =~ ^(dev|start|serve|watch)(:.*)?$ ]]; then
|
|||
|
|
# Resolve the binary: PATH → mise resolution → mise installs glob
|
|||
|
|
ol=$(command -v openlogs || true)
|
|||
|
|
if [ -z "$ol" ] && command -v mise >/dev/null 2>&1; then
|
|||
|
|
ol=$(mise which openlogs 2>/dev/null || true)
|
|||
|
|
fi
|
|||
|
|
if [ -z "$ol" ]; then
|
|||
|
|
for cand in "$HOME"/.local/share/mise/installs/node/*/bin/openlogs; do
|
|||
|
|
[ -x "$cand" ] && { ol=$cand; break; }
|
|||
|
|
done
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ -n "$ol" ] && [ -x "$ol" ]; then
|
|||
|
|
wrapper=$ol
|
|||
|
|
else
|
|||
|
|
echo "pj: openlogs not found, running unwrapped" >&2
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ -n "$wrapper" ]; then
|
|||
|
|
echo "→ $wrapper $pm run $script $*" >&2
|
|||
|
|
exec "$wrapper" "$pm" run "$script" "${extra[@]}"
|
|||
|
|
else
|
|||
|
|
echo "→ $pm run $script $*" >&2
|
|||
|
|
exec "$pm" run "$script" "${extra[@]}"
|
|||
|
|
fi
|