wing-ops/backend/src/rescue/rescueRouter.ts
htlee ff085252b0 feat(phase4): Board/HNS/Prediction/Aerial/Rescue Mock → API 전환
- Board: 매뉴얼 CRUD + 첨부파일 API (012_board_ext.sql)
- HNS: 분석 CRUD 5개 API (013_hns_analysis.sql)
- Prediction: 분석/역추적/오일펜스 7개 API (014_prediction.sql)
- Aerial: 미디어/CCTV/위성 6개 API + PostGIS (015_aerial.sql)
- Rescue: 구난 작전/시나리오 3개 API + JSONB (016_rescue.sql)
- backtrackMockData.ts 삭제

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 01:17:10 +09:00

67 lines
2.5 KiB
TypeScript

import express from 'express';
import { listOps, getOps, listScenarios } from './rescueService.js';
import { isValidNumber } from '../middleware/security.js';
import { requireAuth, requirePermission } from '../auth/authMiddleware.js';
const router = express.Router();
// ============================================================
// GET /api/rescue/ops — 구조 작전 목록
// ============================================================
router.get('/ops', requireAuth, requirePermission('rescue', 'READ'), async (req, res) => {
try {
const { sttsCd, acdntTpCd, search } = req.query;
const items = await listOps({
sttsCd: sttsCd as string | undefined,
acdntTpCd: acdntTpCd as string | undefined,
search: search as string | undefined,
});
res.json(items);
} catch (err) {
console.error('[rescue] 구조 작전 목록 오류:', err);
res.status(500).json({ error: '구조 작전 목록 조회 실패' });
}
});
// ============================================================
// GET /api/rescue/ops/:sn — 구조 작전 단건 상세
// ============================================================
router.get('/ops/:sn', requireAuth, requirePermission('rescue', 'READ'), async (req, res) => {
try {
const sn = parseInt(req.params.sn as string, 10);
if (!isValidNumber(sn, 1, 999999)) {
res.status(400).json({ error: '유효하지 않은 구조 작전 번호' });
return;
}
const item = await getOps(sn);
if (!item) {
res.status(404).json({ error: '구조 작전을 찾을 수 없습니다.' });
return;
}
res.json(item);
} catch (err) {
console.error('[rescue] 구조 작전 상세 오류:', err);
res.status(500).json({ error: '구조 작전 상세 조회 실패' });
}
});
// ============================================================
// GET /api/rescue/ops/:sn/scenarios — 시나리오 목록
// ============================================================
router.get('/ops/:sn/scenarios', requireAuth, requirePermission('rescue', 'READ'), async (req, res) => {
try {
const sn = parseInt(req.params.sn as string, 10);
if (!isValidNumber(sn, 1, 999999)) {
res.status(400).json({ error: '유효하지 않은 구조 작전 번호' });
return;
}
const scenarios = await listScenarios(sn);
res.json(scenarios);
} catch (err) {
console.error('[rescue] 시나리오 목록 오류:', err);
res.status(500).json({ error: '시나리오 목록 조회 실패' });
}
});
export default router;