Files
magnus919_agent-skills/vite/scripts/vite-doctor
Magnus HedemarkGitHubfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
a8b8ad7dbe fix: address routing depth scrutiny findings (#448)
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-09-01 20:30:07 -04:00

135 lines
4.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""Read-only, bounded diagnostics for a Vite project."""
from __future__ import annotations
import argparse
import json
import os
import shutil
import subprocess
import sys
from pathlib import Path
LOCKFILES = {
"package-lock.json": "npm",
"pnpm-lock.yaml": "pnpm",
"yarn.lock": "yarn",
"bun.lock": "bun",
"bun.lockb": "bun",
}
MANAGERS = {
"npm": ["npm", "--version"],
"pnpm": ["pnpm", "--version"],
"yarn": ["yarn", "--version"],
"bun": ["bun", "--version"],
}
def bounded_version(command: list[str], timeout: float) -> dict[str, object]:
executable = shutil.which(command[0])
result: dict[str, object] = {"available": executable is not None}
if executable is None:
return result
try:
completed = subprocess.run(
command, capture_output=True, text=True, timeout=timeout, check=False
)
except subprocess.TimeoutExpired:
result["error"] = "timeout"
return result
value = (completed.stdout or completed.stderr).strip().splitlines()
if value:
result["version"] = value[0][:200]
result["exit_code"] = completed.returncode
return result
def resolved_vite(project: Path, timeout: float) -> dict[str, object]:
"""Report local package metadata and local .bin behavior without installing."""
package_path = project / "node_modules" / "vite" / "package.json"
package: dict[str, object] = {"available": package_path.is_file()}
if package_path.is_file():
try:
data = json.loads(package_path.read_text(encoding="utf-8"))
if isinstance(data, dict):
version = data.get("version")
if isinstance(version, str) and version:
package["version"] = version
package["path"] = str(package_path)
except (OSError, json.JSONDecodeError) as exc:
package["error"] = f"cannot read installed package: {exc}"
binary_path = project / "node_modules" / ".bin" / "vite"
binary: dict[str, object] = {"available": binary_path.is_file()}
if binary_path.is_file():
binary["path"] = str(binary_path)
binary.update(bounded_version([str(binary_path), "--version"], timeout))
return {"package": package, "executable": binary}
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--project", default=".", help="Vite project directory")
parser.add_argument("--timeout", type=float, default=3.0, help="Version probe timeout")
parser.add_argument("--json", action="store_true", help="Emit JSON (default)")
args = parser.parse_args()
if args.timeout <= 0:
parser.error("--timeout must be positive")
project = Path(args.project).expanduser().resolve()
if not project.is_dir():
print(json.dumps({"error": f"project is not a directory: {project}"}), file=sys.stderr)
return 1
package_file = project / "package.json"
package_data: dict[str, object] = {}
errors: list[str] = []
if package_file.is_file():
try:
loaded = json.loads(package_file.read_text(encoding="utf-8"))
if isinstance(loaded, dict):
package_data = loaded
else:
errors.append("package.json is not an object")
except (OSError, json.JSONDecodeError) as exc:
errors.append(f"cannot read package.json: {exc}")
else:
errors.append("package.json not found")
lockfiles = [name for name in LOCKFILES if (project / name).is_file()]
manager_name = LOCKFILES[lockfiles[0]] if lockfiles else None
configs = sorted(
path.name for path in project.iterdir()
if path.is_file() and path.name.startswith("vite.config")
)
dependencies: dict[str, object] = {}
for section in ("dependencies", "devDependencies", "optionalDependencies"):
values = package_data.get(section)
if isinstance(values, dict) and "vite" in values:
dependencies[section] = values["vite"]
payload = {
"project": str(project),
"package_json": package_file.is_file(),
"package_manager": {
"name": manager_name,
"lockfiles": lockfiles,
"version": bounded_version(MANAGERS[manager_name], args.timeout)
if manager_name else None,
},
"node": bounded_version(["node", "--version"], args.timeout),
"vite_dependency": dependencies,
"vite_resolved": resolved_vite(project, args.timeout),
"config_files": configs,
"env_file_names": sorted(
path.name for path in project.iterdir()
if path.is_file() and path.name.startswith(".env")
),
"errors": errors,
}
print(json.dumps(payload, indent=2, sort_keys=True))
return 1 if errors else 0
if __name__ == "__main__":
raise SystemExit(main())