Ready
This commit is contained in:
commit
0f45a51f1d
20 files changed
+3532
No files matched your search
@@ -0,0 +1,84 @@
|
||||
import argparse
|
||||
import hashlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
BACKEND = ROOT / "backend"
|
||||
FRONTEND = ROOT / "frontend"
|
||||
VENV = ROOT / ".venv"
|
||||
|
||||
|
||||
def install_dependencies(
|
||||
inputs: tuple[Path, ...], stamp: Path, command: list[str], cwd: Path
|
||||
) -> None:
|
||||
fingerprint = hashlib.sha256()
|
||||
for path in inputs:
|
||||
fingerprint.update(hashlib.sha256(path.read_bytes()).digest())
|
||||
current = fingerprint.hexdigest()
|
||||
if stamp.is_file() and stamp.read_text(encoding="ascii") == current:
|
||||
return
|
||||
|
||||
stamp.unlink(missing_ok=True)
|
||||
subprocess.run(command, cwd=cwd, check=True)
|
||||
stamp.write_text(current, encoding="ascii")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Локальный запуск AI-заметок.")
|
||||
parser.add_argument("--port", type=int, default=8000, help="Порт приложения (по умолчанию 8000).")
|
||||
args = parser.parse_args()
|
||||
if not 1 <= args.port <= 65535:
|
||||
parser.error("Порт должен быть от 1 до 65535.")
|
||||
if sys.version_info < (3, 11):
|
||||
parser.exit(1, "Установите Python 3.11 или новее.\n")
|
||||
|
||||
npm = shutil.which("npm.cmd" if os.name == "nt" else "npm")
|
||||
if not npm or not shutil.which("node"):
|
||||
parser.exit(1, "Установите Node.js с npm и заново откройте терминал.\n")
|
||||
|
||||
env_file = ROOT / ".env"
|
||||
if not env_file.exists():
|
||||
shutil.copyfile(ROOT / ".env.example", env_file)
|
||||
print("Создан .env. Для генерации добавьте ключ Groq в этот файл.", flush=True)
|
||||
|
||||
python = VENV / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
|
||||
if not python.is_file():
|
||||
subprocess.run([sys.executable, "-m", "venv", str(VENV)], check=True)
|
||||
|
||||
install_dependencies(
|
||||
(BACKEND / "requirements.txt",),
|
||||
VENV / ".notes-dependencies",
|
||||
[str(python), "-m", "pip", "install", "-r", "requirements.txt"],
|
||||
BACKEND,
|
||||
)
|
||||
install_dependencies(
|
||||
(FRONTEND / "package.json", FRONTEND / "package-lock.json"),
|
||||
FRONTEND / "node_modules" / ".notes-dependencies",
|
||||
[npm, "ci"],
|
||||
FRONTEND,
|
||||
)
|
||||
subprocess.run([npm, "run", "build"], cwd=FRONTEND, check=True)
|
||||
|
||||
return subprocess.call(
|
||||
[
|
||||
str(python), "-m", "uvicorn", "app.main:app",
|
||||
"--env-file", str(env_file), "--host", "127.0.0.1", "--port", str(args.port),
|
||||
],
|
||||
cwd=BACKEND,
|
||||
env={**os.environ, "NOTES_WEB_DIST": str(FRONTEND / "dist")},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
raise SystemExit(main())
|
||||
except subprocess.CalledProcessError as error:
|
||||
print("Запуск остановлен. Причина указана выше.", file=sys.stderr)
|
||||
raise SystemExit(error.returncode) from None
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit(130) from None
|
||||
Reference in new issue
Block a user