lotto lab API 정리

- API 스펙 정리 문서 업로드
 - 스펙 다운로드 기능 추가

나스 배포 오류 수정
This commit is contained in:
2026-01-25 17:05:16 +09:00
parent 846b353a37
commit c44bcb4a0f
5 changed files with 99 additions and 2 deletions

View File

@@ -7,7 +7,7 @@
"dev": "vite", "dev": "vite",
"clean": "rimraf dist", "clean": "rimraf dist",
"build": "npm run clean && vite build", "build": "npm run clean && vite build",
"deploy:nas": "node -e 'const isWin = process.platform === \"win32\"; const src = \"dist\"; const dstWin = \"Z:\\\\docker\\\\webpage\\\\frontend\\\\\"; const dstMac = \"/Volumes/gahusb.synology.me/docker/webpage/frontend/\"; const dst = isWin ? dstWin : dstMac; const fs = require(\"fs\"); if (!fs.existsSync(src)) { console.error(\"dist not found. Run build first.\"); process.exit(1); } if (!fs.existsSync(dst)) { console.error(\"NAS path not found. Check mount: \" + dst); process.exit(1); } if (isWin) { const cmd = \"powershell -NoProfile -ExecutionPolicy Bypass -Command \\\"$ErrorActionPreference=\\\"Stop\\\"; $src=\\\"dist\\\"; $dst=\\\"Z:\\\\docker\\\\webpage\\\\frontend\\\\\\\"; if(!(Test-Path $src)){ throw \\\"dist not found. Run build first.\\\" }; if(!(Test-Path $dst)){ throw \\\"NAS drive not found. Check Z: mapping.\\\" }; robocopy $src $dst /MIR /R:1 /W:1 /E /NFL /NDL /NP; if($LASTEXITCODE -ge 8){ exit $LASTEXITCODE }\\\"\"; require(\"child_process\").execSync(cmd); } else { require(\"child_process\").execSync(\"rsync -av --delete --delete-delay --inplace dist/ \" + dst); }'", "deploy:nas": "node scripts/deploy-nas.cjs",
"release:nas": "npm run build && npm run deploy:nas", "release:nas": "npm run build && npm run deploy:nas",
"lint": "eslint .", "lint": "eslint .",
"preview": "vite preview" "preview": "vite preview"

63
public/lotto-api.md Normal file
View File

@@ -0,0 +1,63 @@
# Lotto API 스펙 (프론트 참고)
## 추천 1개 생성
요청:
GET /api/lotto/recommend?recent_window=200&recent_weight=2.0&avoid_recent_k=5&sum_min=120&sum_max=180&max_overlap_latest=1
응답 핵심:
{
"id": 123,
"saved": true,
"deduped": false,
"numbers": [1,2,3,4,5,6],
"based_on_latest_draw": 1145,
"explain": {...},
"metrics": {...},
"recent_overlap": {...},
"params": {...}
}
## 히스토리 목록 (페이지/필터/검색)
기본: GET /api/history?limit=30&offset=0
즐겨찾기만: GET /api/history?favorite=true
태그 필터: GET /api/history?tag=jeju
메모 검색: GET /api/history?q=맛집
정렬: GET /api/history?sort=favorite_desc
응답:
{
"items": [
{
"id": 123,
"created_at": "...",
"numbers": [...],
"params": {...},
"based_on_draw": 1145,
"favorite": false,
"note": null,
"tags": [],
"metrics": {...},
"recent_overlap": {...}
}
],
"limit": 30,
"offset": 0,
"filters": {...}
}
## 히스토리 수정 (즐겨찾기/메모/태그)
요청:
PATCH /api/history/{id}
{
"favorite": true,
"note": "이번주는 이 조합",
"tags": ["jeju","safe"]
}

27
scripts/deploy-nas.cjs Normal file
View File

@@ -0,0 +1,27 @@
const { execSync } = require("child_process");
const fs = require("fs");
const isWin = process.platform === "win32";
const src = "dist";
const dstWin = "Z:\\docker\\webpage\\frontend\\";
const dstMac = "/Volumes/gahusb.synology.me/docker/webpage/frontend/";
const dst = isWin ? dstWin : dstMac;
if (!fs.existsSync(src)) {
console.error("dist not found. Run build first.");
process.exit(1);
}
if (!fs.existsSync(dst)) {
console.error("NAS path not found. Check mount: " + dst);
process.exit(1);
}
if (isWin) {
const cmd =
'powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference=\\"Stop\\"; $src=\\"dist\\"; $dst=\\"Z:\\\\docker\\\\webpage\\\\frontend\\\\\\"; if(!(Test-Path $src)){ throw \\"dist not found. Run build first.\\" }; if(!(Test-Path $dst)){ throw \\"NAS drive not found. Check Z: mapping.\\" }; $log = Join-Path (Get-Location) \\"robocopy.log\\"; robocopy $src $dst /MIR /R:1 /W:1 /E /NFL /NDL /NP /V /TEE /LOG:$log; $rc = $LASTEXITCODE; if($rc -ge 8){ Write-Host \\"robocopy failed with code $rc. See $log\\"; exit $rc } else { exit 0 }"';
execSync(cmd, { stdio: "inherit" });
} else {
execSync(`rsync -av --delete --delete-delay --inplace ${src}/ ${dst}`, {
stdio: "inherit",
});
}

View File

@@ -360,7 +360,10 @@ export default function Functions() {
</section> </section>
<footer className="lotto-foot"> <footer className="lotto-foot">
backend: FastAPI / nginx proxy / DB: sqlite backend: FastAPI / nginx proxy / DB: sqlite {' '}
<a className="lotto-foot__link" href="/lotto-api.md" download>
API 스펙 다운로드
</a>
</footer> </footer>
</div> </div>
); );

View File

@@ -322,6 +322,10 @@
font-size: 12px; font-size: 12px;
} }
.lotto-foot__link {
color: var(--accent);
}
.button.danger { .button.danger {
border-color: rgba(247, 116, 125, 0.5); border-color: rgba(247, 116, 125, 0.5);
color: #fbc4c8; color: #fbc4c8;