# Validate a monorepo workspace config: the JSON parses, and every workspace
# glob/path it declares resolves to a real directory on disk. Pure python3
# stdlib (json module, no external CLI/deps) — there is no off-the-shelf tool
# for "does this workspace glob actually resolve", so this check is 100%
# custom parsing, honestly labeled as such below.
# lint_workspace_config.sh [config-file]
# With no argument, auto-detects by searching the CWD in this order and using
# whichever is found first: package.json (workspaces field), turbo.json,
# scripts/lint_workspace_config.sh ./package.json
# cd my-monorepo && /path/to/lint_workspace_config.sh # auto-detect
warn() { printf '⚠️ %s\n' "$1"; }
error() { printf '❌ %s\n' "$1"; fail=1; }
ok() { printf '✅ %s\n' "$1"; }
if [[ -z "$CONFIG" ]]; then
echo "== auto-detecting workspace config in $(pwd) =="
if [[ -f "package.json" ]]; then
elif [[ -f "turbo.json" ]]; then
elif [[ -f "nx.json" ]]; then
echo "Usage: $0 [config-file]" >&2
echo "No package.json, turbo.json, or nx.json found in $(pwd)." >&2
ok "auto-detected $CONFIG"
if [[ ! -f "$CONFIG" ]]; then
echo "Usage: $0 [config-file]" >&2
echo "Config file not found: $CONFIG" >&2
echo "== JSON validity + workspace path resolution (python3 stdlib json — no external CLI exists for this) =="
py_out=$(python3 "$(dirname "$0")/lint_workspace_config.py" "$CONFIG")
while IFS= read -r line; do
OK::*) ok "${line#OK::}" ;;
ERROR::*) error "${line#ERROR::}" ;;
*) [[ -n "$line" ]] && echo "$line" ;;
if [[ "$py_status" -ne 0 ]]; then
if [[ "$fail" -eq 0 ]]; then
echo "All checks passed."
echo "One or more checks failed — see ❌ lines above."