This commit is contained in:
fengchuanhn@gmail.com
2026-05-17 12:54:13 +08:00
parent 1b8ca10ec9
commit 3db327d93b
38 changed files with 2820 additions and 14 deletions

View File

@@ -0,0 +1,47 @@
"""Node.js 流水线脚本:按文件名下发源码,供桌面端拉取后在 Node 子进程中执行。"""
import re
from pathlib import Path
from fastapi import APIRouter
from app.schemas.common import ApiResponse
router = APIRouter(prefix="/nodejs-scripts", tags=["nodejs"])
# pythonbackend/scripts/nodejs/*.js
_SCRIPTS_DIR = Path(__file__).resolve().parents[3] / "scripts" / "nodejs"
_SAFE_NAME = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9._-]*\.js$")
def _validate_name(name: str) -> str | None:
if not name or not _SAFE_NAME.fullmatch(name.strip()):
return None
return name.strip()
@router.get("", response_model=ApiResponse[dict])
async def get_nodejs_script(name: str) -> ApiResponse[dict]:
safe = _validate_name(name)
if not safe:
return ApiResponse(ok=False, message="无效的脚本名称", data=None)
path = _SCRIPTS_DIR / safe
try:
base_resolved = _SCRIPTS_DIR.resolve()
resolved = path.resolve()
resolved.relative_to(base_resolved)
except (OSError, ValueError):
return ApiResponse(ok=False, message="无效的脚本路径", data=None)
if not path.is_file():
return ApiResponse(ok=False, message=f"脚本不存在: {safe}", data=None)
source = path.read_text(encoding="utf-8")
return ApiResponse(ok=True, message="", data={"source": source})
@router.get("/list", response_model=ApiResponse[dict])
async def list_nodejs_scripts() -> ApiResponse[dict]:
if not _SCRIPTS_DIR.is_dir():
return ApiResponse(ok=True, message="", data={"names": []})
names = sorted(p.name for p in _SCRIPTS_DIR.glob("*.js") if p.is_file())
return ApiResponse(ok=True, message="", data={"names": names})