| """ |
| Custom Hatchling build hook. |
| |
| Only runs when the environment variable ASTRBOT_BUILD_DASHBOARD=1 is set, |
| so that `uv sync` / editable installs are never affected. |
| |
| Usage: |
| ASTRBOT_BUILD_DASHBOARD=1 uv build |
| |
| When enabled, this hook: |
| 1. Runs `npm run build` inside the `dashboard/` directory. |
| 2. Copies the resulting `dashboard/dist/` tree into |
| `astrbot/dashboard/dist/` so the static assets are shipped |
| inside the Python wheel. |
| """ |
|
|
| import os |
| import shutil |
| import subprocess |
| import sys |
| from pathlib import Path |
|
|
| from hatchling.builders.hooks.plugin.interface import BuildHookInterface |
|
|
|
|
| class CustomBuildHook(BuildHookInterface): |
| PLUGIN_NAME = "custom" |
|
|
| def initialize(self, version: str, build_data: dict) -> None: |
| |
| |
| if os.environ.get("ASTRBOT_BUILD_DASHBOARD", "").strip() != "1": |
| return |
|
|
| root = Path(self.root) |
| dashboard_src = root / "dashboard" |
| dist_src = dashboard_src / "dist" |
| dist_target = root / "astrbot" / "dashboard" / "dist" |
|
|
| if not dashboard_src.exists(): |
| print( |
| "[hatch_build] 'dashboard/' directory not found β skipping dashboard build.", |
| file=sys.stderr, |
| ) |
| return |
|
|
| |
| if not (dashboard_src / "node_modules").exists(): |
| print("[hatch_build] Installing dashboard Node dependencies...") |
| subprocess.run( |
| ["npm", "install"], |
| cwd=dashboard_src, |
| check=True, |
| ) |
|
|
| |
| print("[hatch_build] Building Vue dashboard (npm run build)...") |
| subprocess.run( |
| ["npm", "run", "build"], |
| cwd=dashboard_src, |
| check=True, |
| ) |
|
|
| if not dist_src.exists(): |
| print( |
| "[hatch_build] dashboard/dist not found after build β skipping copy.", |
| file=sys.stderr, |
| ) |
| return |
|
|
| |
| if dist_target.exists(): |
| shutil.rmtree(dist_target) |
| shutil.copytree(dist_src, dist_target) |
| print(f"[hatch_build] Dashboard dist copied β {dist_target.relative_to(root)}") |
|
|