mirror of
https://github.com/magnus919/agent-skills.git
synced 2026-09-12 12:06:29 +03:00
a8b8ad7dbe
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
135 lines
4.8 KiB
Python
Executable File
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())
|